Project Zomboid Field guide

How to set up a Project Zomboid Build 42 server on Ubuntu

Set up a Project Zomboid Build42 server on Ubuntu with SteamCMD, UDP ports, explicit data paths, console shutdown and off-host backup.

How to set up a Project Zomboid Build 42 server on Ubuntu

Install the dedicated server, keep its branch aligned with the clients and run a new vanilla world with an accessible console. This guide targets Ubuntu 24.04 x86_64, Steam clients and the public Build 42 branch. On 12 October 2026 the publisher lists 42.21 as stable; older instructions that always add -beta unstable can install a different branch. The Indie Stone's stable release announcement establishes the current branch.

Use a fresh VPS with SSH, sudo, public IPv4 and room for the game files, world and backups. For the example, provision 16 GB RAM and check the downloaded launcher's actual heap limits before starting. This allocation is a working assumption for a small vanilla group, not a guaranteed number of players.

Choose the branch before moving a save#

Build 41 worlds are not compatible with Build 42. For an existing Build 41 group, keep a separate installation and align the server and clients with legacy41; the publisher explains that option in its Build 42 transition announcement. Do not point the commands below at an old save and expect an in-place conversion.

This article creates a new servertest world. Keep that name throughout: changing -servername also changes which configuration and save the game selects.

Install SteamCMD and the dedicated-server app#

Run from the normal administrative SSH account:

bash
sudo apt update
sudo apt install -y software-properties-common tmux ufw nano
sudo add-apt-repository -y multiverse
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install steamcmd
sudo useradd --system --user-group --create-home \
  --home-dir /srv/pz --shell /bin/bash pz
sudo install -d -o pz -g pz -m 750 /srv/pz/server /srv/pz/backups
sudo -iu pz
umask 077
/usr/games/steamcmd +force_install_dir /srv/pz/server \
  +login anonymous +app_update 380870 validate +quit
cd /srv/pz/server
sed -n '1,160p' start-server.sh
free -h

Accept the Steam package licence when prompted. App 380870 is the dedicated server. force_install_dir comes before login; there is no beta flag for the public branch. The official dedicated-server guide documents installation and the shipped Linux launcher, but its retrieved branch note still describes the earlier unstable release: use the current publisher announcement for that choice.

Keep the supplied launch script and packaged runtime together. Follow the runtime path in start-server.sh; install external Java only if the current package explicitly requires it. Inspect where this launcher sets -Xms and -Xmx, including ProjectZomboid64.json if the script uses that file. For this 16 GB example, a maximum heap above 12 GB leaves too little headroom for native memory and Ubuntu. If the supplied limits exceed your budget, edit the file actually used by this launcher before starting. Record the edit: Steam validation can replace files in the installation directory. Increasing the heap cannot compensate for a VPS whose total memory is too small.

Generate the configuration once#

The Linux user's home and the server name select the persistent data. Back up that data together after the game exits.

Still logged in as pz:

bash
tmux new-session -s pz
cd /srv/pz/server
bash start-server.sh -servername servertest

Set the administrator password when the first-run prompt asks. Wait for world initialization to complete, then check the reported build and console errors. If the loaded branch differs from the clients, stop and correct the version before inviting players.

Enter save in the game console, wait for completion, then enter quit. The admin command reference documents that quit saves and exits. These commands go into the game console without a slash; in-game admin chat uses /save and /quit. Wait until Bash returns.

Edit the generated configuration, rather than replacing it with a Build 41 template:

bash
nano /srv/pz/Zomboid/Server/servertest.ini

Set or change the existing lines below. Keep all other generated settings unless you have a specific reason to change them:

ini
Public=false
Password=REPLACE_WITH_A_PRIVATE_PASSWORD
MaxPlayers=8
PauseEmpty=true
DefaultPort=16261
UDPPort=16262
Mods=
WorkshopItems=

Replace the password placeholder. Public=false controls listing, not authentication; keep a game password for an unlisted server. PauseEmpty=true pauses the simulation when nobody is connected. These options belong to the server settings reference. Leaving both mod lists empty gives the first connection a vanilla baseline.

bash
chmod 600 /srv/pz/Zomboid/Server/servertest.ini
bash start-server.sh -servername servertest

Detach with Ctrl+B, then D. After SSH reconnects, access the same console from the administrative account:

bash
sudo -iu pz tmux attach-session -t pz

