2026-08-08 11:57:50 +02:00
2026-08-08 11:56:08 +02:00
2026-08-08 11:56:08 +02:00
2026-08-08 11:56:08 +02:00
2026-08-08 11:56:08 +02:00
2026-08-08 11:57:50 +02:00

Zomboid client-hosted → dedicated server

Convert a locally hosted Project Zomboid multiplayer world into a dedicated server layout, then run it with Docker.

The world save format is the same (B42 Saves/Multiplayer/…). Conversion is packaging + naming + players.db world rename + mod recovery — not a binary rewrite.

Layout

Paths below are relative to the repo root (parent of this converter/ folder):

Path Role
original/ Source saves / zips (do not edit the zips)
converter/ This crate — Rust CLI (zomboid-converter)
server/ Docker dedicated server (docker-compose.yml, .env)
server/server-data/ Zomboid userdir (Saves, Server, db, Logs)
server/server-files/ Game install (Steam download target)

Typical source pair from a host:

  • Saves/Multiplayer/<WorldName>/ — authoritative world (use this)
  • Saves/Multiplayer/<WorldName>_player/ — client cache (ignore)

Server settings live separately under Zomboid/Server/<WorldName>.* on the host machine. They are not inside the world folder.

Prerequisites

  • Rust toolchain (for the converter)
  • Docker + Docker Compose
  • Optional: local Steam workshop cache for app 108600 (to resolve WorkshopItems)

Converter

cd converter
cargo build --release

cargo run --release -- \
  --input ../original/serverb42stable \
  --output ../server/server-data \
  --server-name pzserver \
  --workshop-dir /path/to/steamapps/workshop/content/108600 \
  --force

--input may be a world directory or a .zip (opened read-only; extracted to a temp dir). Paths ending in _player are rejected.

Arguments

Flag Description
-i, --input Hosted world dir or zip
-o, --output Dedicated server-data root
-n, --server-name World + config basename (default: pzserver)
--workshop-dir …/workshop/content/108600 — fills WorkshopItems=
--server-config Optional host Server/ dir to copy/rename configs
--password Server join password (Password= in ini); overrides .env
--env-file .env for password (default: <output>/../.env)
--force Replace existing Saves/Multiplayer/<server-name>/

What it does

  1. Copies the world into output/Saves/Multiplayer/<server-name>/
  2. Skips syncthing conflict sidecars (*-ZwS1g3qi*), *.db-journal, and player-cache junk
  3. Sets networkPlayers.world in players.db to <server-name>
  4. Recovers mod IDs from WorldDictionaryReadable.lua into Server/<name>.ini (Mods=)
  5. If --workshop-dir is set, resolves Steam workshop IDs (WorkshopItems=)
  6. Optionally sets Password= from --password or SERVER_PASSWORD / PASSWORD in .env

It does not overwrite db/<server-name>.db (accounts / whitelist stay managed by the server).

Characters / login

Characters bind to the account username in players.db (networkPlayers.username), not Steam display name. Players must log in with that exact username (or you rename the column before they join).

Dedicated server (Docker)

cd ../server
cp .env.example .env   # if needed; set passwords / SERVER_NAME
docker compose up -d
docker compose logs -f

Important .env keys:

  • SERVER_NAME — must match converter --server-name (default pzserver)
  • ADMIN_USERNAME / ADMIN_PASSWORD — admin account
  • RCON_PASSWORD — RCON
  • SERVER_PASSWORD — optional join password for the converter (Password= in ini)

Ports: 16261/udp, 16262/udp, 27015/tcp.

Stop the container before re-running the converter with --force.

  1. Stop the dedicated server.
  2. Copy the host world into original/ (keep zips untouched as backups).
  3. Ideally also copy the hosts Zomboid/Server/<WorldName>.ini (+ _SandboxVars.lua, spawn files) and pass --server-config.
  4. Run the converter with --workshop-dir and --force.
  5. Start Docker; wait until workshop items finish installing (Workshop: … Installed in logs).
  6. Join with the same username as in the hosted players.db.

Known gaps / caveats

Item Notes
Host SandboxVars / spawn / Map= Not in the world save. Without --server-config, the dedicated defaults remain.
Mods with no WorldDictionary entries Pure Lua/QoL mods may not appear in recovered Mods=.
Workshop versions IDs are resolved from your local workshop cache; newer mod builds than the host used can cause chunk LENGTH mismatch / blam errors and odd world state (e.g. zombies in cleared bases).
ZombieMigrate Dedicated sandbox may allow migration even when respawn is off; align sandbox with the host when possible.
Running without mods first Can rewrite WorldDictionary and map chunks. Re-import from original/ if that happened.

Example passwords

# ../server/.env (next to docker-compose)
SERVER_PASSWORD=hunter2

# or CLI override (from this directory)
cargo run --release -- … --password 'hunter2'
Description
No description provided
Readme 64 KiB
Languages
Rust 100%