version: '3.8' services: pufferpanel: image: pufferpanel/pufferpanel:latest container_name: pufferpanel-seattle restart: unless-stopped environment: - PUID=1000 - PGID=1000 - TZ=America/New_York - PUFFERPANEL_WEB_HOST=0.0.0.0:8080 - PUFFERPANEL_DAEMON_CONSOLE_BUFFER=50 - PUFFERPANEL_DAEMON_CONSOLE_FORWARD=false - PUFFERPANEL_DAEMON_SFTP_HOST=0.0.0.0:5657 - PUFFERPANEL_DAEMON_AUTH_URL=http://localhost:8080 - PUFFERPANEL_DAEMON_AUTH_CLIENTID= - PUFFERPANEL_DAEMON_AUTH_CLIENTSECRET= volumes: - pufferpanel-config:/etc/pufferpanel - pufferpanel-data:/var/lib/pufferpanel - game-servers:/var/lib/pufferpanel/servers - /var/run/docker.sock:/var/run/docker.sock:ro ports: - "8080:8080" # Web interface - "5657:5657" # SFTP - "25565:25565" # Minecraft Java - "19132:19132/udp" # Minecraft Bedrock - "27015:27015" # Source games (GMod, L4D2) - "27015:27015/udp" - "7777:7777/udp" # Satisfactory - "15777:15777/udp" # Satisfactory query - "2456-2458:2456-2458/udp" # Valheim - "7000-7100:7000-7100/tcp" # Additional game ports networks: - game-network - proxy labels: # Nginx Proxy Manager labels - "traefik.enable=true" - "traefik.http.routers.pufferpanel.rule=Host(`games.vish.gg`)" - "traefik.http.routers.pufferpanel.tls=true" - "traefik.http.routers.pufferpanel.tls.certresolver=letsencrypt" - "traefik.http.services.pufferpanel.loadbalancer.server.port=8080" # Monitoring labels - "prometheus.io/scrape=true" - "prometheus.io/port=8080" - "prometheus.io/path=/metrics" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/api/self"] interval: 30s timeout: 10s retries: 3 start_period: 60s deploy: resources: limits: memory: 1G cpus: '1.0' reservations: memory: 512M cpus: '0.5' # Minecraft server template (managed by PufferPanel) minecraft-vanilla: image: itzg/minecraft-server:latest container_name: minecraft-vanilla-seattle restart: unless-stopped environment: - EULA=TRUE - TYPE=VANILLA - VERSION=LATEST - MEMORY=4G - JVM_OPTS=-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 - ENABLE_RCON=true - RCON_PASSWORD="REDACTED_PASSWORD" - DIFFICULTY=normal - MAX_PLAYERS=20 - MOTD=Homelab Minecraft Server - SPAWN_PROTECTION=16 - VIEW_DISTANCE=10 - SIMULATION_DISTANCE=10 volumes: - minecraft-data:/data - minecraft-backups:/backups ports: - "25566:25565" networks: - game-network depends_on: - pufferpanel deploy: resources: limits: memory: 6G cpus: '3.0' reservations: memory: 4G cpus: '2.0' healthcheck: test: ["CMD", "mc-health"] interval: 60s timeout: 10s retries: 3 start_period: 120s # Game server backup service game-backup: image: alpine:latest container_name: game-backup-seattle restart: unless-stopped environment: - TZ=America/New_York - BACKUP_SCHEDULE=0 2 * * * # Daily at 2 AM - RETENTION_DAYS=30 volumes: - game-servers:/game-servers:ro - minecraft-data:/minecraft-data:ro - /mnt/backups/game-servers:/backups - ./scripts/backup-games.sh:/backup-games.sh:ro command: | sh -c " apk add --no-cache dcron rsync gzip echo '0 2 * * * /backup-games.sh' | crontab - crond -f -l 2" networks: - game-network depends_on: - pufferpanel volumes: pufferpanel-config: driver: local driver_opts: type: none o: bind device: /opt/pufferpanel/config pufferpanel-data: driver: local driver_opts: type: none o: bind device: /opt/pufferpanel/data game-servers: driver: local driver_opts: type: none o: bind device: /opt/pufferpanel/servers minecraft-data: driver: local driver_opts: type: none o: bind device: /opt/minecraft/data minecraft-backups: driver: local driver_opts: type: none o: bind device: /mnt/backups/minecraft networks: game-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16 proxy: external: true name: nginx-proxy-manager_default