Tmux preserves the process across a disconnected SSH session. After a VPS reboot, create a fresh tmux session as pz, return to /srv/pz/server and run the same launcher command. This setup does not provide automatic reboot recovery; add supervision only after validating a stop action that sends the game's quit command and waits for the process to exit.

Open the correct UDP ports#

Use a separate administrative SSH session. Confirm your SSH port with sudo sshd -T and allow it first; this example assumes TCP 22:

bash
sudo ufw allow 22/tcp
sudo ufw allow 16261/udp
sudo ufw allow 16262/udp
sudo ufw enable
sudo ufw status verbose
sudo ss -lunp 'sport = :16261 or sport = :16262'

If SSH uses another port, replace 22 before enabling UFW. Allow the same two UDP ports in the provider firewall. For a server behind a router, forward both to its fixed private address. Do not copy older per-player TCP ranges or open every Steam-related port by habit. Read the active build's startup log if it requests another port.

In the matching Steam game client, choose Join → Favorites, add the VPS public IP and connection port 16261, enter the server password and create a separate player username/password. Avoid using the administrator account for ordinary play. A browser listing and a UDP scan are weak checks: enter the world, make a recognizable change and confirm it after a save and restart. For UDP, a TCP port-checking website does not test the right protocol.

Add mods only after the vanilla connection works#

WorkshopItems selects Workshop downloads; Mods selects components inside those downloads. A numeric Workshop ID and a mod's internal ID are different identifiers. Build 42's layout and mod selection differ from Build 41, and early multiplayer troubleshooting contains conflicting workarounds.

When expanding this server, create the intended mod configuration using Host → Manage Settings in a client on the same release, then inspect the .ini it generates. Preserve its Mods syntax and Workshop associations instead of copying a Build 41 line. Check dependencies and multiplayer support on each mod's current Workshop page. Trial the configuration on a disposable world before changing this save, especially for map mods. Disabling Lua checksum validation is not an appropriate first step for a fresh server.

Back up settings, world and accounts together#

In the server console, warn players, run save, wait and run quit. Once the process has exited, log in as pz and create an archive:

bash
(
  set -e
  umask 077
  pz_backup="/srv/pz/backups/zomboid-$(date -u +%Y%m%dT%H%M%SZ).tar.gz"
  tar -czf "$pz_backup" -C /srv/pz Zomboid
  tar -tzf "$pz_backup"
)

This keeps the generated settings, multiplayer world and database together, rather than archiving only map files. Keep client character/map data separately where relevant; this server archive does not collect files from players' PCs.

Transfer the archive outside the VPS. In a separate administrative SSH session, enter the exact archive path and create an owner-only copy in your SSH account’s home:

bash
read -r -p "Exact archive path: " game_archive
ssh_admin=$(id -un)
ssh_group=$(id -gn)
ssh_home=$(getent passwd "$ssh_admin" | cut -d: -f6)
sudo install -o "$ssh_admin" -g "$ssh_group" -m 600 \
  "$game_archive" "$ssh_home/zomboid-export.tar.gz"

From your workstation, replace both placeholders:

bash
scp YOUR_SSH_USER@YOUR_VPS_IP:zomboid-export.tar.gz .

The staged copy is readable only by its owner. Remove it after downloading and verifying the archive. Protect the off-VPS archive too: it contains server passwords and player account data.

To restore, stop the server, preserve its current Zomboid directory and unpack the chosen archive into a temporary directory. Restore the whole data set with owner pz:pz, keep the same server name and launch the matching game build. Verify the recognizable world change and a normal player's login before treating restoration as successful. Before an update, also retain the current installation and memory settings; an older executable may not read data already written by a newer build.

When the server starts but the connection fails#

SymptomCheck next
Client waits at “Getting server info”Compare builds, use the correct public address, inspect server-side Steam initialization and verify both UDP paths
Startup reports memory allocation failureCheck total available RAM and the heap settings used by the actual launcher
A different world appearsCheck the Linux account, its home directory and -servername; do not rename save folders blindly
Workshop item downloads but its mod is absentCompare generated Mods/WorkshopItems, dependencies and supported build
Players reconnect to changed data after a restartCheck graceful shutdown and restore a consistent world/database backup

For an unresolved failure, collect the startup version, relevant server configuration with passwords removed, the current console output and files under /srv/pz/Zomboid/Logs. Describe the first failed step. A working process, a listed server and a completed game login are separate observations; that distinction keeps the investigation focused.