Свой сервер Project Zomboid на VPS работает круглосуточно, и друзья могут заходить в общий мир в любое время, не дожидаясь, пока включится чей-то компьютер. Вы сами решаете, сколько будет игроков, включён ли PVP и кто может зайти. В этой статье мы установим выделенный сервер через SteamCMD, ограничим его память, откроем нужные порты, настроим автозапуск с безопасной остановкой и резервные копии мира. Все шаги мы повторили на тестовом сервере с Debian 12. На момент проверки актуальная версия игры Build 42.21.
Как устроен сервер Project Zomboid
Сервер Project Zomboid – это отдельная бесплатная программа, которую Valve раздаёт через Steam под номером приложения 380870. Для установки не нужны ни аккаунт Steam, ни купленная игра, потому что скачивать её можно анонимно, а делает это консольный клиент SteamCMD. Игра написана на Java, и сервер привозит собственную Java 25 в папке jre64, поэтому ставить её отдельно не нужно. Программа и данные при этом лежат в разных местах. Файлы игры находятся в папке сервера, а мир, учётные записи игроков, настройки и журналы хранятся в папке Zomboid в домашней папке пользователя. Благодаря этому обновление через SteamCMD заменяет саму игру и не трогает ваш мир.
Игроки подключаются по протоколу UDP. При запуске сервер сам пишет в журнале, что слушает порт 16261 для соединений Steam и порт 16262 для соединений RakNet, а клиентам советует использовать порт 16261. Мы проверили оба порта снаружи. На 16261 сервер отвечает на запросы Steam о своём имени и числе игроков, а на 16262 отвечает на служебный пинг RakNet, поэтому в брандмауэре нужно открыть оба порта. Если порты закрыты, UDP-пакеты просто пропадают, а сервер молчит, потому что до него ничего не доходит. Именно так наш сервер выглядел для проверки снаружи, пока в UFW не было правила.
Главным ресурсом сервера является память. В файле ProjectZomboid64.json лимит памяти Java по умолчанию стоит -Xmx8g, то есть 8 ГБ, и для небольшого VPS это слишком много. Мы ставим 3 ГБ. При этом процесс занимает больше, чем указанный лимит, потому что к куче добавляется служебная память самой Java. На нашем сервере с -Xmx3g процесс занял около 4 ГБ, а с -Xmx2g около 2,9 ГБ, то есть лимит плюс примерно 0,9 ГБ. Сервер использует сборщик мусора ZGC (параметр -XX:+UseZGC в том же файле), и занятая память не освобождается в простое. Через шесть минут после запуска без единого игрока процесс по-прежнему занимал те же 3,9 ГБ, так что считайте память с запасом.
Build 42 и Build 41
Ветка public в SteamCMD, которую вы получите по умолчанию, сейчас содержит Build 42. В нашем журнале запуска написано version=42.21.0, а в официальных объявлениях Steam версия 42.21 названа стабильной. Кроме неё в SteamCMD есть ветки unstable для тестирования, legacy41 с Build 41.78.21 и 42.19 с Build 42.19.2. Выбрать ветку можно параметром -beta, например +app_update 380870 -beta legacy41 validate. Мы проверили, что SteamCMD принимает такой параметр и начинает скачивать сборку Build 41, она занимает около 5 ГБ. Версия клиента у игроков должна совпадать с версией сервера. Игру на сервере Build 41 мы не запускали и переход между ветками не проверяли, поэтому перед ним сделайте копию мира.
Что понадобится
- Сервер с Debian 12 и не меньше 6 ГБ памяти, например тариф DE-RZ9-3. При
-Xmx3gпроцесс занимает около 4 ГБ, а ещё нужно около 7 ГБ на диске. Если сервера ещё нет, закажите его по инструкции. На тарифе DE-RZ9-2 с 4 ГБ сервер запускается с-Xmx2g, но запас небольшой, а работу под нагрузкой игроков мы не проверяли. - Подключение по SSH, например через Termius. Команды выполняются от имени
root, если не сказано иначе. - Игра Project Zomboid у каждого игрока, той же версии, что и сервер.
Что мы проверили, а что нет
Мы не запускали клиент игры и не заходили на сервер как игрок. Мы проверили другое. Сервер запускается, слушает порты 16261 и 16262 по UDP и отвечает на запросы Steam и RakNet с другого компьютера. Остановка, перезапуск, обновление и резервные копии работают. Нагрузку от игроков, моды и работу в списке серверов игры мы не проверяли.
Шаг 1. Установите библиотеки и создайте пользователя
SteamCMD – это 32-разрядная программа, и на 64-разрядном Debian ей нужны две библиотеки. Заодно поставьте screen, он понадобится для консоли сервера.
apt update
apt install -y screen curl ca-certificates lib32gcc-s1 lib32stdc++6Запускать сервер от имени root небезопасно, поэтому создадим для него отдельного пользователя zomboid с домашней папкой /opt/zomboid. Подробнее о пользователях рассказано в статье про пользователей Linux.
useradd -r -m -d /opt/zomboid -s /bin/bash zomboidШаг 2. Установите SteamCMD
Войдите под пользователем zomboid и скачайте SteamCMD с сервера Valve. Команды шагов со 2-го по 5-й выполняются от его имени.
su - zomboid
mkdir ~/steamcmd && cd ~/steamcmd
curl -fsSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar zxf -Это маленький загрузчик, полная программа скачается при первом запуске.
Шаг 3. Скачайте сервер
Команда ниже входит в Steam анонимно и скачивает приложение 380870 в папку /opt/zomboid/server. При первом запуске SteamCMD сначала обновит сам себя, около 41 МБ, а затем начнёт загрузку сервера.
./steamcmd.sh +force_install_dir /opt/zomboid/server +login anonymous +app_update 380870 validate +quitНа нашем сервере скачалось около 2 ГБ, а на диске сервер занял около 7 ГБ. Установка заняла примерно три минуты. В конце SteamCMD пишет Success! App '380870' fully installed.
В папке сервера теперь лежит скрипт запуска start-server.sh, собственная Java в jre64 и файл ProjectZomboid64.json с настройками памяти.
Шаг 4. Ограничьте память
Замените в ProjectZomboid64.json лимит 8 ГБ на 3 ГБ. Если у вас тариф с 4 ГБ, поставьте -Xmx2g.
sed -i 's/-Xmx8g/-Xmx3g/' ~/server/ProjectZomboid64.json
grep Xmx ~/server/ProjectZomboid64.jsonВ ответе должна быть строка "-Xmx3g",. Остальные параметры в файле лучше не трогать.
Проверка файлов сбрасывает этот параметр
Если запустить SteamCMD с параметром validate, он вернёт ProjectZomboid64.json к исходному виду, и лимит снова станет 8 ГБ. Мы проверили это на тестовом сервере. Как обновлять сервер и не потерять лимит, показано в разделе про обновление ниже.
Шаг 5. Запустите сервер первый раз
Первый запуск нужно сделать вручную, потому что сервер спросит пароль администратора.
cd ~/server
./start-server.shСначала сервер напечатает много строк о загрузке игры. Затем появятся строки Enter new administrator password и Confirm the password. Введите придуманный пароль и нажмите Enter, затем повторите его для подтверждения. После этого сервер сообщит Administrator account 'admin' created. Так создаётся учётная запись admin, под которой вы будете входить в игру как администратор.

