On this page
Hosting a Minecraft server for your friends or kids is one of the most satisfying first projects a homelab can take on — and running it in an LXC container is tidier than a bare VM: near-native performance, isolated from the rest of the cluster, snapshotable before every risky mod update, and easy to migrate to another node. This guide covers Fabric 1.20.1 with the performance mod stack that makes a modest CPU-only machine genuinely playable for small groups.
If you’re building the hardware from scratch, the HP EliteDesk 705 G4 mini covered in the cluster post handles 8 concurrent players with headroom to spare.
Performance target
Two numbers tell you whether a Minecraft server is healthy. TPS (ticks per second) is the game’s heartbeat — 20.0 is perfect, and anything sustained below ~18 feels laggy to players. MSPT (milliseconds per tick) is how long each tick takes to compute; the server has a 50 ms budget per tick, so lower is better and anything under ~25 ms leaves comfortable headroom. On a Ryzen 5 2400G with 4 GB RAM allocated to the container and 3 GB to the JVM, expect:
| Metric | Idle | 4 players | 8 players |
|---|---|---|---|
| TPS | 20.0 | 19.8 | 18.5–20.0 |
| MSPT | 4–6ms | 8–14ms | 14–22ms |
| RAM used | 800 MB | 1.4 GB | 2.1 GB |
| CPU % | 5–8% | 20–35% | 45–65% |
The mods below get you from stock’s 12–18 MSPT at 4 players down to 8–14ms.
Mod stack
| Mod | What it fixes |
|---|---|
| Fabric API | Required loader for all Fabric mods |
| Lithium | Server-side optimizations: physics, collision, chunk loading |
| Starlight | Complete rewrite of the lighting engine (~30% faster chunk load) |
| Carpet | Admin utilities: tick control, spawn tracking, /log profiling |
| Carpet-Extra | Additional Carpet features: block update optimizations |
Skip Sodium/Iris/Indium — those are client-side rendering mods. Server performance mods are Lithium and Starlight. Clients can use any mods they want regardless of what’s on the server.
Starlight’s author archived the project in March 2024 and will not update it beyond 1.20.1. For this guide’s target (1.20.1) it works perfectly. If you upgrade to 1.21+, replace Starlight with ScalableLux, its community-maintained successor.
Task 1: Create the container
The commands below use example values: container ID 104, node name pvelab03, and IP 10.0.0.76 — substitute your own free container ID, node, and LAN address everywhere they appear (including the pct commands and the client connect address near the end). If a value looks specific to one machine, it’s a placeholder to change — not a literal to copy.
| Field | Value |
|---|---|
| VMID | 104 |
| Hostname | minecraft |
| OS | Ubuntu 24.04 LXC (unprivileged) |
| Host | pvelab03 |
| IP | 10.0.0.76 (or your choice) |
| Cores | 4 |
| RAM | 4096 MB |
| Disk | 20 GB |
4 GB RAM is fine for up to 10 players. For larger servers or many loaded chunks, increase to 8 GB (DDR4 SO-DIMMs on Amazon) and set JVM to -Xmx6G.
Task 2: Install Java and create the server
Minecraft 1.20.1 requires Java 17+. Java 21 performs better with virtual threads and the Shenandoah GC:
apt-get update && apt-get install -y curl wget jq
apt-get install -y openjdk-21-jre-headless
java -version
# → openjdk version "21.0.x" ...
useradd -m -s /bin/bash minecraft
mkdir -p /srv/minecraft/{server,mods,backups}
chown -R minecraft:minecraft /srv/minecraft
cd /srv/minecraft/server
wget -q "https://meta.fabricmc.net/v2/versions/installer" -O - | \
jq -r '.[0].url' | xargs wget -q -O fabric-installer.jar
# Bootstrap the server jar (Fabric loader 0.16.0, Minecraft 1.20.1)
su - minecraft -c "java -jar /srv/minecraft/server/fabric-installer.jar server \
-mcversion 1.20.1 \
-loader 0.16.0 \
-downloadMinecraft \
-dir /srv/minecraft/server"
echo "eula=true" > /srv/minecraft/server/eula.txt
chown minecraft:minecraft /srv/minecraft/server/eula.txt
Task 3: Install performance mods
Download the 1.20.1-compatible versions from Modrinth:
MODS_DIR="/srv/minecraft/server/mods"
# Lithium — check Modrinth for current 1.20.1 build
wget -q "https://cdn.modrinth.com/data/gvQqBUqZ/versions/FT.../lithium-fabric-mc1.20.1-0.11.2.jar" \
-O "$MODS_DIR/lithium.jar"
# Starlight — Fabric 1.20.1
wget -q "https://cdn.modrinth.com/data/H8CaAYZC/versions/.../starlight-1.1.2+fabric.dce1c55.jar" \
-O "$MODS_DIR/starlight.jar"
# Carpet
wget -q "https://github.com/gnembon/fabric-carpet/releases/download/1.4.112/fabric-carpet-1.20.1-1.4.112+v230628.jar" \
-O "$MODS_DIR/carpet.jar"
chown minecraft:minecraft "$MODS_DIR"/*.jar
Mod downloads change URLs as new versions release. Before running: check the Modrinth project page for each mod, filter by Minecraft 1.20.1 + Fabric, and grab the direct download URL from the latest compatible release.
Task 4: Tune the JVM and create the systemd service
The flags below use Shenandoah (low-pause GC), pin threads to avoid cross-NUMA latency, and pre-touch memory:
cat > /srv/minecraft/server/start.sh {'<<'} 'EOF'
#!/bin/bash
cd /srv/minecraft/server
exec java \
-Xms2G -Xmx3G \
-XX:+UseShenandoahGC \
-XX:ShenandoahGCHeuristics=adaptive \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:+UseNUMA \
-XX:+PerfDisableSharedMem \
-Dfml.ignorePatchDiscrepancies=true \
-jar fabric-server-launch.jar --nogui
EOF
chmod +x /srv/minecraft/server/start.sh
chown minecraft:minecraft /srv/minecraft/server/start.sh
cat > /etc/systemd/system/minecraft.service {'<<'} 'EOF'
[Unit]
Description=Minecraft Fabric Server 1.20.1
After=network.target
[Service]
User=minecraft
WorkingDirectory=/srv/minecraft/server
ExecStart=/srv/minecraft/server/start.sh
ExecStop=/bin/kill -s SIGTERM $MAINPID
Restart=on-failure
RestartSec=10
StandardInput=null
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now minecraft
journalctl -u minecraft -f
# Wait for: [Server thread/INFO]: Done (15.234s)! For help, type "help"
Once live, connect with Minecraft client to 10.0.0.76:25565. In-game, verify TPS with Carpet:
/carpet setDefault commandLog true
/log tps
# → TPS: 20.0, MSPT: 6.24
Task 5: Automatic backups
cat > /srv/minecraft/backups/backup.sh {'<<'} 'EOF'
#!/bin/bash
BACKUP_DIR="/srv/minecraft/backups"
WORLD_DIR="/srv/minecraft/server/world"
DATE=$(date +%Y%m%d_%H%M)
TAR="/srv/minecraft/backups/world_$(date +%Y%m%d_%H%M).tar.gz"
# Tell players about the backup
# (works if minecraft-send-command tool is installed, skip otherwise)
tar -czf "$TAR" -C /srv/minecraft/server world
echo "Backup: $TAR ($(du -sh $TAR | cut -f1))"
# Keep last 7 daily backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
EOF
chmod +x /srv/minecraft/backups/backup.sh
Add to root crontab:
echo "0 3 * * * /srv/minecraft/backups/backup.sh >> /var/log/minecraft-backup.log 2>&1" | crontab -
Proxmox snapshot for pre-update safety
Before any Minecraft or mod update:
pct snapshot 104 pre-update-$(date +%Y%m%d) \
--description "Before Minecraft/mod update"
# To roll back if the update breaks things:
pct rollback 104 pre-update-20260705
The snapshot includes the entire container filesystem — world data, mods, configs. Rollback takes under 30 seconds.
Server management reference
# View live log
journalctl -u minecraft -f
# Restart (saves world first via SIGTERM → ExecStop)
pct exec 104 -- systemctl restart minecraft
# Check memory usage
pct exec 104 -- ps aux | grep java
# Emergency stop (only if systemctl fails)
pct exec 104 -- kill -9 $(pgrep -f fabric-server)
# View backup list
pct exec 104 -- ls -lh /srv/minecraft/backups/
The complete Proxmox cluster setup supporting this server — including Tailscale for remote access and Grafana alerts for monitoring the container’s RAM and CPU — is covered in the other posts in this series.
Related posts:
- Proxmox LXC Networking: Bridges, VLANs, and Static IPs — give the server container a static IP your friends can reach
- Tailscale Subnet Router: Remote Access to Your Entire Homelab — connect and administer the server from anywhere
- Proxmox Backup Server: Automated Container Backups — back up your world saves automatically
- Proxmox Firewall Guide — open only the Minecraft port (25565) and nothing else
Recommended hardware for this setup:
- HP EliteDesk 705 G4 mini — the host node used in this guide
- APC UPS 1500VA — protect your world saves from power cuts
- DDR4 SO-DIMM 8GB — RAM upgrade for 8+ player servers
Sources: FabricMC, Fabric API (Modrinth).
This post contains Amazon affiliate links (tag: buildahomelab-20). I earn a small commission on qualifying purchases at no extra cost to you.
Comments
Comments are powered by GitHub Discussions — sign in with a GitHub account to join the conversation.