TL;DR:
- Install SteamCMD, download Steam app 380870 as an unprivileged
zomboiduser, and run the server under systemd, which sendssaveandquitto its console on stop. - Checked against Build 42.21, the stable public branch since September 28, 2026. The Linux server files take about 7.2 GB.
- Players connect on UDP ports 16261 and 16262. The RCON port 27015 stays closed.
- PZwiki, the official wiki, sizes the server heap at 3 GB plus about 500 MB per player. This tutorial starts at 8 GB of RAM with a 6 GB Java heap set in
ProjectZomboid64.json. - Build 41 saves do not load on Build 42. The
legacy41branch keeps a Build 41 server running.
Applies to: Ubuntu 24.04 LTS · Project Zomboid Dedicated Server Build 42.21 · checked October 2026
A Project Zomboid dedicated server is The Indie Stone's free server program (Steam app 380870) that hosts a Project Zomboid multiplayer world without a game client running, so players can join while the host is offline. This tutorial installs the Build 42 server on Ubuntu 24.04 with SteamCMD, runs it under systemd as its own user, and covers the Java heap, servertest.ini, Workshop mods, admin commands, backups and updates per branch. A VPS keeps the world online when your own PC is off.
Project Zomboid dedicated server requirements
PZwiki, the official wiki, and The Indie Stone's release posts list:
| Resource | Guidance |
|---|---|
| Server build | Build 42.21 on the public (stable) branch. Build 41.78.21 on the legacy41 branch |
| RAM | PZwiki: at least 3 GB for the server plus about 500 MB per player (4 players: 5 GB), more with mods. The Windows start script ships set to 16 GB |
| Storage | About 7.2 GB of Linux server files, plus saves and backups |
| Network | UDP 16261 (game port) and UDP 16262 (direct connection port) |
The Java heap (-Xmx, with -Xms as its starting size) caps the memory for game data. The Java process uses some memory on top of it, so leave RAM free for it and for Ubuntu:
| VPS RAM | Java heap (-Xms and -Xmx) | Players by PZwiki's sizing, no mods | Left outside the heap |
|---|---|---|---|
| 8 GB | 6g | 6 | 2 GB |
| 12 GB | 9g | 12 | 3 GB |
| 16 GB | 12g | 18 | 4 GB |
Move up a size for more players, many mods or memory errors. The Memory: line in systemctl status zomboid shows what the whole service uses.
Prerequisites
- A VPS running Ubuntu 24.04 LTS with at least 8 GB RAM and your SSH public key added at deploy. Arct Cloud plans with 8 GB RAM and 4 vCPU are
cvm.small,vm.tinyand the High Performancehvm.tiny; plans with 16 GB RAM and 8 vCPU arecvm.xlarge,vm.mediumandhvm.medium. - An SSH key pair. See How to Generate an SSH Key on Windows, macOS, and Linux.
- A non-root user with sudo privileges that logs in with your SSH key. The commands below create one.
- A copy of Project Zomboid on Steam for each player, on the same branch as the server.
On a new server, log in as root and create the sudo user. The rsync line copies root's authorized SSH key to the new account, because the key added at deploy belongs to root:
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
Open a second terminal and confirm ssh [email protected] works before you log out as root. Replace 203.0.113.10 with your server's public IP address. Commands below run as the sudo user. Replace values in capitals, such as YOUR_SERVER_NAME, with your own.
Step 1: Install SteamCMD
SteamCMD is Valve's command-line Steam client. Ubuntu ships it as a 32-bit package in the multiverse repository, so enable multiverse and the i386 architecture first. The SteamCMD tutorial covers the install in detail.
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository -y multiverse
sudo dpkg --add-architecture i386
sudo apt update
The package asks you to accept Valve's Steam License Agreement, which incorporates the Steam Subscriber Agreement. Read it, then record your answer and install:
echo steam steam/question select "I AGREE" | sudo debconf-set-selections
echo steam steam/license note '' | sudo debconf-set-selections
sudo apt install -y steamcmd
Step 2: Enable UFW and allow SSH
Allow SSH before you enable UFW, or UFW blocks your next SSH login:
sudo ufw allow OpenSSH
sudo ufw enable
Type y when UFW asks to confirm. The game ports stay closed until Step 10, after the join password is set.
Step 3: Create a system user for the server
PZwiki says not to run the server as root. Create an unprivileged service user that owns the server files and the world:
sudo useradd --system --create-home --home-dir /home/zomboid --shell /usr/sbin/nologin zomboid
Step 4: Get the Project Zomboid dedicated server for Linux
App ID 380870 is the Project Zomboid Dedicated Server tool. It downloads with an anonymous login, so no Steam account is needed on the server:
sudo -u zomboid -H /usr/games/steamcmd \
+force_install_dir /home/zomboid/server \
+login anonymous \
+app_update 380870 validate \
+quit
+force_install_dir must come before +login. The full /usr/games/steamcmd path is needed because sudo's default secure_path on Ubuntu does not include /usr/games. The output ends similar to this:
...
Success! App '380870' fully installed.
Step 5: Set the server memory
PZwiki documents ProjectZomboid64.json as the launcher's config file, with the heap size on its -Xmx line. A SteamCMD validate restores changed files, so this script sets the heap in the server folder's copy and the service runs it after every update. Create /usr/local/bin/zomboid-heap, with HEAP=6g changed to your row of the RAM table:
sudo tee /usr/local/bin/zomboid-heap > /dev/null <<'EOF'
#!/bin/sh
set -eu
HEAP=6g
CONF=/home/zomboid/server/ProjectZomboid64.json
sed -i -E "s/\"-Xm([sx])[0-9]+[gGmM]\"/\"-Xm\\1$HEAP\"/g" "$CONF"
grep -oE '"-Xm[sx][0-9]+[gGmM]"' "$CONF" || echo "No -Xmx entry found in $CONF"
EOF
sudo chmod 755 /usr/local/bin/zomboid-heap
The script also sets an -Xms entry if present, so the starting heap never exceeds the maximum. The service runs it at every start, so a later change to the HEAP= line applies at the next restart. Run it once as the service user:
sudo -u zomboid /usr/local/bin/zomboid-heap
The output shows the heap entries with the new value. PZwiki warns that the Windows script's shipped 16 GB setting must be changed or the server fails with memory errors, so set the heap before the first launch.
Step 6: Run the first launch and set the admin password
On the first run, the server asks for an admin password, then generates the world and settings files in /home/zomboid/Zomboid. PZwiki says to do this once by hand. -adminusername names the admin account; Step 9 uses the same name:
sudo -u zomboid -H bash -c 'cd /home/zomboid/server && bash start-server.sh -adminusername YOUR_ADMIN_NAME'
Use letters and numbers for the name and type the password when asked. When the console prints a line with SERVER STARTED, type quit and press Enter to save the world and stop.
Step 7: Configure servertest.ini settings
Set the server name, join password, player limit and autosave interval as the zomboid user:
sudo -u zomboid sed -i \
-e 's/^PublicName=.*/PublicName=YOUR_SERVER_NAME/' \
-e 's/^Password=.*/Password=YOUR_JOIN_PASSWORD/' \
-e 's/^MaxPlayers=.*/MaxPlayers=6/' \
-e 's/^SaveWorldEveryMinutes=.*/SaveWorldEveryMinutes=15/' \
/home/zomboid/Zomboid/Server/servertest.ini
Use letters and numbers, because / and & break sed. MaxPlayers=6 matches the 6 GB heap in the RAM table. With the default SaveWorldEveryMinutes=0, PZwiki says the map is usually saved only when players leave an area. Check the values:
sudo grep -E '^(PublicName|Password|MaxPlayers|SaveWorldEveryMinutes|Public|Open|DefaultPort|UDPPort)=' \
/home/zomboid/Zomboid/Server/servertest.ini
Other settings and their PZwiki defaults:
| Setting | Default | Effect |
|---|---|---|
Public | false | true lists the server in the in-game browser |
Open | true | Players create an account on first join |
DefaultPort / UDPPort | 16261 / 16262 | The two UDP ports |
RCONPort / RCONPassword | 27015 / empty | Remote console; UFW keeps the port closed |
Sandbox settings such as zombie population live in servertest_SandboxVars.lua. The server reads both files at its next start.
Step 8: Create the backup script
The service runs this script before every start, while the world is stopped, so each archive holds a consistent copy of the world, the settings and the server's db folder. Create /usr/local/bin/zomboid-backup:
sudo tee /usr/local/bin/zomboid-backup > /dev/null <<'EOF'
#!/bin/sh
set -eu
DATA=/home/zomboid/Zomboid
DEST=/home/zomboid/backups
[ -d "$DATA/Saves/Multiplayer" ] || exit 0
mkdir -p "$DEST"
find "$DEST" -name 'zomboid-*.tar.gz' -mmin -10 | grep -q . && exit 0
ITEMS="Saves/Multiplayer Server"
[ -d "$DATA/db" ] && ITEMS="$ITEMS db"
tar -czf "$DEST/zomboid-$(date +%Y%m%d-%H%M%S).tar.gz" -C "$DATA" $ITEMS
find "$DEST" -name 'zomboid-*.tar.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/zomboid-backup
The script skips the archive when one is less than 10 minutes old and keeps 14 days of archives.
Step 9: Run the server as a systemd service
PZwiki's systemd example connects the server console to a named pipe (FIFO) that systemd creates. On stop, the unit writes save, waits 15 seconds and writes quit. The same page warns that the developers discourage this method and that a clean save on shutdown is not guaranteed; Step 8 archives the world before each start.
Create /etc/systemd/system/zomboid.socket with sudo nano, paste this unit, then save with Ctrl+O and exit with Ctrl+X:
[Unit]
BindsTo=zomboid.service
[Socket]
ListenFIFO=/home/zomboid/zomboid.control
FileDescriptorName=control
RemoveOnStop=true
SocketMode=0660
SocketUser=zomboid
Create /etc/systemd/system/zomboid.service the same way. Replace YOUR_ADMIN_NAME with the name from Step 6:
[Unit]
Description=Project Zomboid Dedicated Server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=zomboid
Group=zomboid
WorkingDirectory=/home/zomboid/server
Sockets=zomboid.socket
PrivateTmp=true
ExecStartPre=/usr/local/bin/zomboid-backup
ExecStartPre=-/usr/games/steamcmd +force_install_dir /home/zomboid/server +login anonymous +app_update 380870 +quit
ExecStartPre=/usr/local/bin/zomboid-heap
ExecStart=/bin/sh -c "exec /home/zomboid/server/start-server.sh -adminusername YOUR_ADMIN_NAME < /home/zomboid/zomboid.control"
ExecStop=/bin/sh -c "echo save > /home/zomboid/zomboid.control; sleep 15; echo quit > /home/zomboid/zomboid.control"
KillSignal=SIGCONT
TimeoutStartSec=1800
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
What the unit does:
- Each start runs the backup, a SteamCMD update and the heap script. The
-lets the server start when Steam is unreachable. KillSignal=SIGCONTkeeps systemd from killing the server afterquit; it waits up to 5 minutes (TimeoutStopSec=300) for the save.- Like PZwiki's example, the unit has no automatic restart, so the pipe never holds a stale
quit. After a crash or an in-game/quit, start it again.
Start the server and enable it at boot:
sudo systemctl daemon-reload
sudo systemctl enable --now zomboid
sudo systemctl status zomboid --no-pager
The Active: line reads active (running). Follow the log with sudo journalctl -u zomboid -f until a line with SERVER STARTED appears.
Step 10: Open UDP ports 16261 and 16262
Open the two UDP ports PZwiki lists, 16261 and the direct connection port 16262:
sudo ufw allow 16261:16262/udp
sudo ufw status
The output looks similar to this:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
16261:16262/udp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
16261:16262/udp (v6) ALLOW Anywhere (v6)
If your provider runs a network firewall in front of the server, open the same ports there.
Step 11: Connect and verify the server
Check the UDP sockets and the console pipe:
sudo ss -ulpn | grep -E ':1626[12]'
echo players | sudo tee /home/zomboid/zomboid.control > /dev/null
sudo journalctl -u zomboid -n 10 --no-pager
ss lists the server's UDP sockets, including port 16261, and the journal shows the reply to players.
In Project Zomboid, select Join, open the Favorites tab and add the server's public IPv4 address (for example 203.0.113.10), port 16261, an account name and password, and the join password from Step 7. Save and join. For admin rights, log in as YOUR_ADMIN_NAME with the admin password.
Add Steam Workshop mods
servertest.ini lists mods in three lines: WorkshopItems= (Workshop IDs to download, separated by semicolons), Mods= (mod IDs to load) and Map= (map mods). The game's settings editor, which PZwiki documents, writes them for you:
- On your PC, subscribe to the mods, start Project Zomboid, select Host, then Manage Settings, and create or edit settings named
servertest. - Add the mods on the Steam Workshop and Mods pages, set the Map order for map mods, and save.
- Copy the three lines from
servertest.iniin theZomboid\Serverfolder of your PC user profile.
Paste them over the same lines on the server while the service is stopped:
sudo systemctl stop zomboid
sudo -u zomboid nano /home/zomboid/Zomboid/Server/servertest.ini
sudo systemctl start zomboid
The server downloads the Workshop items as it starts, and players get them on connect. PZwiki notes that mods for older versions are likely not to work, so a Build 41 mod needs an update from its author. Add mods you trust: in April 2026, The Indie Stone reported 14 Workshop mods that created malicious files outside the game folder, and they were removed from the Steam Workshop.
Project Zomboid server commands
Admin commands work in the server console and in game chat, where each starts with /. From PZwiki's command list:
| Command | Effect |
|---|---|
players | List connected players |
save | Save the world |
servermsg "text" | Broadcast a message |
kickuser "name" | Kick a player |
banuser "name" -ip | Ban a player and the player's IP address |
setaccesslevel "name" "moderator" | Set Admin, Moderator, Overseer, GM, Observer or none |
checkModsNeedUpdate | Write to the log whether a mod has an update |
From SSH, write a command to the console pipe and read the reply in the journal:
echo 'servermsg "Restart in 5 minutes"' | sudo tee /home/zomboid/zomboid.control > /dev/null
sudo journalctl -u zomboid -n 5 --no-pager
Update the Project Zomboid server and switch branches
Each restart checks Steam for a new build on the server's branch, so sudo systemctl restart zomboid applies an update. Build 42.21 fixed a way into dedicated servers without Steam authentication that broke SteamID bans, so update after each stable release. To verify every file, run the download with validate while the server is stopped:
sudo systemctl stop zomboid
sudo -u zomboid -H /usr/games/steamcmd \
+force_install_dir /home/zomboid/server \
+login anonymous \
+app_update 380870 validate \
+quit
sudo systemctl start zomboid
Branches of app 380870 on October 6, 2026:
| Branch | Build | SteamCMD option |
|---|---|---|
public | Build 42.21, stable | none |
unstable | New builds before they reach stable | -beta unstable |
legacy41 | Build 41.78.21 | -beta legacy41 |
42.19 | Build 42.19.2 | -beta 42.19 |
Valve's SteamCMD guide says the -beta option must be quoted on the command line. To switch to legacy41, stop the server, archive the world with the Step 8 script, then run the download with the branch inside the quotes:
sudo systemctl stop zomboid
sudo -u zomboid /usr/local/bin/zomboid-backup
sudo -u zomboid -H /usr/games/steamcmd \
+force_install_dir /home/zomboid/server \
+login anonymous \
+app_update "380870 -beta legacy41 validate" \
+quit
Open the unit with sudo nano /etc/systemd/system/zomboid.service and change the update line to:
ExecStartPre=-/usr/games/steamcmd +force_install_dir /home/zomboid/server +login anonymous +app_update "380870 -beta legacy41" +quit
Apply the change and start the server:
sudo systemctl daemon-reload
sudo systemctl start zomboid
Use -beta public the same way to move back to the stable branch. Players pick the same branch under Properties, Game Versions & Betas in Steam.
Back up and restore the world
Every start writes an archive to /home/zomboid/backups. The server also keeps its own backups, set by BackupsCount (default 5), BackupsOnStart and BackupsOnVersionChange in servertest.ini. List the archives:
sudo ls -lh /home/zomboid/backups
To restore one, stop the server, move the current world aside and extract the archive, which also restores the settings and db folder. Replace YYYYMMDD-HHMMSS with its timestamp:
sudo systemctl stop zomboid
sudo -u zomboid mv /home/zomboid/Zomboid/Saves/Multiplayer /home/zomboid/Zomboid/Saves/Multiplayer.old-$(date +%Y%m%d-%H%M%S)
sudo -u zomboid tar -xzf /home/zomboid/backups/zomboid-YYYYMMDD-HHMMSS.tar.gz -C /home/zomboid/Zomboid
sudo systemctl start zomboid
The archives share a disk with the world. Copy them to your computer as shown in how to copy files to a VPS. For copies kept off the server, see VPS backups.
Troubleshoot common Project Zomboid server errors
| Symptom | Cause | Fix |
|---|---|---|
| Joining times out or the server failed to respond | Server down, UDP ports blocked, or a different branch | Check systemctl status zomboid, sudo ufw status and the branch in Steam |
Assertion Failed: Illegal termination of worker thread | Data from an earlier Build 41 server | Run sudo cat /home/zomboid/server/steam_appid.txt; it must hold only 108600. Then back up and move /home/zomboid/Zomboid aside |
Server terminated at startup, OutOfMemoryError or killed by the OOM killer in the journal | Heap too large for free RAM, or too small for the world | Run sudo sed -i 's/^HEAP=.*/HEAP=9g/' /usr/local/bin/zomboid-heap with your row of the RAM table, then sudo systemctl restart zomboid, or add RAM |
| Journal stops at the admin password prompt | Step 6 skipped, or another -adminusername in the unit | Stop the service and run Step 6 with the same name |
Settings not saving, or servertest.ini changes do nothing | Edited a copy the server does not read | Edit /home/zomboid/Zomboid/Server/servertest.ini as zomboid, then run reloadoptions or restart |
FAQ
How much RAM does a Project Zomboid dedicated server need?
PZwiki, the official wiki, says to assign the server at least 3 GB plus about 500 MB per player, so 2 players need 4 GB and 4 players need 5 GB. This tutorial sets a 6 GB Java heap on a server with 8 GB of RAM. Mods need more.
Is a Project Zomboid dedicated server free?
Yes. The server tool, Steam app 380870, downloads free with an anonymous SteamCMD login. Each player still needs a copy of Project Zomboid on the same branch as the server.
Can you host a Project Zomboid server without playing?
Yes. The dedicated server runs without a game client, so the world stays online while you are offline. You join from your own PC like any other player.
Can you make a private server in Project Zomboid?
Yes. Set Password in servertest.ini so players need it to join; Steam's server browser lists Steam servers anyway, so the password keeps it private. Public=false keeps it out of the in-game list, and Open=false with the adduser command makes it invite-only.
How do I make a server in Project Zomboid Build 42?
Install Steam app 380870 from the public branch, which has carried Build 42 since July 29, 2026. Build 41 saves do not load on Build 42, so to keep a Build 41 world, install the server from the legacy41 branch and have players switch the game to legacy41 in Steam.
How do I join a dedicated server in Project Zomboid?
Select Join, open the Favorites tab and add the server's public IPv4 address, port 16261, an account name and password, and the join password. Save the entry and join. Your VPS provider shows the IP address.
Next steps
- How to Install SteamCMD on Ubuntu 24.04
- How to Host a Valheim Dedicated Server on Ubuntu 24.04
- PZwiki: Dedicated server
- PZwiki: Server settings
High Performance plans run on AMD Ryzen 9 up to 5.7 GHz or AMD EPYC Genoa 9004 Series up to 4.3 GHz, with DDR5 RAM. Compare plans.
This work is licensed under CC BY-NC-SA 4.0.