# Crafty Controller - Minecraft szerver kezelő webes felülettel # Domain: ${SUBDOMAIN}.${DOMAIN} # Database: None (file-based) # RAM: ~256M (mem_limit: 2048M) | Pi-compatible: No # # Environment variables: # DOMAIN - Your domain (e.g., demo-felhom.eu) # CRAFTY_PASSWORD - felhom-generated initial admin password (seeded into default.json, see below) # # Initial admin password (seeding): Crafty's image ships # app/config_original/default.json = {"username":"admin","password":"crafty"} — only 6 chars, below # Crafty's 8-char minimum, so Crafty rejects it and generates an ugly random password into # default-creds.txt. The entrypoint below overwrites that template with a felhom-generated password # BEFORE the launcher runs; on fresh install the launcher copies it into the config volume and Crafty # creates the admin user with it. The seeded default.json stays in the volume as the source the # controller reads for the "Kezdeti belépési adatok" card (initial_credentials in .felhom.yml). services: crafty-controller: image: registry.gitlab.com/crafty-controller/crafty-4:4.10.7 container_name: crafty-controller restart: unless-stopped environment: - TZ=Europe/Budapest - CRAFTY_PASSWORD=${CRAFTY_PASSWORD} # Seed the felhom-generated admin password via Crafty's default.json template, then hand off to the # image's normal launcher (entrypoint /crafty/docker_launcher.sh, default cmd "-d -i"). $$ escapes # the compose interpolation so CRAFTY_PASSWORD is read from the container env at runtime. entrypoint: - /bin/sh - -c - | printf '{"username":"admin","password":"%s"}\n' "$${CRAFTY_PASSWORD}" > /crafty/app/config_original/default.json exec /crafty/docker_launcher.sh -d -i volumes: - crafty_backups:/crafty/backups - crafty_logs:/crafty/logs - crafty_servers:/crafty/servers - crafty_config:/crafty/app/config - crafty_import:/crafty/import # Publish the Minecraft Java game-port range (TCP) from the container to the guest so players can # connect to the game servers. The web UI (8443) stays behind Traefik via the labels below — do NOT # use network_mode: host (it would break that label routing). 11 ports = up to 11 Java servers; the # first server uses 25565, the rest 25566–25575. Bedrock (UDP 19132) is intentionally out of scope. ports: - "25565-25575:25565-25575" networks: - traefik-public deploy: resources: limits: memory: 2048M healthcheck: test: ["CMD", "/usr/bin/python3", "-c", "import socket,ssl; ssl._create_unverified_context().wrap_socket(socket.create_connection(('127.0.0.1',8443),timeout=3)).close()"] interval: 30s timeout: 5s retries: 3 start_period: 60s labels: - "traefik.enable=true" - "traefik.http.routers.crafty-controller.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)" - "traefik.http.routers.crafty-controller.entrypoints=websecure" - "traefik.http.routers.crafty-controller.tls=true" - "traefik.http.routers.crafty-controller.tls.certresolver=letsencrypt" - "traefik.http.services.crafty-controller.loadbalancer.server.port=8443" # Crafty serves self-signed HTTPS on :8443 (no plain-HTTP panel) — Traefik must speak https to the # backend and skip verifying the per-container self-signed cert (named transport defined in the # controller-managed traefik dynamic config; verification stays ON for all other backends). - "traefik.http.services.crafty-controller.loadbalancer.server.scheme=https" - "traefik.http.services.crafty-controller.loadbalancer.serverstransport=insecure-skip-verify@file" volumes: crafty_backups: crafty_config: crafty_import: crafty_logs: crafty_servers: networks: traefik-public: external: true