178 lines
6.3 KiB
YAML
178 lines
6.3 KiB
YAML
name: minecraft
|
|
|
|
services:
|
|
# ── Minecraft server (Fabric via itzg/minecraft-server) ─────────────────
|
|
mc:
|
|
image: itzg/minecraft-server:latest
|
|
container_name: mc
|
|
restart: unless-stopped
|
|
stop_grace_period: 2m
|
|
tty: false
|
|
stdin_open: false
|
|
environment:
|
|
EULA: "TRUE"
|
|
TYPE: ${SERVER_TYPE:-FABRIC}
|
|
VERSION: ${MC_VERSION:-26.2}
|
|
MEMORY: ${MC_MEMORY:-6G}
|
|
USE_AIKAR_FLAGS: "true"
|
|
|
|
# Offline mode + whitelist as the approval gate (see docs/auth-flow.md).
|
|
# enforce-secure-profile must be off or offline-launcher players are
|
|
# rejected before EasyAuth can even prompt them (EasyAuth issue #68).
|
|
ONLINE_MODE: "FALSE"
|
|
ENFORCE_SECURE_PROFILE: "FALSE"
|
|
ENABLE_WHITELIST: "TRUE"
|
|
ENFORCE_WHITELIST: "TRUE"
|
|
|
|
MOTD: ${MC_MOTD:-A cozy server for friends}
|
|
DIFFICULTY: ${MC_DIFFICULTY:-normal}
|
|
MAX_PLAYERS: ${MC_MAX_PLAYERS:-10}
|
|
VIEW_DISTANCE: ${MC_VIEW_DISTANCE:-10}
|
|
SIMULATION_DISTANCE: ${MC_SIMULATION_DISTANCE:-8}
|
|
SEED: ${MC_SEED:-}
|
|
SPAWN_PROTECTION: "0"
|
|
|
|
# RCON is only reachable inside the compose network (never published)
|
|
ENABLE_RCON: "true"
|
|
RCON_PASSWORD: ${RCON_PASSWORD:?generate with scripts/setup.sh}
|
|
|
|
# Server-side mods, auto-resolved for the current MC version on every start.
|
|
# ":beta" allows beta-typed builds for that project (EasyAuth publishes
|
|
# its 26.x builds as beta).
|
|
MODRINTH_PROJECTS: ${MODRINTH_PROJECTS:-fabric-api,easyauth:beta,spark,lithium,ferrite-core}
|
|
MODRINTH_DOWNLOAD_DEPENDENCIES: required
|
|
|
|
# Modpack support (leave empty for lean Fabric; see docs/mods-and-modpacks.md)
|
|
MODRINTH_MODPACK: ${MODRINTH_MODPACK:-}
|
|
|
|
# Enforce mod configs on every boot (proxy-protocol/TCPShield settings —
|
|
# see docs/tcpshield.md). Mods that rewrite their own config files can't
|
|
# clobber these: patches re-apply before each server start.
|
|
PATCH_DEFINITIONS: /patches/patch-set.json
|
|
|
|
TZ: ${TZ:-UTC}
|
|
ports:
|
|
- "${MC_PORT:-25565}:25565"
|
|
# BlueMap web map (only active if the bluemap mod is installed)
|
|
- "${MAP_PORT:-8100}:8100"
|
|
volumes:
|
|
- ./data/mc:/data
|
|
- ./config/patches:/patches:ro
|
|
mem_limit: ${MC_CONTAINER_MEM_LIMIT:-7g}
|
|
|
|
# ── Scheduled world backups (itzg/mc-backup) ─────────────────────────────
|
|
backup:
|
|
image: itzg/mc-backup:latest
|
|
container_name: mc-backup
|
|
restart: unless-stopped
|
|
environment:
|
|
BACKUP_INTERVAL: ${BACKUP_INTERVAL:-24h}
|
|
INITIAL_DELAY: 10m
|
|
PRUNE_BACKUPS_DAYS: ${BACKUP_RETENTION_DAYS:-7}
|
|
BACKUP_NAME: world
|
|
TAR_COMPRESS_METHOD: gzip
|
|
PAUSE_IF_NO_PLAYERS: "false"
|
|
RCON_HOST: mc
|
|
RCON_PORT: "25575"
|
|
RCON_PASSWORD: ${RCON_PASSWORD}
|
|
EXCLUDES: "*.tmp,cache,logs"
|
|
TZ: ${TZ:-UTC}
|
|
volumes:
|
|
- ./data/mc:/data:ro
|
|
- ./data/backups:/backups
|
|
depends_on:
|
|
mc:
|
|
condition: service_healthy
|
|
|
|
# ── Web management dashboard ─────────────────────────────────────────────
|
|
dashboard:
|
|
build: ./dashboard
|
|
image: minecraft-dashboard:local
|
|
container_name: mc-dashboard
|
|
restart: unless-stopped
|
|
environment:
|
|
PANEL_SESSION_SECRET: ${PANEL_SESSION_SECRET:?generate with scripts/setup.sh}
|
|
PANEL_ADMIN_PASSWORD: ${PANEL_ADMIN_PASSWORD:-}
|
|
RCON_HOST: mc
|
|
RCON_PORT: "25575"
|
|
RCON_PASSWORD: ${RCON_PASSWORD}
|
|
MC_CONTAINER: mc
|
|
BACKUP_CONTAINER: mc-backup
|
|
MC_DATA_DIR: /mc-data
|
|
BACKUPS_DIR: /backups
|
|
APP_DATA_DIR: /app-data
|
|
PROJECT_DIR: /project
|
|
REGISTRATION_WINDOW_MINUTES: ${REGISTRATION_WINDOW_MINUTES:-2}
|
|
DISCORD_WEBHOOK_URL: ${DISCORD_WEBHOOK_URL:-}
|
|
TZ: ${TZ:-UTC}
|
|
ports:
|
|
# LAN/VPN only — do not port-forward this on your router (docs/networking.md)
|
|
- "${DASHBOARD_PORT:-8080}:8080"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- ./data/mc:/mc-data
|
|
- ./data/backups:/backups
|
|
- ./data/dashboard:/app-data
|
|
- ./:/project
|
|
mem_limit: 512m
|
|
depends_on:
|
|
- mc
|
|
|
|
# ── Public READ-ONLY mirror (portfolio deployment) ───────────────────────
|
|
# Opt-in via the "public" profile: `docker compose --profile public up -d`.
|
|
# This service is safe to expose to the internet. It serves ONLY the
|
|
# exported feed and CANNOT touch the server: no Docker socket, no project
|
|
# dir, no RCON password, no .env secrets. See docs/public-mode.md.
|
|
dashboard-public:
|
|
build: ./dashboard
|
|
image: minecraft-dashboard:local
|
|
container_name: mc-dashboard-public
|
|
restart: unless-stopped
|
|
profiles: ["public"]
|
|
environment:
|
|
PUBLIC_READONLY: "1"
|
|
FEED_PATH: /feed/feed.db
|
|
TZ: ${TZ:-UTC}
|
|
ports:
|
|
- "${DASHBOARD_PUBLIC_PORT:-8090}:8080"
|
|
volumes:
|
|
# Feed only, read-only. Deliberately NO docker.sock / project / secrets.
|
|
- ./data/feed:/feed:ro
|
|
mem_limit: 256m
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/api/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
start_period: 20s
|
|
depends_on:
|
|
- feed-export
|
|
|
|
# ── Feed exporter sidecar ────────────────────────────────────────────────
|
|
# Snapshots the LAN panel DB (read-only) into the public feed on an interval.
|
|
# Reads only the panel DB; writes only the feed volume. No server access.
|
|
feed-export:
|
|
build: ./dashboard
|
|
image: minecraft-dashboard:local
|
|
container_name: mc-feed-export
|
|
restart: unless-stopped
|
|
profiles: ["public"]
|
|
working_dir: /app
|
|
entrypoint: ["/bin/sh", "-c"]
|
|
command:
|
|
- 'while true; do node scripts/export-feed.mjs || echo "export failed"; sleep ${FEED_INTERVAL_SECONDS:-30}; done'
|
|
environment:
|
|
SOURCE_DB: /app-data/craftdeck.db
|
|
FEED_PATH: /feed/feed.db
|
|
MC_VERSION: ${MC_VERSION:-}
|
|
SERVER_TYPE: ${SERVER_TYPE:-}
|
|
TZ: ${TZ:-UTC}
|
|
volumes:
|
|
- ./data/dashboard:/app-data:ro
|
|
- ./data/feed:/feed
|
|
mem_limit: 128m
|
|
healthcheck:
|
|
test: ["CMD", "test", "-f", "/feed/feed.db"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
start_period: 40s
|