TL;DR: grab SteamCMD, pull app 2394010, drop a systemd unit, open 8211/udp.
sudo apt install steamcmd
steamcmd +login anonymous +app_update 2394010 validate +quit
sudo systemctl enable --now palworld
sudo ufw allow 8211/udp
Rest of this post is the stuff you wish the Steam page told you.
Prereqs
- Ubuntu 22.04 or 24.04, x86_64
- 16 GB RAM recommended. 4 GB is the absolute floor and the server will swap itself into a coma. 8 GB works for 4 players if nobody builds anything
- 4 CPU cores — Palworld only really uses one of them hard but the engine spawns threads
- glibc 2.31+ (Ubuntu 22.04 is 2.35, you're fine)
- Non-root user for the server. Don't run game servers as root
Create the user first:
sudo adduser --system --group --home /opt/palworld palworld
Install SteamCMD
SteamCMD is in the multiverse repo. Enable it, then install:
sudo add-apt-repository multiverse
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install steamcmd
Accept the Steam license when it prompts. You'll only get the prompt once.
Install the Palworld server
The Steam app ID is 2394010. Run SteamCMD as the palworld user so file ownership is right:
sudo -u palworld -H steamcmd \
+force_install_dir /opt/palworld \
+login anonymous \
+app_update 2394010 validate \
+quit
First run downloads about 3 GB. validate re-checks file hashes — slower but catches corrupted downloads. I always use it.
First run (smoke test)
Before touching systemd, boot the server once by hand so you can see the output:
sudo -u palworld -H bash -c 'cd /opt/palworld && ./PalServer.sh'
If you get error while loading shared libraries: libsteam_api.so, the LD_LIBRARY_PATH isn't set. The PalServer.sh wrapper normally handles this — if it doesn't, your install is incomplete. Re-run SteamCMD with validate.
Once it says Setting breakpad minidump AppID = 2394010 and sits there, it's up. Ctrl+C to kill it, then we'll do it properly with systemd.
systemd unit
Drop this at /etc/systemd/system/palworld.service:
[Unit]
Description=Palworld Dedicated Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=palworld
Group=palworld
WorkingDirectory=/opt/palworld
ExecStart=/opt/palworld/PalServer.sh -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS
Restart=on-failure
RestartSec=10
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
The three flags on ExecStart are the ones the devs actually recommend for dedicated servers. They do real work — leave them in.
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable --now palworld
sudo systemctl status palworld
journalctl -u palworld -f
More on systemd units if you want the pattern for other game servers: Writing systemd service unit files.
PalWorldSettings.ini
The settings file lives here after the first boot:
/opt/palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini
There's a default template at /opt/palworld/DefaultPalWorldSettings.ini. Don't edit that one — copy what you need out of it into the LinuxServer copy. Minimal useful overrides:
[/Script/Pal.PalGameWorldSettings]
OptionSettings=(Difficulty=None,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.500000,PalCaptureRate=1.200000,DeathPenalty=None,ServerPlayerMaxNum=8,ServerName="My Palworld Server",ServerDescription="",AdminPassword="CHANGEME",ServerPassword="",PublicPort=8211,PublicIP="",RCONEnabled=True,RCONPort=25575,bIsMultiplay=True)
Settings that actually matter for ops:
AdminPassword— set it. Without it you can't kick anyone or save the world remotelyDeathPenalty=None— friends will stop playing if they lose their Pals on death. Trust meServerPlayerMaxNum— hard cap. Each player is roughly 1 GB of extra RAMExpRate,PalCaptureRate— tune for your group. 1.5–2.0x makes the early game not miserableRCONEnabled=True— enables the admin console. Keep the port firewalled
After editing, sudo systemctl restart palworld. The server rewrites parts of this file, so edit it with the service stopped.
Firewall
Palworld needs 8211/udp open to the internet. Don't open 25575 (RCON) to the internet. Ever.
sudo ufw allow 8211/udp
sudo ufw status
Full UFW primer if you need it: UFW firewall rules on Ubuntu.
Verify
sudo ss -ulnp | grep 8211
journalctl -u palworld -n 50 --no-pager
From another machine, try joining via the in-game "Join via IP" dialog: SERVER_IP:8211. If the server responds but you time out, 99% of the time it's the firewall — either your server's UFW or the hoster's network ACL above it.
Updates
Palworld updates break save compatibility less than they used to, but they still happen. Updating is just SteamCMD again:
sudo systemctl stop palworld
sudo -u palworld -H steamcmd +force_install_dir /opt/palworld +login anonymous +app_update 2394010 validate +quit
sudo systemctl start palworld
Back up the save directory before every update. Yes, every update.
Backups
The save dir is /opt/palworld/Pal/Saved/SaveGames/. A simple daily rsync to another disk is enough for most groups:
rsync -a --delete /opt/palworld/Pal/Saved/SaveGames/ /backup/palworld/$(date +\%F)/
Full rsync pattern (with retention) is in rsync backups on Linux. Throw the command in a cron job or a systemd timer and forget it.
Gotchas
Server eats all the RAM
It will. Set a hard cap with systemd if the host runs other things:
[Service]
MemoryMax=14G
Drop into a /etc/systemd/system/palworld.service.d/override.conf so you don't lose it on an unattended-upgrades pass.
Save corruption after crash
Palworld sometimes dies mid-save. If players log in to an old world state, the current Players/*.sav files are truncated. Restore from backup. This is why the backup is not optional.
EOS login errors
Palworld uses Epic Online Services. If players get "connection timeout" with no server-side logs, EOS is down or blocked. Nothing to do on your end, wait it out.
Next
If you've done the Hytale server prep this pattern is identical: SteamCMD, systemd unit, config file, firewall. Every Steam-based dedicated server follows this shape — once you've done one, the next ones are just different app IDs.