Выделенный сервер Valheim на Linux ставится в четыре шага: установить SteamCMD, создать пользователя, которому принадлежит только сервер, скачать приложение 896660 с анонимным входом и запустить valheim_server.x86_64 через копию штатного start_server.sh, который указывает в LD_LIBRARY_PATH собственную папку сервера linux64, а в SteamAppId - значение 892970. Откройте UDP 2456 и 2457, оберните скрипт в юнит systemd, который останавливает сервер сигналом SIGINT, чтобы тот успел сохраниться при выходе, и получите сервер, переживающий перезагрузки. Всё это занимает около четверти часа на свежей машине с Ubuntu или Debian, а большинство проблем возникает в трёх местах: запуск от root, правка скрипта, который Steam перезаписывает, и убийство процесса вместо остановки.
Эта статья - про установку. Что означают аргументы запуска, описано в справочнике по аргументам запуска Valheim, а общая картина - выбор мощности, админы, модификаторы мира - в руководстве по выделенному серверу Valheim.
Что нужно перед началом#
Сервер Valheim - это 64-битная Linux-сборка игры на Unity. Он работает на любом современном дистрибутиве x86-64; чаще всего берут Ubuntu 22.04 и 24.04 или Debian 12, и команды ниже рассчитаны именно на них. На ARM-машинах (Raspberry Pi, облачные инстансы Ampere) он нативно не запустится: сам SteamCMD существует только под x86, а эмуляция сервера через Box64 - это хобби-проект, а не способ хостить компанию игроков.
| Ресурс | Минимум | Комфортно для 10 игроков |
|---|---|---|
| RAM | 2 GB свободно | 4 GB свободно |
| CPU | 1 быстрое ядро | 2 ядра, высокая частота |
| Диск | 3 GB под установку | 10 GB с мирами и бэкапами |
| Сеть | доступны UDP 2456-2457 | то же, низкая задержка до игроков |
Память - это показатель, в котором люди ошибаются в обратную сторону: сам сервер скромен, но растёт вместе с исследованной частью мира и числом построенных элементов. Цифры по возрасту мира и размеру группы есть в статье сколько RAM нужно серверу Valheim. На маленьком VPS помните, что операционная система и SteamCMD тоже занимают свою долю: машина с 2 GB, на которой больше ничего не запущено, подойдёт для троих друзей и будет впритык для десятерых.
Ещё нужны sudo на машине и терминал, в котором вам комфортно. Если сервер совсем новый, сначала сделайте базовые вещи - обычный пользователь вместо root, SSH-ключи, обновления; это разобрано в статье первый час на новом VDS.
Установка SteamCMD на Ubuntu и Debian#
SteamCMD - консольный клиент Steam от Valve. Оба дистрибутива его упаковывают, но он лежит в несвободной части архива и требует 32-битных библиотек, поэтому сначала два подготовительных шага.
На Ubuntu включите компонент multiverse и архитектуру i386:
$ sudo add-apt-repository multiverse$ sudo dpkg --add-architecture i386$ sudo apt update$ sudo apt install steamcmdНа Debian 12 пакет находится в non-free. Добавьте contrib non-free к компонентам в списке источников (в /etc/apt/sources.list или в строку Components: файла /etc/apt/sources.list.d/debian.sources на более новых установках), затем:
$ sudo dpkg --add-architecture i386$ sudo apt update$ sudo apt install steamcmdУстановщик попросит принять лицензионное соглашение Steam; пользуйтесь стрелками и Enter. Бинарник окажется в /usr/games/steamcmd: для обычных пользователей эта папка есть в PATH по умолчанию, но не всегда внутри скриптов и юнитов systemd, поэтому везде, кроме интерактивной оболочки, указывайте полный путь.
Заодно стоит поставить несколько библиотек. Бэкенд кроссплея загружает libatomic1, и без неё сервер, запущенный с -crossplay, падает при старте с ошибкой об отсутствующей библиотеке. Часто сообщают, что на минимальных образах нужна и libpulse0, потому что рантайм Unity линкуется с ней даже без звука. Вреда от них нет:
$ sudo apt install libatomic1 libpulse0 ca-certificatesЕсли вы не хотите пользоваться пакетом дистрибутива, подойдёт и архив от Valve: скачайте steamcmd_linux.tar.gz, распакуйте в домашнюю папку пользователя сервера и запускайте ./steamcmd.sh вместо steamcmd. Команды при этом те же. Общая механика - что делает +force_install_dir, зачем нужен validate, как работают бета-ветки - описана в статье SteamCMD: подробный разбор.
Отдельный пользователь для сервера#
Не запускайте сервер от root и не запускайте его под своей обычной учётной записью. Отдельный аккаунт без sudo удерживает скомпрометированный или сбойный сервер внутри его домашней папки, делает владельцев файлов предсказуемыми и не даёт файлам мира оказаться во владении root после того, как кто-то один раз запустил скрипт через sudo.
$ sudo useradd --create-home --shell /bin/bash valheim$ sudo -iu valheimВсё дальнейшее, до раздела про systemd, делается под этим пользователем. Структура, которую использует эта статья:
| Путь | Что там лежит |
|---|---|
/home/valheim/server | Установка сервера из SteamCMD |
/home/valheim/server/start_valheim.sh | Ваша копия стартового скрипта |
/home/valheim/.config/unity3d/IronGate/Valheim | Папка сохранений по умолчанию: миры и файлы списков |
/home/valheim/Steam | Собственный кэш и логи SteamCMD |
Папка сохранений - самая важная. Если не передать -savedir, сервер пишет миры в worlds_local внутри ~/.config/unity3d/IronGate/Valheim того пользователя, от которого запущен, а файлы adminlist.txt, bannedlist.txt и permittedlist.txt лежат на уровень выше. Запустите сервер хоть раз от другого пользователя, и он спокойно создаст совершенно новый мир в его домашней папке - это самая частая причина жалоб «мой мир пропал» на Linux. Все пути на обеих платформах собраны в статье где Valheim хранит свои файлы.
Скачивание приложения 896660#
Выделенный сервер Valheim - это отдельное приложение Steam, не совпадающее с игрой. Сервер имеет номер 896660, клиент игры - 892970. Сервер скачивается с анонимным входом: ни владеть Valheim, ни передавать SteamCMD какой-либо аккаунт не нужно.
$ /usr/games/steamcmd +force_install_dir /home/valheim/server \ +login anonymous +app_update 896660 validate +quitПорядок важен: +force_install_dir должен стоять перед +login, а современный SteamCMD выводит предупреждение, если их поменять местами. Первый запуск обновляет сам SteamCMD, на это уходит минута и экран заполняется индикаторами прогресса, после чего скачивается 1-2 GB файлов сервера. Успех выглядит так:
Success! App '896660' fully installed.Если вы видите Error! App '896660' state is 0x202 after update job, значит, диск заполнен; 0x602 и похожие коды обычно означают проблему с правами на папку установки или прерванную загрузку. Сначала просто повторите ту же команду - SteamCMD продолжит с места остановки, - а если ошибка повторяется, проверьте df -h и владельца папки.
Эта же команда служит и командой обновления. Запускайте её после каждого патча Valheim при остановленном сервере. validate сверяет каждый файл с манифестом: это медленнее, но чинит всё, что повредили сбой или неосторожная правка; заодно он перезапишет ваши правки в файлах, которые поставляются с сервером, - именно поэтому в следующем разделе скрипт предлагается скопировать. О том, когда обновлять сервер для группы и что значит ошибка Incompatible version, если сделать это неправильно, рассказывает статья как обновить сервер Valheim.
start_server.sh, LD_LIBRARY_PATH и SteamAppId#
В установку входит пример стартового скрипта. Его содержимое - с поправкой на точные комментарии и на то, есть ли в строке запуска уже -crossplay (это зависит от сборки) - выглядит так:
#!/bin/bashexport templdpath=$LD_LIBRARY_PATHexport LD_LIBRARY_PATH=./linux64:$LD_LIBRARY_PATHexport SteamAppId=892970echo "Starting server PRESS CTRL-C to exit"# Tip: Make a local copy of this script to avoid it being overwritten by steam.# NOTE: Minimum password length is 5 characters & Password cant be in the server name.# NOTE: You need to make sure the ports 2456-2458 is being forwarded to your server./valheim_server.x86_64 -name "My server" -port 2456 -world "Dedicated" -password "secret"export LD_LIBRARY_PATH=$templdpathДве строки здесь делают настоящую работу, и именно из-за них запуск одного лишь valheim_server.x86_64 не работает.
LD_LIBRARY_PATH=./linux64 велит динамическому загрузчику искать библиотеки в собственной папке linux64, где лежит steamclient.so, нужный серверу для связи со Steam. Без неё вы получите [S_API FAIL] SteamAPI_Init() failed и сервер, который так и не зарегистрируется. Обратите внимание, что путь относительный: скрипт работает только при запуске из папки установки, поэтому в юните systemd ниже задан WorkingDirectory.
SteamAppId=892970 сообщает API Steam, какая это игра. Да, это номер клиента, а не сервера - так сервер Valheim представляется Steam, и замена на 896660 всё ломает.
Совет из комментария в скрипте стоит выполнить: сделайте копию. validate и каждое обновление возвращают start_server.sh к штатной версии, так что правки в нём пропадают при следующем патче. Ваша копия под своим именем переживёт всё:
#!/bin/bashcd "$(dirname "$0")"export LD_LIBRARY_PATH=./linux64:$LD_LIBRARY_PATHexport SteamAppId=892970exec ./valheim_server.x86_64 -nographics -batchmode \ -name "Longship Crew" -port 2456 -world "Midgard" \ -password "herring-barrel-42" -public 1 \ -saveinterval 900 -backups 4$ chmod +x /home/valheim/server/start_valheim.shТри отличия от примера сделаны намеренно. cd "$(dirname "$0")" заставляет относительный путь к библиотекам работать, откуда бы ни вызвали скрипт. -nographics -batchmode - стандартные флаги Unity для процесса без экрана; в примере их иногда нет, и сервер работает и без них, но с ними рантайм Unity не пытается инициализировать графику на машине, где её нет. А exec заменяет оболочку процессом сервера, поэтому SIGINT, который посылает systemd или Ctrl+C, попадает прямо в Valheim, а не в оболочку, которая может его не передать. Танец с templdpath пропустите: он нужен только тогда, когда скрипт подключают через source, а не запускают.
Первый запуск и что должно быть в логе#
В первый раз запустите скрипт вручную, под пользователем valheim, чтобы видеть, что происходит:
$ cd /home/valheim/server$ ./start_valheim.shПервый запуск нового мира идёт дольше любого следующего, потому что мир создаётся и сохраняется. Строки, которые стоит узнавать, примерно в том порядке, в каком они появляются:
Valheim version: l-0.xxx.xx (network version xx)Load world: Midgard (Midgard)Game server connectedSession "Longship Crew" with join code 483920 and IP 203.0.113.10:2456 is activeСтрока с версией зависит от патча; важна её форма. Load world с названием вашего мира подтверждает, что аргумент -world сработал. Если вы ждали существующий мир, а видите сообщения о генерации нового, значит, имя не совпадает с файлом в worlds_local - включая регистр букв. Game server connected означает, что регистрация в Steam прошла; если этой строки так и нет, поищите выше ошибки SteamAPI_Init: они говорят о неверном пути к библиотекам или SteamAppId. Код присоединения появляется только с -crossplay.
Остановите сервер через Ctrl+C и подождите. Вы должны увидеть, как мир сохраняется, прежде чем процесс завершится. Именно это сохранение по SIGINT - причина, по которой всё остальное в статье устроено именно так. Если сервер не стартует вовсе, в статье сервер Valheim падает при запуске разобраны сбои по сообщениям лога.
Файрвол и порты#
Valheim использует UDP 2456 для игрового трафика и UDP 2457 для запросов Steam, а в комментарии примера упомянут диапазон 2456-2458. Открыть все три порта ничего не стоит, и это покроет старые сборки, где использовался третий:
$ sudo ufw allow 2456:2458/udp comment 'Valheim'$ sudo ufw statusОбратите внимание на двоеточие в синтаксисе диапазона ufw и на /udp: правило для TCP Valheim ничего не даёт, и это самая частая причина, по которой сервер работает, но никто не может его найти. На облачном VPS часто есть и второй файрвол - в панели провайдера (группа безопасности), и ему нужно такое же правило. Дома пробросьте тот же диапазон UDP на роутере на локальный адрес машины. Руководство по файрволу ufw описывает настройки по умолчанию, которые нужно задать до включения ufw на удалённой машине: включите его, не разрешив SSH, и сами себя заблокируете.
Если вы меняете -port, сдвигается всё остальное: порт запросов всегда на единицу выше игрового. Два сервера на одной машине требуют двух непересекающихся диапазонов, например 2456-2458 и 2466-2468. Подробности - в статье порты Valheim 2456-2458.
Проверяйте снаружи своей сети: подключитесь в игре по IP как your.address:2456. Если так работает, а в общем списке сервера всё ещё нет, то с сервером всё в порядке, а список просто медленный - см. сервер Valheim не отображается в списке.
Запуск как служба systemd#
Сервер, запущенный из SSH-сессии, умирает вместе с ней. tmux или screen сохраняют его, но не переживают перезагрузку и не перезапускают его после сбоя. Юнит systemd делает и то и другое и - если настроен правильно - ещё и останавливает его чисто.
[Unit]Description=Valheim dedicated serverWants=network-online.targetAfter=network-online.target[Service]Type=simpleUser=valheimGroup=valheimWorkingDirectory=/home/valheim/serverExecStartPre=/usr/games/steamcmd +force_install_dir /home/valheim/server +login anonymous +app_update 896660 +quitExecStart=/home/valheim/server/start_valheim.shKillSignal=SIGINTTimeoutStopSec=120Restart=on-failureRestartSec=15[Install]WantedBy=multi-user.target$ sudo systemctl daemon-reload$ sudo systemctl enable --now valheim$ journalctl -u valheim -fСтроки, которые имеют значение:
KillSignal=SIGINTзаставляетsystemctl stopвести себя как Ctrl+C, и мир сохраняется. Сигнал по умолчанию,SIGTERM, не гарантирует такого же чистого завершения, а когда истекает таймаут, systemd присылаетSIGKILL, после которого ничего не сохраняется.TimeoutStopSec=120даёт большому миру время дописать данные. Обычно хватает и 90 секунд по умолчанию; увеличение ничего не стоит.ExecStartPreобновляет сервер при каждом запуске, так что перезапуск после патча Valheim приводит вас к актуальной версии. Уберите эту строку, если используете моды BepInEx: автоматическое обновление в день патча ломает моды раньше, чем их авторы успевают подстроиться, а выбирать этот момент лучше самому. Кроме того, каждый запуск становится медленнее на время проверки SteamCMD.Restart=on-failureвозвращает сервер после сбоя, но не после намеренной остановки.
Вывод идёт в журнал, поэтому journalctl -u valheim - это лог сервера, по которому можно искать с --since и -g. Если вы предпочитаете файл, добавьте в строку запуска -logFile /home/valheim/valheim.log. Подробнее о юнитах, в том числе об ограничении ресурсов через MemoryMax=, рассказывает статья службы systemd для ваших приложений.
Для еженедельного перезапуска хватит таймера или записи в cron от root, выполняющей systemctl restart valheim в тихий час. Перезапуск сбрасывает рост памяти у долго работающего мира, а при наличии строки ExecStartPre заодно подтягивает обновления.
Бэкапы, которых установка не даёт#
Флаг сервера -backups хранит ротируемые копии мира рядом с самим миром, на том же диске. Это защита от неудачного сохранения, а не от умершего диска или удалённой папки. Копируйте всю папку сохранений в другое место по расписанию:
$ tar -czf /backup/valheim-$(date +%F).tar.gz \ -C /home/valheim/.config/unity3d/IronGate ValheimЗапуск этой команды из cron при работающем сервере может застать мир посреди сохранения; надёжнее копировать самую свежую целую пару .db и .fwl или делать архив сразу после плановой перезагрузки. Полная стратегия, включая восстановление и распознавание повреждённого мира, описана в статье бэкапы сервера Valheim и повреждение мира.
Если вы не хотите заниматься всем этим сами, панельный хостинг делает то же самое за формой: на RE:NODE вкладка Startup содержит аргументы из вашей строки запуска, оба порта UDP выделяются вместе с тарифом, Restart отправляет чистую остановку, чтобы мир сохранился, а бэкапы уходят с машины и восстанавливаются одной кнопкой.
FAQ#
Нужно ли владеть Valheim, чтобы скачать сервер?
Нет. Приложение 896660 скачивается с +login anonymous. Копия игры нужна, чтобы играть на сервере, а не чтобы его хостить.
Почему серверу нужен SteamAppId 892970, если его собственный номер 896660?
Сервер обращается к API Steam от имени игры, а API определяет игру по номеру клиента. 896660 - это лишь депо, которое скачивает SteamCMD. Задайте в SteamAppId любое другое значение, и регистрация в Steam не пройдёт.
Можно ли править start_server.sh напрямую?
Можно, но следующий app_update ... validate или патч игры вернёт оригинал вместе с вашими настройками. Храните копию под другим именем и запускайте её.
Стоит ли запускать сервер внутри screen или tmux?
Только для быстрой проверки. Мультиплексор оставляет процесс жить после выхода из системы, но ничего не делает после перезагрузки или сбоя, и легко закрыть сессию вместо того, чтобы остановить сервер. Юнит systemd с KillSignal=SIGINT - это конфигурация, при которой сохранения не теряются.
Как добавить админов на Linux-сервере?
Впишите ID каждого игрока на отдельной строке в adminlist.txt в папке сохранений - для пользователя valheim по умолчанию это ~/.config/unity3d/IronGate/Valheim. Файл перечитывается, пока сервер работает. Форматы ID, в том числе префиксы кроссплея, описаны в руководстве по файлам списков Valheim.
Linux-сервер работает хуже Windows-сервера?
Не так, чтобы группа это заметила. Это одна и та же сборка Unity для разных платформ, а на маленькой машине у Linux меньше фоновых накладных расходов. Случаи, когда платформа всё же важна, разобраны в статье Linux или Windows для игровых серверов.


