Set Up a Modded Minecraft Server with Hermes Agent
Host modded Minecraft servers (CurseForge, Modrinth).
Written by Neura Market from the official Hermes Agent documentation for Minecraft Modpack Server. Commands, paths, and version numbers are reproduced from the source unchanged.
Read the official documentationThis skill walks you through standing up a modded Minecraft server from a server pack zip, covering NeoForge and Forge configuration, JVM tuning, firewall rules, and automated backups. It is for anyone who has a pack downloaded and wants a working, tuned server without hand-assembling every step. If you already run a vanilla server or use a managed host, you probably do not need it.
What it does
The skill turns a server pack archive into a running server. It starts by inspecting the pack to identify the mod loader, its version, and the Java release the pack expects. From there it installs the matching JRE, runs the pack's installer in install-only mode, accepts the EULA, and writes a server.properties tuned for modded play. It then sets JVM arguments in user_jvm_args.txt, opens the firewall port, and creates a clean launch script. Finally it adds a backup script and an hourly cron entry so the world is archived on a schedule.
You would reach for this when a friend sends you a CurseForge or Modrinth server pack and you want it running on a Linux or macOS box you control. It is also useful when you are migrating an existing world to a new pack version and need the configuration and backup pieces rebuilt consistently.
Before you start
The skill is optional and installed on demand. Its path is optional-skills/gaming/minecraft-modpack-server, version 1.0.0, authored by Teknium (teknium1) under the MIT license. It supports Linux and macOS.
The source assumes you have a server pack zip URL and a machine with enough RAM for the pack you chose. It also assumes you can run sudo for package installs and firewall changes, and that wget, unzip, tar, and crontab are available. The skill does not state minimum disk or CPU requirements, so size the host against the pack's own documentation.
Before any commands run, the skill asks you for a set of preferences: server name and MOTD, seed, difficulty, gamemode, online mode, expected player count, RAM allocation, view and simulation distance, PvP, whitelist, and backup frequency. Answer these up front. The source says to use sensible defaults if you do not care, but to always ask before generating the config. That matters because several of these values interact: online mode affects secure profiles, and player count drives both RAM and view distance.
Step 1: Download and inspect the pack
mkdir -p ~/minecraft-server
cd ~/minecraft-server
wget -O serverpack.zip "<URL>"
unzip -o serverpack.zip -d server
ls server/
This creates a working directory, downloads the pack, extracts it into server/, and lists the result. You are looking for startserver.sh, an installer jar for NeoForge or Forge, user_jvm_args.txt, and a mods/ folder. Read the start script to determine the mod loader type, its version, and the Java version the pack requires. Do this before installing Java so you pick the right release.
Step 2: Install Java
Match the JRE to the Minecraft version the pack targets:
- Minecraft 1.21+ needs Java 21:
sudo apt install openjdk-21-jre-headless - Minecraft 1.18 through 1.20 needs Java 17:
sudo apt install openjdk-17-jre-headless - Minecraft 1.16 and below needs Java 8:
sudo apt install openjdk-8-jre-headless
Verify the install with java -version. If the host already has a different JRE, confirm the one you just installed is the one that will run the server.
Step 3: Install the mod loader
Most server packs ship an install script. The source shows using an install-only environment variable so the installer runs without launching the server:
cd ~/minecraft-server/server
ATM10_INSTALL_ONLY=true bash startserver.sh
# Or for generic Forge packs:
# java -jar forge-*-installer.jar --installServer
This step downloads libraries and patches the server jar. The exact variable name depends on the pack; the source notes that packs expose their own environment variables, with ATM10 using ATM10_JAVA, ATM10_RESTART, and ATM10_INSTALL_ONLY as examples. Check the pack's start script for the names it honors.
Step 4: Accept the EULA
echo "eula=true" > ~/minecraft-server/server/eula.txt
Minecraft will not start until the EULA file contains this value. Writing it directly is the fastest path on a headless host.
Step 5: Configure server.properties
These are the settings the source calls out for modded and LAN use:
motd=\u00a7b\u00a7lServer Name \u00a7r\u00a78| \u00a7aModpack Name
server-port=25565
online-mode=true # false for LAN without Mojang auth
enforce-secure-profile=true # match online-mode
difficulty=hard # most modpacks balance around hard
allow-flight=true # REQUIRED for modded (flying mounts/items)
spawn-protection=0 # let everyone build at spawn
max-tick-time=180000 # modded needs longer tick timeout
enable-command-block=true
Two of these are non-negotiable for modded play. allow-flight=true prevents players from being kicked when a mod grants flight. max-tick-time=180000 gives the server room for the long ticks that world generation produces. If you set online-mode=false, also set enforce-secure-profile=false, or clients will be rejected.
Performance settings scale with hardware and player count. The source gives three starting points:
# 2 players, beefy machine:
view-distance=16
simulation-distance=10
# 4-6 players, moderate machine:
view-distance=10
simulation-distance=6
# 8+ players or weaker hardware:
view-distance=8
simulation-distance=4
Pick the row that matches your expected load, then adjust after you see how the server behaves.
Step 6: Tune JVM arguments
Edit user_jvm_args.txt and scale RAM to the mod count and player count. The source's rule of thumb: 100 to 200 mods take 6 to 12GB, 200 to 350+ mods take 12 to 24GB, and you should leave at least 8GB free for the OS and other tasks.
-Xms12G
-Xmx24G
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:+AlwaysPreTouch
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20
-XX:G1HeapWastePercent=5
-XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15
-XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem
-XX:MaxTenuringThreshold=1
These are G1GC tuning flags aimed at reducing pause times on a modded heap. Keep the block together rather than cherry-picking lines unless you know why you are changing one.
Step 7: Open the firewall
sudo ufw allow 25565/tcp comment "Minecraft Server"
Confirm the rule with sudo ufw status | grep 25565. If you changed server-port in server.properties, open that port instead.
Step 8: Create a launch script
cat > ~/start-minecraft.sh << 'EOF'
#!/usr/bin/env bash
cd ~/minecraft-server/server
java @user_jvm_args.txt @libraries/net/neoforged/neoforge/<VERSION>/unix_args.txt nogui
EOF
chmod +x ~/start-minecraft.sh
This gives you a clean launch path without the pack's auto-restart loop. Replace <VERSION> with the NeoForge version from your install. For Forge rather than NeoForge, the args file path differs, so check startserver.sh for the exact path.
Step 9: Set up automated backups
cat > ~/minecraft-server/backup.sh << 'SCRIPT'
#!/usr/bin/env bash
SERVER_DIR="$HOME/minecraft-server/server"
BACKUP_DIR="$HOME/minecraft-server/backups"
WORLD_DIR="$SERVER_DIR/world"
MAX_BACKUPS=24
mkdir -p "$BACKUP_DIR"
[ ! -d "$WORLD_DIR" ] && echo "[BACKUP] No world folder" && exit 0
TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_FILE="$BACKUP_DIR/world_${TIMESTAMP}.tar.gz"
echo "[BACKUP] Starting at $(date)"
tar -czf "$BACKUP_FILE" -C "$SERVER_DIR" world
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "[BACKUP] Saved: $BACKUP_FILE ($SIZE)"
BACKUP_COUNT=$(ls -1t "$BACKUP_DIR"/world_*.tar.gz 2>/dev/null | wc -l)
if [ "$BACKUP_COUNT" -gt "$MAX_BACKUPS" ]; then
REMOVE=$((BACKUP_COUNT - MAX_BACKUPS))
ls -1t "$BACKUP_DIR"/world_*.tar.gz | tail -n "$REMOVE" | xargs rm -f
echo "[BACKUP] Pruned $REMOVE old backup(s)"
fi
echo "[BACKUP] Done at $(date)"
SCRIPT
chmod +x ~/minecraft-server/backup.sh
The script archives the world folder, records the archive size, and prunes older backups beyond MAX_BACKUPS. Add the hourly cron entry:
(crontab -l 2>/dev/null | grep -v "minecraft/backup.sh"; echo "0 * * * * $HOME/minecraft-server/backup.sh >> $HOME/minecraft-server/backups/backup.log 2>&1") | crontab -
This replaces any existing entry for the backup script and schedules it at the top of every hour, appending output to a log file.
When not to use it
The source does not name alternatives or exclusions. It is scoped to server packs delivered as a zip, so a hand-built mod list or a managed hosting provider falls outside what it covers.
Limits and gotchas
The source lists several pitfalls worth reading before your first launch. allow-flight=true is mandatory for modded servers; without it, mods that grant flight will kick players. max-tick-time=180000 or higher is needed because modded servers often have long ticks during world generation. The first startup is slow, several minutes for large packs, and "Can't keep up!" warnings on first launch are normal and settle after initial chunk generation. If you set online-mode=false, set enforce-secure-profile=false as well or clients get rejected. The pack's startserver.sh often includes an auto-restart loop, which is why the skill builds a separate launch script. Deleting the world/ folder regenerates it with a new seed. Some packs expose environment variables that change behavior, such as ATM10_JAVA, ATM10_RESTART, and ATM10_INSTALL_ONLY.
Verifying the server
Use pgrep -fa neoforge or pgrep -fa minecraft to check whether the process is running. Follow the log with tail -f ~/minecraft-server/server/logs/latest.log. The server is ready when the log shows "Done (Xs)!". To test the connection, have a player add the server IP in the Multiplayer menu.
What pairs with it
The source does not list related skills. In practice, pair this with whatever skill you use for host provisioning and process supervision, since the launch script and cron entry assume the server runs on a machine you manage directly.