setupmc.com

Run a CurseForge Modpack with itzg/minecraft-server and Docker Compose

Deploy a CurseForge modpack with AUTO_CURSEFORGE, pin its file ID, protect the API key, handle manual downloads, and validate loader and client compatibility.

Mods & Plugins
setupmc.com Team

Need a cleaner Java baseline?

Generate a Java Compose setup before you keep patching by hand

If you are still refining the Java server baseline, use the Java configurator and then return to the guides for the next issue.

Open Java configurator

Keep pack, loader, Java, and memory together

A CurseForge pack declares its Minecraft version, mod loader, mods, and configuration. AUTO_CURSEFORGE reads that manifest and installs the matching Forge or Fabric loader automatically.

Do not independently choose a newer loader because it looks preferable. Pin one tested modpack file and use the Java and memory requirements published for that release.

Prerequisites

  • a CurseForge pack with server support
  • the pack's normal file ID, not its separate server-file download
  • enough RAM and disk for the selected pack
  • the Java image tag required by its Minecraft version
  • the same pack release on test clients
  • a complete backup before importing an existing world

Compose baseline with a pinned file

The file ID below is the pinned ATM8 example used by the itzg documentation. It is intentionally an older, concrete example; replace the slug, file ID, Java tag, and memory together for your chosen pack.

services:
  mc:
    image: itzg/minecraft-server:java17
    restart: unless-stopped
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      TYPE: AUTO_CURSEFORGE
      CF_SLUG: all-the-mods-8
      CF_FILE_ID: "4248390"
      CF_API_KEY_FILE: /run/secrets/cf_api_key
      MEMORY: 6G
    mem_limit: 8g
    volumes:
      - ./data:/data
      - ./downloads:/downloads:ro
    secrets:
      - cf_api_key

secrets:
  cf_api_key:
    file: ./cf_api_key.secret

Create cf_api_key.secret beside Compose, restrict its host permissions, and keep it out of version control. A personal key is optional while the image ships a key; if you do not supply one, remove both CF_API_KEY_FILE and the secret declarations.

Validate without exposing the secret value:

docker compose config
docker compose pull mc

Why the file ID matters

Without CF_FILE_ID, the image locates the newest pack file again on a later startup. That makes an ordinary restart an implicit pack and loader upgrade.

You can pin with a specific file URL, CF_FILE_ID, or CF_FILENAME_MATCHER. A numeric file ID is the clearest operational record. Do not select the pack's separately published server file: it normally lacks the CurseForge manifest required by AUTO_CURSEFORGE.

First start on empty data

Use a fresh ./data for the first installation:

mkdir -p data downloads
docker compose up -d
docker compose logs -f mc

The initial start downloads many artifacts and can take considerably longer than Paper. Wait for the server-ready message. If it fails, preserve the first error before the restart policy hides it behind repeated logs.

Handle projects that require manual downloads

CurseForge authors can prohibit third-party automated downloads. The image then logs a “Mods Need Download” list.

For each listed project:

  1. open the provided page in a browser
  2. download the exact requested file
  3. copy it into the host ./downloads directory
  4. run docker compose up -d mc again

Do not replace this with a guessed curl URL. The itzg documentation explicitly requires browser downloads for these restricted files.

Validate the installed pack

docker compose exec mc rcon-cli version
docker compose exec mc sh -c 'find /data/mods -maxdepth 1 -type f -name "*.jar" | wc -l'
docker compose logs --since=20m mc

Then join with the exact matching client pack and check custom blocks, items, dimensions, recipes, and a reconnect. Create the first backup after this validation.

Client-only files and synchronization

Use CF_EXCLUDE_MODS only for projects incorrectly delivered to the server, and CF_FORCE_INCLUDE_MODS only when metadata incorrectly marks a required server mod as client-only. Report the metadata problem upstream.

CF_FORCE_SYNCHRONIZE: "TRUE" is a troubleshooting switch, not a harmless permanent default. Synchronization intentionally reconciles installed files with the selected pack. Back up first and remove the flag when the correction is complete.

Upgrade and roll back the pack

Treat a new file ID as a server update:

  1. make an application-aware backup and stopped full copy
  2. change only CF_FILE_ID
  3. start under supervision
  4. test with the matching client
  5. restore the previous Compose and /data together if validation fails

Follow the safe Docker update and rollback runbook. Never start an older pack against world data already migrated by the newer one.

Troubleshooting

SymptomLikely causeFix
Manifest missingA server file was selectedPin the normal modpack file instead
No matching fileSlug and file ID do not belong togetherCopy both from the same pack release
Manual-download list appearsDistribution is restrictedDownload exact files in a browser into /downloads
Unsupported class versionWrong Java imageUse the pack's required Java release
Exit 137 during startupHeap/container/host memory is insufficientUse the OOMKilled runbook
Client cannot joinPack or loader release differsInstall the exact same client pack file

Next steps

Frequently asked questions

Short answers to the questions that usually come up while working through this topic.