Deploy and manage modded Minecraft servers like a pro. Dockerized, automated, and optimized infrastructure for Ragnamod VII, ATM9, and beyond.
One-command setup · Automatic backups · Optimized JVM flags · Oracle Cloud ARM ready
| Feature | Details |
|---|---|
| 🐳 Docker-first | One compose service, one custom image, predictable runtime |
| 🧰 Bootstrap script | install.sh installs Docker, cron, Java, and creates .env |
| 📦 Supported modpack flow | Automatic install only for MODPACK_TYPE=custom with MODPACK_URL; otherwise use manual server files |
| 💾 Automated backups | scripts/backup.sh runs on the cron schedule from .env and prunes old archives |
| 🏃 JVM and container memory split | MEMORY controls JVM heap, MEMORY_LIMIT controls the container limit |
| 🩺 Real healthcheck | RCON-based healthcheck with a startup grace period |
| 🔁 Restart policy | restart: unless-stopped for crash recovery |
| 📜 Log rotation | Host log rotation for backup output |
| 🛠️ Makefile shortcuts | make start / stop / restart / logs / backup / setup |
modded-minecraft-server-infra/
├── docker/
│ ├── Dockerfile # Custom image (itzg/minecraft-server base)
│ └── modpack-entrypoint.sh # Automatic modpack bootstrap logic
├── scripts/
│ ├── start.sh # Start the server
│ ├── stop.sh # Graceful RCON stop
│ ├── restart.sh # Stop + start
│ ├── logs.sh # Tail container logs
│ ├── backup.sh # Snapshot world data + prune old backups
│ └── setup-modpack.sh # Interactive modpack install wizard
├── config/
│ ├── server.properties # Minecraft server config template
│ └── jvm-flags.txt # JVM flag reference / documentation
├── server-files/ # Runtime server data (gitignored)
├── backups/ # Backup archives (gitignored)
├── docker-compose.yml # Service definition
├── install.sh # System bootstrap (Docker, Java, cron)
├── Makefile # Developer-friendly shortcuts
├── .env.example # Configuration template
└── README.md
The repository is intentionally small and split by responsibility:
docker/builds the runtime image and contains the entrypoint that installs a custom server pack whenMODPACK_TYPE=customandMODPACK_URLis set.scripts/contains the host-side lifecycle tools for install, start, stop, restart, logs, backups, and modpack setup.config/holds static server configuration files that are mounted into the container.server-files/is the live Minecraft working directory on the host and is gitignored.backups/stores timestamped compressed archives and is gitignored.
The container mounts server-files/ at /data and backups/ at /backups. Docker handles restarts, while the healthcheck verifies the server can answer RCON commands after startup.
This repository is validated for a straightforward deployment on Ubuntu 22.04 or similar Linux hosts with Docker Compose v2:
- Run
sudo bash install.sh. - Copy
.env.exampleto.envand setRCON_PASSWORD,MEMORY,MEMORY_LIMIT, andBACKUP_CRON. - Either set
MODPACK_TYPE=customwith a directMODPACK_URL, or manually extract a server pack intoserver-files/. - Run
make start. - Check
make logsuntil the server reports healthy startup.
That is the deployment path this repo is designed to support. Anything else should be treated as an operator choice, not an implied feature.
| Requirement | Minimum | Recommended |
|---|---|---|
| OS | Ubuntu 22.04 | Ubuntu 22.04 LTS (ARM64 or x86_64) |
| RAM | 8 GB | 12–16 GB |
| CPU | 4 vCPU | 6+ vCPU |
| Disk | 20 GB | 50 GB SSD |
| Docker | 24.x | latest |
| Docker Compose | v2 | v2 |
Oracle Cloud Free Tier: The Ampere A1 instance (4 OCPUs / 24 GB RAM) is an excellent free option.
git clone https://github.com/ALevesqueDev/modded-minecraft-server-infra.git
cd modded-minecraft-server-infrasudo bash install.shRe-login or run
newgrp dockerafter this step so your user can run Docker withoutsudo.
cp .env.example .env
nano .env # or: vim .envAt minimum, change:
RCON_PASSWORD=your_secure_password_here
MEMORY=10G # set to ~75 % of available RAM
MEMORY_LIMIT=14G # leave headroom above the JVM heapmake setupUse the wizard to either download and extract a direct server-pack URL once or follow the manual extraction path. For Ragnamod VII, ATM9, and most CurseForge packs, the manual path is the realistic default unless you already have a direct server-pack URL.
make startmake logsWait for Done! For help, type "help" – then connect to your-ip:25565.
This is the only fully automated path in the current codebase.
- Obtain a direct download URL for the server-pack zip.
- Set it in
.env:
MODPACK_TYPE=custom
MODPACK_URL=https://mediafilez.forgecdn.net/files/XXXX/XXXX/RagnamodVII-ServerPack-X.X.zip- Run
make start.
On first boot, the entrypoint downloads the archive into /data, extracts it, and records a sentinel file so it does not reinstall on subsequent restarts.
If the URL is not a direct archive or cannot be fetched without a browser login, automatic install will fail fast and you should use the manual path.
- Download the server-pack zip for your chosen pack.
- Extract the zip directly into
./server-files/:
unzip RagnamodVII-ServerPack-X.X.zip -d ./server-files/- Your
server-files/directory should now contain aforge-*.jar,server.jar, orstart.sh. - Leave
MODPACK_TYPEas-is or set any descriptive value you want; the runtime will simply detect the files and continue. - Run
make start.
💡 The
make setupwizard now reflects these two paths only: custom URL or manual extraction.
| Variable | Default | Description |
|---|---|---|
MINECRAFT_VERSION |
1.20.1 |
Minecraft game version |
MODPACK_TYPE |
ragnamod7sky |
Runtime label; set to custom to enable automatic download |
MODPACK_URL |
(empty) | Direct download URL used only when MODPACK_TYPE=custom |
MEMORY |
8G |
JVM heap size (-Xmx / -Xms) |
MEMORY_LIMIT |
14G |
Docker container memory limit |
JAVA_FLAGS |
(empty) | Override full JVM flags string |
SERVER_PORT |
25565 |
Minecraft TCP/UDP port |
RCON_PORT |
25575 |
RCON port |
RCON_PASSWORD |
changeme… |
Change this! |
DIFFICULTY |
normal |
Game difficulty |
MAX_PLAYERS |
8 |
Max concurrent players |
VIEW_DISTANCE |
8 |
Chunk view distance |
SIMULATION_DISTANCE |
6 |
Simulation distance |
ONLINE_MODE |
true |
Mojang auth (set false for offline LAN) |
OPS |
(empty) | Comma-separated operator usernames |
WHITELIST |
(empty) | Comma-separated allowed usernames |
ENABLE_WHITELIST |
FALSE |
Enable whitelist enforcement |
BACKUP_RETENTION |
7 |
Number of backup archives to keep |
BACKUP_CRON |
0 3 * * * |
Cron schedule for backups on the host (written to /etc/cron.d/minecraft-server-backup) |
BACKUP_DIR |
/backups |
Host-side backup destination |
| Command | Description |
|---|---|
make start |
Start the server in detached mode |
make stop |
Gracefully stop (RCON save-all + stop) |
make restart |
Stop then start |
make logs |
Tail live container logs |
make status |
Show container health & resource usage |
make backup |
Trigger a manual backup immediately |
make shell |
Open a bash shell inside the container |
make rcon |
Open an interactive RCON console |
make setup |
Re-run the modpack install wizard |
make clean |
Remove stopped containers & dangling images |
make help |
List all available commands |
docker compose up -d # start
docker compose down # stop
docker compose logs -f # logs
docker compose ps # status
docker compose exec mc rcon-cli --password <pw> list # list online playersGitHub Actions runs a small validation workflow on every push and pull request:
shellcheckforinstall.sh,scripts/*.sh, anddocker/modpack-entrypoint.shdocker compose config -qfordocker-compose.yml
This catches shell syntax mistakes and compose interpolation issues before they reach a host.
- Automatic modpack installation only supports direct archive URLs. CurseForge pages, launcher pages, and browser-gated links are not supported.
- The healthcheck is intentionally simple and requires RCON to answer before the container is marked healthy.
- Backup pruning keeps the current timestamp-based naming convention and only deletes files that still match that format.
Before using this on a real server, verify the full path on the target host:
- Run
sudo bash install.shand confirm/etc/cron.d/minecraft-server-backupexists. - Start with either
MODPACK_TYPE=customplus a directMODPACK_URL, or a manually extractedserver-files/directory. - Run
make startand wait for a healthy status. - Trigger
make backupand confirm a new archive appears inbackups/. - Restart once with
make restartto confirm the startup wait and graceful stop path.
Backups are managed by scripts/backup.sh:
- Creates a timestamped
.tar.gzarchive ofserver-files/(world data, configs, mods). - Excludes
logs/andcrash-reports/to keep archive sizes small. - Sends a RCON
save-allbefore archiving to flush world data. - Auto-prunes old archives beyond
BACKUP_RETENTION(default: 7). - Installed as a cron job using the
BACKUP_CRONvalue from.env. - Logs to
/var/log/mc-backup.logand the log file is rotated bylogrotate.
make backup# Stop the server first
make stop
# Extract the archive (replace timestamp)
tar -xzf backups/mc_backup_20240101_030000.tar.gz
# Start again
make startBackup archives are stored in ./backups/ on the host (gitignored).
If you change BACKUP_CRON after the initial bootstrap, rerun sudo bash install.sh to refresh the cron entry.
Set MEMORY to approximately 75 % of your host's total RAM. Examples:
| Host RAM | Recommended MEMORY |
|---|---|
| 8 GB | 6G |
| 12 GB | 9G |
| 16 GB | 12G |
| 24 GB (A1) | 18G |
The image uses USE_AIKAR_FLAGS=true by default, which applies the community-standard G1GC flags for Minecraft servers. For large modpacks, also consider:
JAVA_FLAGS=-XX:+UseZGC -XX:+ZGenerational
⚠️ ZGC requires Java 21+. The default image uses Java 17.
Lower these in .env for better TPS on CPU-limited hosts:
VIEW_DISTANCE=6
SIMULATION_DISTANCE=4Use a plugin like Chunky to pre-generate the world radius before opening to players.
The modpack files are missing from server-files/. Either set MODPACK_TYPE=custom with a valid MODPACK_URL, or manually extract the server pack zip into ./server-files/.
The URL is not a direct server-pack archive or it requires authentication that the container cannot supply. Switch to the manual path or provide a direct CDN link.
chmod +x scripts/*.sh install.sh- Check RAM:
make status→ ensure memory isn't being swapped. - Reduce
VIEW_DISTANCEandSIMULATION_DISTANCEin.env. - Check for runaway entities with
/forge tps.
# Check UFW (Ubuntu firewall)
sudo ufw allow 25565/tcp
sudo ufw allow 25565/udp
# Oracle Cloud also requires a Security List rule for port 25565The server may still be starting. RCON is only available after the world loads. Allow 2–5 minutes for heavy modpacks.
docker compose logs mc --tail=50Look for OOM kills (exit code 137) – increase MEMORY_LIMIT in .env or reduce MEMORY so the JVM leaves enough room for the container.
Re-run sudo bash install.sh after updating BACKUP_CRON in .env, then confirm the user crontab contains the backup command.
MIT © ALevesqueDev
Made with ☕ and too many Minecraft hours.