Files
ulicraft-server-v1/docker-compose.yml
Oier Bravo Urtasun 4c874e20ed refactor(ingress): extract caddy to its own compose file; add nginx path
Caddy is no longer in the base stack. Two ingress paths now:
- docker-compose.caddy.yml — LAN/air-gap; build-stack.sh adds it for all
  up modes + the prep pre-bake. Holds the mcnet auth./pack. aliases.
- docker-compose.nginx.yml — production behind the host's nginx: publishes
  drasl on 127.0.0.1:25585, points minecraft at the host (extra_hosts) over
  HTTPS for pack + authlib.

Base loses the caddy service and minecraft's caddy depends_on (re-added by
caddy.yml). Blessing Skin override now requires caddy.yml (it only swaps
caddy's core conf).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:35:07 +02:00

119 lines
4.9 KiB
YAML

# ──────────────────────────────────────────────────────────────────
# Ulicraft LAN-party stack — Minecraft 1.21.1 NeoForge + Drasl auth
# ──────────────────────────────────────────────────────────────────
# Single source of config: BASE_DOMAIN + HOST_LAN_IP in .env.
# DNS is provided by YOUR party DNS server — see tooling/dns-records.sh for the
# records to add (online vs airgap). A turnkey dnsmasq is available as an
# optional layer: docker-compose.dnsmasq.yml.
# - ingress is layered on, NOT in this base file: caddy (docker-compose.caddy.yml,
# LAN/air-gap, holds mcnet aliases) OR the host's nginx (docker-compose.nginx.yml
# + Let's Encrypt, production)
# - drasl handles auth (password login; NO Keycloak/OIDC in this stack)
# - packwiz pack is served by the ingress at pack.${BASE_DOMAIN}
# - minecraft installs mods via PACKWIZ_URL, authlib-injector -> auth.
# ──────────────────────────────────────────────────────────────────
services:
# NOTE: the HTTP(S) ingress is NOT in this base file.
# - LAN / air-gap: caddy (docker-compose.caddy.yml) — added by build-stack.sh
# - production: the HOST's nginx + Let's Encrypt (docker-compose.nginx.yml
# publishes drasl to localhost; nginx/ulicraft.conf.tmpl)
# Base alone (drasl + minecraft + mc-backup) is not a complete deployment —
# always layer one ingress file on top.
drasl:
image: unmojang/drasl:latest
container_name: drasl
restart: unless-stopped
# Internal-only: no published host port. Reached via Caddy at
# auth.${BASE_DOMAIN} (Caddy holds the network alias on mcnet).
volumes:
- ./drasl/config:/etc/drasl:ro
- drasl_state:/var/lib/drasl
networks:
- mcnet
# No env vars — config is the rendered ./drasl/config/config.toml
# (from config.toml.tmpl via tooling/render-config.sh).
minecraft:
image: itzg/minecraft-server:java21
container_name: minecraft
restart: unless-stopped
stdin_open: true
tty: true
ports:
- "25565:25565"
- "24454:24454/udp" # Simple Voice Chat, if used
environment:
EULA: "TRUE"
TYPE: "NEOFORGE"
VERSION: "1.21.1"
# Verify NEOFORGE_VERSION against projects.neoforged.net before deploy.
NEOFORGE_VERSION: "21.1.209" # pin a known-good build; update deliberately
# ── Memory / performance ────────────────────────────────────
INIT_MEMORY: "4G"
MAX_MEMORY: "10G" # 8 players + 100 mods comfortably
USE_AIKAR_FLAGS: "TRUE"
JVM_XX_OPTS: "-XX:+UseG1GC"
# ── Auth: offline mode + authlib-injector pointing at Drasl ─
ONLINE_MODE: "FALSE"
# mount authlib-injector.jar at /extras/authlib-injector.jar
JVM_OPTS: "-javaagent:/extras/authlib-injector.jar=http://auth.${BASE_DOMAIN}/authlib-injector"
# ── Server config ───────────────────────────────────────────
DIFFICULTY: "normal"
MODE: "survival"
MOTD: "Uli LAN party"
MAX_PLAYERS: "10"
VIEW_DISTANCE: "10"
SIMULATION_DISTANCE: "8"
ENFORCE_SECURE_PROFILE: "FALSE" # required for authlib-injector on 1.21+
ALLOW_FLIGHT: "TRUE" # many tech mods need this
# ── Mod source: packwiz pack served by the ingress ──────────
# http + caddy alias by default; the nginx override switches this to
# https + host-gateway (extra_hosts) for the production path.
PACKWIZ_URL: "http://pack.${BASE_DOMAIN}/pack.toml"
# ── RCON for remote admin ───────────────────────────────────
ENABLE_RCON: "TRUE"
RCON_PASSWORD: ${RCON_PASSWORD}
RCON_PORT: 25575
TZ: "Europe/Madrid"
volumes:
- mc_data:/data
- ./runtime:/extras:ro # authlib-injector.jar lives here
depends_on:
- drasl # ingress (caddy/nginx) is layered separately
networks:
- mcnet
# Optional: backups
mc-backup:
image: itzg/mc-backup
container_name: mc-backup
restart: unless-stopped
environment:
BACKUP_INTERVAL: "6h"
RCON_HOST: "minecraft"
RCON_PASSWORD: ${RCON_PASSWORD}
PRUNE_BACKUPS_DAYS: "14"
TZ: "Europe/Madrid"
volumes:
- mc_data:/data:ro
- ./backups:/backups
depends_on:
- minecraft
networks:
- mcnet
volumes:
drasl_state:
mc_data:
networks:
mcnet:
driver: bridge