Fabric Minecraft Server in a Proxmox LXC Container: Mods + JVM Tuning

Run a Fabric 1.20.1 Minecraft server in an unprivileged Proxmox LXC container with performance mods (Lithium, Starlight, Carpet), JVM garbage collection tuning, and systemd service management.

On this page
  1. Performance target
  2. Mod stack
  3. Task 1: Create the container
  4. Task 2: Install Java and create the server
  5. Task 3: Install performance mods
  6. Task 4: Tune the JVM and create the systemd service
  7. Task 5: Automatic backups
  8. Proxmox snapshot for pre-update safety
  9. Server management reference

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.

Fabric Minecraft Server in a Proxmox LXC: Mods + JVM Tuning — video walkthrough

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
Note

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 is archived

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

First: make these values your own

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.

1Create CT 104 on pvelab035 min
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
Tip

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

1Install Java 213 min

Minecraft 1.20.1 requires Java 17+. Java 21 performs better with virtual threads and the Shenandoah GC:

Inside CT 104

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" ...
2Create the minecraft user and directories2 min
Inside CT 104

useradd -m -s /bin/bash minecraft
mkdir -p /srv/minecraft/{server,mods,backups}
chown -R minecraft:minecraft /srv/minecraft
3Download Fabric installer and bootstrap the server5 min
Inside CT 104 — as root, then switch to minecraft user

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"
4Accept the EULA1 min
Inside CT 104

echo "eula=true" > /srv/minecraft/server/eula.txt
chown minecraft:minecraft /srv/minecraft/server/eula.txt

Task 3: Install performance mods

1Download Lithium and Starlight3 min

Download the 1.20.1-compatible versions from Modrinth:

Inside CT 104

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
Always verify mod versions against your MC + loader version

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

1Create start.sh with optimized JVM flags5 min

The flags below use Shenandoah (low-pause GC), pin threads to avoid cross-NUMA latency, and pre-touch memory:

Create /srv/minecraft/server/start.sh

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
2Create the systemd service3 min
Create /etc/systemd/system/minecraft.service

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
3Verify the server starts and verify TPS5 min
Watch the server log

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:

In-game console (Carpet mod required)

/carpet setDefault commandLog true
/log tps
# → TPS: 20.0, MSPT: 6.24

Task 5: Automatic backups

1Create a backup script5 min
Create /srv/minecraft/backups/backup.sh

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:

Schedule daily 3AM backup

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:

Proxmox host — snapshot CT 104 before updates

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

Common management commands from pvelab03 host

# 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:

Recommended hardware for this setup:

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.