Files
ulicraft-server-v1/plan/05-minecraft.md
2026-05-24 04:03:42 +02:00

2.3 KiB

Minecraft server — itzg NeoForge + offline launch

Summary

itzg/minecraft-server:java21, NeoForge 1.21.1, offline-mode + authlib-injector pointing at drasl. Mods via PACKWIZ_URL. The challenge: itzg re-resolves Mojang version metadata on every boot (issue #2340), so it cannot air-gap-boot in TYPE=NEOFORGE mode. Solved with a pre-bake + custom-launch switch.

Offline strategy (two phases)

Phase 1 — pre-bake (online, once):

TYPE=NEOFORGE, VERSION=1.21.1, NEOFORGE_VERSION=21.1.x
PACKWIZ_URL=http://packwiz.ulicraft.local/pack.toml

Boot once with internet → installs MC + NeoForge + libraries + server mods into the mc_data volume, generates NeoForge's launch args/run.sh.

Phase 2 — offline launch (party): Switch to TYPE=CUSTOM + CUSTOM_SERVER=<container path> pointing at the already-installed NeoForge launcher in /data. A container path (not URL) means no download, no Mojang resolution → boots air-gapped, survives restarts.

OPEN: NeoForge 1.21.1 launches via @libraries/.../unix_args.txt / run.sh, not a single fat jar. Exact CUSTOM_SERVER target + any EXTRA_ARGS must be verified against a real pre-baked volume. Tracked as a task.

Auth / config (carry-over)

ONLINE_MODE=FALSE
ENFORCE_SECURE_PROFILE=FALSE                 # pairs with drasl SignPublicKeys=false
JVM_OPTS=-javaagent:/extras/authlib-injector.jar=http://auth.${BASE_DOMAIN}/authlib-injector

authlib URL uses the auth subdomain; resolves internally via Caddi alias. (Server still needs the agent even though Fjord clients have it built in.)

Memory: INIT_MEMORY 4G, MAX_MEMORY 10G, USE_AIKAR_FLAGS TRUE. RCON enabled for mc-backup.

Tasks

  • Compose: switch authlib URL to http://auth.${BASE_DOMAIN}/authlib-injector
  • Compose: replace MODRINTH_PROJECTS with PACKWIZ_URL (packwiz subdomain)
  • Mount renamed ./runtime (was ./extras) for authlib-injector.jar
  • depends_on: drasl + caddy (pack served before server installs)
  • Pre-bake the volume online; snapshot it
  • Identify exact NeoForge launch target for TYPE=CUSTOM / CUSTOM_SERVER
  • Add a documented "offline mode" compose override (docker-compose.offline.yml?)
  • Verify air-gapped boot: cut internet, restart container, server comes up
  • Confirm ENFORCE_SECURE_PROFILE=FALSE ↔ drasl SignPublicKeys=false