Advanced Palworld RCON and Memory Management via Docker Compose
Palworld's dedicated server is built on Unreal Engine 5, and like most UE5 servers, it leaks memory under sustained load. A 32 player base captured world will routinely climb past 16 GB of resident memory after 48 hours of uptime, at which point the kernel OOM killer terminates the process and the active save is corrupted. The fix is automation: an RCON sidecar that can issue clean shutdown commands, plus a host watchdog that monitors memory and triggers a safe reboot before the kernel intervenes.
This guide deploys the popular thijsvanloef/palworld-server-docker image with Compose, layers an RCON CLI container alongside it for scripted command execution, and finishes with a host mounted shell script that broadcasts a warning and triggers a graceful restart whenever memory crosses 90 percent of the configured limit.
Prerequisites
- Ubuntu 24.04 LTS with at least 16 GB of RAM and a fast 4 core CPU.
- Docker Engine plus the Compose plugin installed.
- 20 GB of free SSD storage for binaries, world saves, and backups.
- UDP 8211 (game) and TCP 25575 (RCON) open at the firewall.
Step 1: Project Layout
sudo mkdir -p /opt/palworld/{data,backups,scripts}sudo chown -R 1000:1000 /opt/palworldcd /opt/palworldStep 2: The Compose File
The compose stack runs two services: the Palworld server itself, and an rcon-cli container that is invoked on demand (not kept running) so we can script clean shutdowns without bundling RCON tooling into the game image.
services: palworld: image: thijsvanloef/palworld-server-docker:latest container_name: palworld restart: unless-stopped stop_grace_period: 60s ports: - "8211:8211/udp" - "25575:25575/tcp" volumes: - ./data:/palworld - ./backups:/palworld/backups environment: PUID: 1000 PGID: 1000 PORT: 8211 PLAYERS: 32 SERVER_NAME: "Pal Sanctuary" SERVER_DESCRIPTION: "Memory guarded community server" ADMIN_PASSWORD: "REPLACE_WITH_LONG_PASSWORD" SERVER_PASSWORD: "" RCON_ENABLED: "true" RCON_PORT: 25575 TZ: UTC MULTITHREADING: "true" BACKUP_ENABLED: "true" BACKUP_CRON_EXPRESSION: "0 */6 * * *" deploy: resources: limits: memory: 14G rcon: image: outdead/rcon:latest container_name: palworld-rcon network_mode: "service:palworld" depends_on: - palworld entrypoint: ["sleep", "infinity"]Three details matter here. First, memory: 14G gives us a hard ceiling that the watchdog can reason about. Second, network_mode: "service:palworld" on the RCON container shares the network namespace with the game server, which means RCON can talk to 127.0.0.1:25575 with no port forwarding. Third, the RCON container's entrypoint is sleep infinity: we never want it doing work on its own, only on demand when our watchdog script execs into it.
Step 3: First Boot
docker compose up -ddocker compose logs -f palworldWait for the log line Setting breakpad minidump AppID. From that point on, the server accepts client connections, and RCON answers on the internal port.
Step 4: The Memory Watchdog Script
The script lives on the host (not inside any container), runs every minute via cron, and uses docker stats for memory inspection and docker exec into the RCON sidecar for the safe shutdown sequence.
#!/usr/bin/env bashset -euo pipefailCONTAINER="palworld"RCON_CONTAINER="palworld-rcon"RCON_PASS="REPLACE_WITH_LONG_PASSWORD"THRESHOLD_PERCENT=90# Pull memory usage as a percentage of the configured limit.USAGE=$(docker stats --no-stream --format "{{.MemPerc}}" "$CONTAINER" | tr -d '%')USAGE_INT=$(printf "%.0f" "$USAGE")echo "[$(date -Iseconds)] Palworld memory at ${USAGE_INT}%"if [ "$USAGE_INT" -ge "$THRESHOLD_PERCENT" ]; then echo "[$(date -Iseconds)] Threshold reached, broadcasting warning" docker exec "$RCON_CONTAINER" rcon \ -a 127.0.0.1:25575 -p "$RCON_PASS" \ "Broadcast Server_restart_in_5_minutes_for_memory_hygiene" sleep 300 echo "[$(date -Iseconds)] Saving world and triggering shutdown" docker exec "$RCON_CONTAINER" rcon -a 127.0.0.1:25575 -p "$RCON_PASS" "Save" sleep 10 docker exec "$RCON_CONTAINER" rcon \ -a 127.0.0.1:25575 -p "$RCON_PASS" \ "Shutdown 5 Server_restart_in_5_seconds" sleep 15 docker compose -f /opt/palworld/docker-compose.yml restart palworldfichmod +x /opt/palworld/scripts/memory-watchdog.sh# Wire it into cron, every minutecrontab -e* * * * * /opt/palworld/scripts/memory-watchdog.sh >> /var/log/palworld-watchdog.log 2>&1Note the Palworld RCON command grammar uses underscores instead of spaces inside broadcast messages. The dedicated server tokenizer treats whitespace as the argument boundary, so Broadcast Server restart now would only send the word Server. Underscores survive the tokenizer and Palworld renders them as spaces client side.
Step 5: Verify End to End
Force a manual run to confirm the path works without waiting for organic memory growth. Temporarily lower the threshold to a value below the current usage, run the script by hand, watch the broadcast appear in game, and verify the container restarts cleanly.
THRESHOLD_PERCENT=10 /opt/palworld/scripts/memory-watchdog.sh# Then revert THRESHOLD_PERCENT to 90 in the script before savingPerformance and Tuning
- Keep
MULTITHREADING=truefor any host with more than 2 cores. The single threaded fallback is dramatically slower under sustained load. - Pin
memory: 14Gbelow the host's actual RAM (we use 14 on a 16 GB host) so the OOM killer never has reason to look at this container. - Mount
./backupson a separate disk if possible, so a save corruption event cannot cascade into the backup history. - Tune
BACKUP_CRON_EXPRESSIONto your community's tolerance. Every 6 hours is a sensible default, every hour is fine if disk is cheap.
Conclusion
With the Palworld server, an RCON sidecar, and a host mounted watchdog all defined in one Compose stack plus a single shell script, your community is protected from the most common Unreal Engine 5 failure mode: silent memory growth followed by an OOM kill mid play session. Tune the threshold and warning window to your community's patience, ship the backups offsite, and you have a hands off Palworld deployment that survives weeks of uptime without operator intervention.