Пароль администратора сервер просит при первом запуске, пароли на экране скрыты
Пароль виден, пока вы его вводите
В нашем терминале введённый пароль отображался на экране открытым текстом. Следите, чтобы за спиной никого не было, и не делайте скриншотов этого окна. Лучше сгенерировать пароль в менеджере паролей и вставить его. Не используйте параметр -adminpassword в скрипте запуска, ведь пароль тогда останется в открытом виде в файле.
Дальше сервер создаёт мир. После ввода пароля это заняло у нас около 50 секунд. Когда в журнале появится строка SERVER STARTED, сервер готов.

Сервер слушает порты 16261 и 16262
Остановите сервер командой quit, введя её в этом же окне. Она сохраняет мир и завершает сервер, у нас это заняло около 10 секунд. После остановки вернитесь в root. Дальше сервер будет запускаться сам.
exitНастройки и мир создались в папке /opt/zomboid/Zomboid. Главное, что там лежит.
Server/servertest.iniс основными настройками сервера.Server/servertest_SandboxVars.luaс правилами мира, например количеством зомби и скоростью смены дня и ночи.Saves/Multiplayer/servertestс самим миром.db/servertest.dbс учётными записями игроков.Logsс журналами сервера.
Имя servertest – это имя сервера по умолчанию, по нему называются все эти файлы.
Шаг 6. Настройте сервер
Откройте файл настроек. Меняйте его при остановленном сервере, потому что сервер сам переписывает этот файл при запуске.
nano /opt/zomboid/Zomboid/Server/servertest.iniРядом с каждым параметром в файле есть комментарий на английском. Самое важное мы собрали в таблицу, значения по умолчанию взяты из созданного файла.
| Параметр | По умолчанию | Что означает |
|---|---|---|
PublicName | My PZ Server | Название сервера в списках игры и Steam |
Password | пусто | Пароль, который нужно знать, чтобы зайти на сервер |
MaxPlayers | 32 | Сколько игроков может быть на сервере одновременно, администраторы не считаются |
PVP | true | Игроки могут ранить и убивать друг друга |
Open | true | Игрок может зайти без заранее созданной учётной записи, она создаётся при первом входе |
Public | false | Показывать сервер в списке серверов игры |
PauseEmpty | true | Игровое время стоит, пока на сервере никого нет |
SaveWorldEveryMinutes | 0 | Как часто сохранять мир. При нуле карта сохраняется в основном тогда, когда игроки уходят из загруженной области |
UPnP | true | Попытка настроить роутер автоматически. На VPS роутера нет, поэтому ставьте false |
Для сервера с друзьями мы поменяли несколько значений. Эти строки мы проверили на тестовом сервере.
PublicName=Friends Server
Password=ваш_пароль
MaxPlayers=8
PVP=false
UPnP=false
SaveWorldEveryMinutes=15После запуска сервера мы проверили, что настройки подхватились. Команда showoptions в консоли показала новые значения, а запрос Steam с другого компьютера вернул имя сервера, число мест 8 и признак того, что нужен пароль.
Пароль на сервер и закрытый список
Для компании друзей достаточно задать Password, этот пароль вы просто сообщаете друзьям. Если нужен строгий контроль, поставьте Open=false. Тогда учётные записи игроков создаёте вы сами командой adduser Имя Пароль в консоли сервера. Мы проверили эту команду, сервер ответил, что пользователь создан.
Шаг 7. Откройте порты 16261 и 16262
Откройте оба порта в брандмауэре UFW. Порты нужны именно по UDP.
ufw allow 16261:16262/udpПодробнее о брандмауэре рассказано в статье про UFW.
Сервер нужно проверить из интернета, то есть с другого компьютера. Для этого мы написали маленький скрипт на Python 3, он отправляет серверу стандартный запрос Steam на информацию о сервере (A2S_INFO). Сохраните его в файл pz-check.py на своём компьютере.
import socket, sys
host, port = sys.argv[1], 16261
req = b"\xff\xff\xff\xffTSource Engine Query\x00"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(3)
try:
s.sendto(req, (host, port))
data, _ = s.recvfrom(4096)
if data[4:5] == b"A": # сервер просит повторить запрос с проверочным кодом
s.sendto(req + data[5:9], (host, port))
data, _ = s.recvfrom(4096)
print("Сервер отвечает, имя:", data[6:data.index(0, 6)].decode())
except socket.timeout:
print("Ответа нет, порт закрыт или сервер не запущен")Запустите его, указав IP-адрес VPS. Мы проверили скрипт дважды, до и после правила в UFW.
python3 pz-check.py IP-адрес-сервера
Пока порт закрыт, ответа нет. После правила в UFW сервер называет своё имя
Если вы видите имя сервера, то порт 16261 доступен из интернета. Порт 16262 мы отдельно проверили служебным пингом RakNet, он тоже ответил.
Шаг 8. Настройте автозапуск
Чтобы сервер работал в фоне, запускался вместе с VPS и поднимался после сбоя, оформим его как службу systemd. Как устроены службы, подробно рассказано в статье про systemd. Консоль сервера мы, как и в статье про сервер Minecraft, запустим внутри screen. Через неё сервер получает команды, в том числе команду сохранения и остановки.
Сначала создайте скрипт остановки. Он отправляет в консоль команду quit, чтобы сервер сохранил мир, и ждёт, пока сервер завершится.
nano /opt/zomboid/stop.sh#!/bin/sh
# Отправляет команду quit в консоль сервера и ждёт, пока сервер сохранит мир и завершится
screen -p 0 -S zomboid -X stuff "quit$(printf '\r')"
while kill -0 "$MAINPID" 2>/dev/null; do sleep 1; doneСделайте скрипт исполняемым и создайте службу.
chmod +x /opt/zomboid/stop.sh
chown zomboid:zomboid /opt/zomboid/stop.sh
nano /etc/systemd/system/zomboid.service[Unit]
Description=Project Zomboid server
After=network-online.target
Wants=network-online.target
[Service]
User=zomboid
WorkingDirectory=/opt/zomboid/server
ExecStart=/usr/bin/screen -DmS zomboid /opt/zomboid/server/start-server.sh
ExecStop=/opt/zomboid/stop.sh
Restart=always
RestartSec=10
TimeoutStopSec=120
[Install]
WantedBy=multi-user.targetВключите автозапуск и запустите сервер.
systemctl daemon-reload
systemctl enable --now zomboid
systemctl status zomboid
Служба работает, сервер слушает оба порта
После запуска службы сервер загружается около 40 секунд, а затем начинает отвечать на запросы. Управлять им теперь нужно через systemd.
systemctl stop zomboidсохраняет мир и выключает сервер.systemctl restart zomboidперезапускает сервер.systemctl start zomboidвключает сервер.
Мы проверили, как служба ведёт себя в разных ситуациях.
- Остановка командой
systemctl stop zomboidзаняла около 10 секунд, а в журнале сервера появились записи о командеquitи о сохранении мира. - Когда мы принудительно завершили Java, systemd поднял сервер заново через 10 секунд. Скрипт
start-server.shзавершается с кодом 0 даже после такого сбоя, поэтому нужен именноRestart=always. - Команда
quit, введённая прямо в консоли, тоже приводит к перезапуску, а не к выключению. Чтобы выключить сервер, используйтеsystemctl stop zomboid.
Игровые сообщения в journalctl не попадают, потому что сервер пишет их в консоль внутри screen. Журналы лежат в /opt/zomboid/Zomboid/Logs, а последний запуск записан в файле /opt/zomboid/Zomboid/server-console.txt. Подробнее о журналах рассказано в статье про логи Linux.
Шаг 9. Консоль сервера и подключение игроков
Чтобы открыть консоль сервера, подключитесь к сессии screen.
su - zomboid -c "screen -r zomboid"Выйти из консоли и оставить сервер работать можно сочетанием Ctrl + A, затем D. Подробнее о работе с screen рассказано в отдельной статье. Список всех команд выводит help. Вот те, что мы проверили.
playersпоказывает подключённых игроков.saveсохраняет мир сразу.servermsg "Текст"отправляет сообщение всем игрокам.adduser Имя Парольсоздаёт учётную запись игрока.quitсохраняет мир и останавливает сервер, после чего служба запускает его снова.
Игрокам нужно ввести в игре IP-адрес VPS, порт 16261, пароль сервера, если вы его задали, а затем имя и пароль своего персонажа. На открытом сервере с Open=true учётная запись создаётся при первом входе. Вместо IP-адреса удобно использовать домен, как это сделать, описано в статье про привязку домена. Чтобы войти администратором, используйте имя admin и пароль из шага 5.
Обновление сервера
Когда выходит новая версия игры, клиенты обновляются через Steam сами, а версия сервера должна с ней совпадать. В обновлении 42.21 разработчики добавили уведомление для игроков, которые пытаются зайти на сервер другой версии. Сервер обновляется отдельно. Мы собрали скрипт, который останавливает сервер, обновляет его, возвращает лимит памяти и запускает снова.
nano /usr/local/bin/zomboid-update.sh#!/bin/sh
# Останавливает сервер, обновляет его через SteamCMD, возвращает лимит памяти и запускает снова
systemctl stop zomboid
su - zomboid -c "~/steamcmd/steamcmd.sh +force_install_dir /opt/zomboid/server +login anonymous +app_update 380870 +quit"
su - zomboid -c "sed -i 's/-Xmx[0-9]*[gGmM]/-Xmx3g/' /opt/zomboid/server/ProjectZomboid64.json"
systemctl start zomboidЕсли вы выбрали другой лимит памяти, замените 3g в скрипте. Сделайте скрипт исполняемым и запускайте, когда нужно обновиться.
chmod +x /usr/local/bin/zomboid-update.sh
zomboid-update.shКогда обновлений нет, SteamCMD пишет Success! App '380870' already up to date. У нас весь скрипт отработал за 14 секунд. В скрипте нет параметра validate намеренно. Мы проверили, что обычное обновление не трогает изменённый ProjectZomboid64.json, а проверка файлов с validate возвращает в нём 8 ГБ.

