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:
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#
Still logged in as pz:
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:
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:
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.
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:
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:
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:
(
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:
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:
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#
| Symptom | Check 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 failure | Check total available RAM and the heap settings used by the actual launcher |
| A different world appears | Check the Linux account, its home directory and -servername; do not rename save folders blindly |
| Workshop item downloads but its mod is absent | Compare generated Mods/WorkshopItems, dependencies and supported build |
| Players reconnect to changed data after a restart | Check 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.




