Yes, you can run a Minecraft server on a Raspberry Pi, but the experience hinges entirely on the board variant, RAM allocation, and storage I/O. For modern Java Edition (1.20+), the Raspberry Pi 5 (8GB) is the only viable choice for a lag-free survival world with 3-5 concurrent players. Older boards like the Pi 4 can handle Bedrock Edition (C++) or heavily stripped-down vanilla forks, but Java Edition's chunk generation will rapidly bottleneck the Cortex-A72 CPU and the SD card bus.
This guide targets the Raspberry Pi 5 (8GB) running Raspberry Pi OS (64-bit, Bookworm). We will bypass the microSD I/O bottleneck by mapping an NVMe drive via the PCIe lane, install Java 21, and deploy PaperMC with Aikar’s Garbage Collection (GC) flags to prevent tick lag.
Raspberry Pi Models vs. Minecraft Server Performance
Before ordering parts, you need to know what your board can actually handle. Minecraft Java Edition is notoriously single-thread-heavy for chunk generation and entity AI. Here is the real-world performance data based on 1.20.4 PaperMC benchmarks at default view distances.
| Board Variant | CPU Arch / Clock | RAM | Max Players (PaperMC) | Chunk Gen Speed (10x10) | Verdict |
|---|---|---|---|---|---|
| Pi 3B+ | Cortex-A53 @ 1.4GHz | 1GB | 0 (Unplayable) | > 45 seconds | Obsolete for Java. Bedrock only. |
| Pi 4 (4GB) | Cortex-A72 @ 1.5GHz | 4GB | 2-3 | ~ 18 seconds | Passable for vanilla, struggles with farms. |
| Pi 4 (8GB) | Cortex-A72 @ 1.8GHz | 8GB | 4-5 | ~ 14 seconds | Good, but SD card I/O causes stutter. |
| Pi 5 (8GB) | Cortex-A76 @ 2.4GHz | 8GB | 6-10 | ~ 4 seconds | Sweet spot. NVMe PCIe makes it viable. |
Hardware BOM and GPIO/Interface Mapping
To build a reliable embedded server, you need to manage thermals and I/O. The Pi 5 runs hot under sustained Java compilation and chunk generation loads. Below is the exact parts list and the hardware interface mapping required for the provisioning script.
Parts List
- Compute: Raspberry Pi 5 (8GB variant)
- Thermal: Official Pi 5 Active Cooler (PWM controlled)
- Power: Official 27W USB-C PD Power Supply (Required to prevent PCIe brownouts)
- Storage HAT: Geekworm X1001 NVMe Base (M.2 NGFF)
- Storage: 256GB M.2 2230 NVMe SSD (e.g., WD Blue SN580)
- Boot: 32GB microSD (UHS-I, A2 rated) for bootloader fallback
Hardware Interface & Pin Mapping Table
Unlike microcontrollers, the Pi uses a Linux device tree for pinmuxing. However, for our automated setup script, we must explicitly define the hardware interfaces and GPIO pins we are targeting for thermal management and storage.
| Component | Interface / Bus | Pin / Lane Mapping | Function in Build |
|---|---|---|---|
| Active Cooler Fan | PWM (Hardware) | GPIO 18 (Pin 12) | Dynamically scales fan RPM based on SoC temp. |
| NVMe SSD | PCIe Gen 2.0 x1 | PCIe Lane 0 (FPC Connector) | Hosts world data; bypasses SDIO bottleneck. |
| Power Supply | USB-C PD | 5V / 5A (27W) | Prevents throttled=0x50000 brownout errors. |
The Setup: PaperMC, Java 21, and Aikar’s Flags
Minecraft 1.20.5 and newer strictly require Java 21. Furthermore, running the server with default Java garbage collection will result in massive lag spikes every time the JVM clears dead objects (like broken blocks or dead mobs). We use Aikar’s Flags, a highly tuned set of JVM arguments designed specifically for Minecraft's object-heavy memory model.
The following Bash script automates the installation of Java 21, downloads the latest PaperMC jar, configures the startup script with Aikar's flags, and sets up a systemd service. It also configures the GPIO 18 PWM fan daemon.
#!/bin/bash
# Minecraft Pi 5 Provisioning Script
# Target: Raspberry Pi 5 (8GB) running Raspberry Pi OS 64-bit (Bookworm)
set -e
# --- PIN & HARDWARE DEFINITIONS ---
FAN_GPIO_PIN=18
NVME_MOUNT="/mnt/nvme"
SERVER_DIR="${NVME_MOUNT}/minecraft"
PAPER_VERSION="1.20.6"
BUILD_NUM="143" # Check papermc.io for latest build
# --- ERROR HANDLING ---
trap 'echo "[ERROR] Provisioning failed at line $LINENO. Check logs."; exit 1' ERR
echo "[1/6] Updating system and installing Java 21..."
sudo apt update && sudo apt install -y openjdk-21-jre-headless curl wget
# Verify Java version
JAVA_VER=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1)
if [ "$JAVA_VER" -lt 21 ]; then
echo "[FATAL] Java 21 is required for MC 1.20.5+. Found: $JAVA_VER"
exit 1
fi
echo "[2/6] Configuring NVMe mount for world storage..."
sudo mkdir -p $NVME_MOUNT
# Assuming /dev/nvme0n1p1 is formatted as ext4
if ! grep -q "$NVME_MOUNT" /etc/fstab; then
echo "/dev/nvme0n1p1 $NVME_MOUNT ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
sudo mount -a
fi
sudo mkdir -p $SERVER_DIR
cd $SERVER_DIR
echo "[3/6] Downloading PaperMC..."
wget -O paper.jar "https://api.papermc.io/v2/projects/paper/versions/${PAPER_VERSION}/builds/${BUILD_NUM}/downloads/paper-${PAPER_VERSION}-${BUILD_NUM}.jar"
echo "[4/6] Writing start.sh with Aikar's Flags..."
cat << 'EOF' > start.sh
#!/bin/bash
# Aikar's Flags tuned for Pi 5 8GB (Allocating 5GB to JVM, leaving 3GB for OS/IO)
java -Xms5G -Xmx5G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-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 \
-Dusing.aikars.flags=https://mcflags.emc.gs \
-Daikars.new.flags=true \
-jar paper.jar --forceUpgrade
EOF
chmod +x start.sh
echo "[5/6] Accepting EULA..."
echo "eula=true" > eula.txt
echo "[6/6] Configuring GPIO 18 PWM Fan Daemon..."
# Pi 5 active cooler is managed by the firmware, but we ensure the overlay is active
if ! grep -q "dtoverlay=pwm,pin=${FAN_GPIO_PIN},func=2" /boot/firmware/config.txt; then
echo "dtoverlay=pwm,pin=${FAN_GPIO_PIN},func=2" | sudo tee -a /boot/firmware/config.txt
fi
echo "[SUCCESS] Server provisioned at $SERVER_DIR. Run './start.sh' inside the directory to generate initial files."
Debugging Server Lag and Crash Loops
When hosting on embedded ARM hardware, you don't have the luxury of brute-forcing performance with a 16-core Xeon. When the server stutters, you need to diagnose the exact bottleneck. Here are the exact error strings you will see in the console, ranked by likelihood, and how to fix them.
1. "Can't keep up! Is the server overloaded?"
Exact Error String: [Server thread/WARN]: Can't keep up! Is the server overloaded? Running 2500ms or 50 ticks behind
- Cause A (Most Likely): View distance is too high for the Cortex-A76 CPU. Fix: Open
server.propertiesand setview-distance=6andsimulation-distance=4. - Cause B: Thermal throttling. The SoC hit 85°C and clocked down to 1.5GHz. Fix: Ensure the active cooler is seated properly and check thermal paste.
- Cause C: Redstone clocks or massive item sorters causing entity tick lag. Fix: Install the Spark profiler plugin to identify the exact chunk causing the TPS drop.
2. Java Heap Space Crash
Exact Error String: java.lang.OutOfMemoryError: Java heap space
- Cause A: You allocated too much RAM to the JVM, leaving the Linux OS no memory for file caching, causing an OOM kill. Fix: Never allocate more than 5GB to the JVM on an 8GB Pi 5.
- Cause B: A memory leak in a poorly coded plugin. Fix: Remove plugins one by one and monitor heap usage via
htop.
The First Three Things to Check When It Fails
If the server crashes or becomes unresponsive, run these three diagnostic commands via SSH before touching any config files:
- Check for Thermal/Power Throttling: Run
vcgencmd get_throttled. If it returns0x0, you are fine. If it returns0x50000or similar, your Pi has experienced power brownouts or thermal throttling since boot. - Check Storage I/O Wait: Run
iostat -x 1 3. If the%iowaitcolumn on your NVMe device is consistently above 20%, your storage bus is bottlenecked (often caused by excessive logging or a failing SSD). - Check OS Memory Swapping: Run
free -h. If theSwaprow shows heavy usage, the JVM is pushing the OS into swap, which will instantly destroy server TPS. Reduce your-Xmxflag.
Extending or Simplifying Your Pi Server
Once your baseline PaperMC server is stable, you can tailor the build to your specific administration style.
How to Extend the Build
- Add Prometheus Monitoring: Install the Prometheus Exporter plugin on PaperMC. Run a lightweight Grafana instance on a separate machine to graph player counts, TPS, and JVM heap usage in real-time.
- Automated Off-Site Backups: Write a cron job that triggers the
rcon-clito executesave-offandsave-all, usesrsyncto push the world folder to a remote NAS, and then re-enables saving. This prevents world corruption during I/O spikes. - Run via Docker: For better isolation, wrap the
start.shscript in anarm64v8/eclipse-temurin:21-jreDocker container, mapping the NVMe directory as a volume. This makes migrating to a beefier x86 server later trivial.
How to Simplify the Build
If writing Bash scripts and tuning JVM garbage collection flags feels like overkill, you can abstract the embedded layer entirely:
- MineOS WebUI: Install the MineOS Turnkey Linux distribution. It provides a web-based GUI to create servers, schedule backups, and manage JVM flags without touching the command line.
- DietPi: Flash DietPi instead of Raspberry Pi OS. Use the
dietpi-softwaremenu to install the pre-configured Minecraft server package, which automatically handles Java dependencies and systemd services. - Bedrock Edition: If your players are on consoles or mobile, abandon Java entirely. Run the official Bedrock Dedicated Server (BDS) via Docker. It is written in C++, uses a fraction of the RAM, and requires zero JVM tuning, making it perfectly viable even on a Pi 4.
Running a server on embedded hardware is an exercise in resource management. By respecting the Pi 5's thermal limits, bypassing the SD card bus with NVMe, and tuning the JVM for ARM architecture, you can host a highly capable, low-power Minecraft server that runs 24/7 for pennies a month in electricity.