Проверка файлов заняла около минуты и заменила один маленький файл с настройками памяти
validate нужен только для ремонта, например если файлы игры повредились. После него снова запустите команду из шага 4.
Резервные копии мира
Мир лежит в /opt/zomboid/Zomboid/Saves, а учётные записи игроков в /opt/zomboid/Zomboid/db. Сервер сам делает копии при запуске и при смене версии и кладёт их в /opt/zomboid/Zomboid/backups, по умолчанию он хранит пять копий (параметр BackupsCount). Но они лежат на том же диске, что и мир. Для надёжности добавим свой скрипт. Он сохраняет мир командой save, упаковывает мир, учётные записи и настройки в архив в папке /opt/zomboid/archives и хранит 7 последних архивов. Сервер на время копирования не останавливается.
nano /opt/zomboid/backup.sh#!/bin/sh
# Сохраняет мир, архивирует его вместе с настройками и хранит 7 последних архивов
cd /opt/zomboid || exit 1
screen -p 0 -S zomboid -X stuff "save$(printf '\r')"
sleep 10
mkdir -p archives
tar -czf "archives/zomboid-$(date +%F-%H%M).tar.gz" Zomboid/Saves Zomboid/db Zomboid/Server
ls -1t archives/zomboid-*.tar.gz | tail -n +8 | xargs -r rm --Сделайте скрипт исполняемым и добавьте его в расписание пользователя zomboid, например каждую ночь в 4:00.
chmod +x /opt/zomboid/backup.sh
chown zomboid:zomboid /opt/zomboid/backup.sh
echo "0 4 * * * /opt/zomboid/backup.sh" | crontab -u zomboid -Мы проверили скрипт вручную и по расписанию, оба раза архив появился. В свежем мире архив занял меньше 1 МБ, в реальной игре он будет расти вместе с миром. Подробнее о расписании рассказано в статье про cron. Копии на этом же сервере не спасут, если пропадёт сам сервер, поэтому время от времени скачивайте архивы к себе или отправляйте их на другой сервер, например командой rsync.
Чтобы восстановить мир, остановите сервер, распакуйте нужный архив поверх папки /opt/zomboid и запустите сервер. Мы проверили восстановление, сервер после него запустился.
systemctl stop zomboid
su - zomboid -c "tar -xzf /opt/zomboid/archives/ИМЯ-АРХИВА.tar.gz -C /opt/zomboid"
systemctl start zomboidЧастые вопросы
./steamcmd.sh: cannot execute: required file not found
Полностью она выглядит как ./steamcmd.sh: line 85: /opt/zomboid/steamcmd/linux32/steamcmd: cannot execute: required file not found. Не хватает 32-разрядных библиотек. Мы получили это сообщение, когда удалили lib32gcc-s1 и lib32stdc++6. Установите их, как описано в шаге 1.
Служба работает, а сервер не отвечает, в консоли Enter new administrator password
Сервер при первом запуске ждёт пароль администратора, а в службе вводить его некому. Мы воспроизвели это на новом имени сервера. Служба оставалась active, но порты 16261 и 16262 никто не слушал, а проверка снаружи не получала ответа. Остановите службу командой systemctl stop zomboid, выполните шаг 5 вручную, введите пароль и дождитесь SERVER STARTED, затем остановите сервер командой quit и снова запустите службу.
Красные ERROR при запуске, libjsig.so и Property Name not found
В журнале запуска мы видели две группы строк с ошибками, и обе безвредны.
- ERROR: ld.so: object 'libjsig.so' from LD_PRELOAD cannot be preloaded появляется при запуске. В конце строки сервер пишет, что пропустил эту библиотеку (
ignored), и работает дальше. - IsoPropertyType.lookupOrDefaultStr> Exception thrown с текстом вроде
Property Name not found: ladderWи длинным стеком вызовов появляется при создании нового мира несколько раз.
Если после них в журнале есть строка SERVER STARTED, всё в порядке.
If the server hangs here, set UPnP=false
Это строка из журнала запуска, она идёт сразу за сообщением Router detection/configuration starting. Пока параметр UPnP равен true, сервер ищет в сети роутер, чтобы открыть порты. На VPS роутера нет. На нашем сервере запуск ждал около 12 секунд и писал No UPnP-enabled Internet gateway found, после чего запускался. Поставьте UPnP=false в servertest.ini, и запуск станет быстрее на это время.
Ответа нет, порт закрыт или сервер не запущен
Так отвечает наш скрипт pz-check.py, когда с другого компьютера не приходит ответ. Мы получили это сообщение, пока в UFW не было правила для UDP. Проверьте, что служба работает, командой systemctl status zomboid, что правило есть, командой ufw status, и что порты слушаются, командой ss -ulpn | grep 1626. Откройте именно UDP, правило для TCP не поможет.
Killed process (ProjectZomboid6) в журнале ядра
Сервер внезапно завершился без сообщений в консоли. Так бывает, когда процесс занял больше памяти, чем есть на сервере или выделено службе, и систему защитило от нехватки памяти ядро. Проверьте командой journalctl -k | grep -i "killed process". Мы воспроизвели это, ограничив службу 2 ГБ памяти при лимите Java 3 ГБ, и ядро написало Memory cgroup out of memory: Killed process … (ProjectZomboid6). Уменьшите -Xmx в ProjectZomboid64.json или возьмите тариф с большим объёмом памяти.
После обновления сервер снова занимает 8 ГБ
Вы запускали SteamCMD с параметром validate, и он вернул ProjectZomboid64.json к исходному виду. Мы получили это, когда проверили файлы, SteamCMD скачал 359 байт, и в файле снова появился -Xmx8g. Верните лимит командой из шага 4 и обновляйте сервер скриптом из раздела про обновление.
Наши ресурсы
Telegram-канал: https://t.me/f3cloud_news
Официальный сайт: https://f3cloud.com