RE:NODE

Valheim server jako služba systemd: unit, restarty a logy

Text: Tým RE:NODE
13 min čtení


Server Valheimu na Linuxu patří pod systemd: jeden soubor unit v /etc/systemd/system/valheim.service, který spouští server pod vlastním uživatelem, startuje ho při bootu, restartuje ho po pádu a - řádek, na který se zapomíná - zastavuje ho přes KillSignal=SIGINT, aby se svět při ukončení uložil. Přidej TimeoutStopSec=120, aby měl velký svět čas dopsat data, log čti přes journalctl -u valheim a pro týdenní restart a noční zálohu používej místo cronu timery systemd. Tenhle článek staví unit řádek po řádku, vysvětluje, před čím jednotlivá nastavení chrání, a prochází situace, které se pokazí: smyčky pádů, zastavení, které skončí zabitím procesu, mizející logy a víc serverů na jednom stroji.

Předpokládá, že server už je nainstalovaný přes SteamCMD pod uživatelem valheim v /home/valheim/server a že máš vlastní startovací skript. Pokud ne, instalace serveru Valheim na Linuxu přes SteamCMD tě k tomu dovede zhruba za patnáct minut a tenhle článek navazuje tam, kde končí její část o systemd.

Proč systemd a ne tmux nebo screen#

U serveru, který necháš běžet měsíce, musí platit tři věci: po restartu stroje naběhne sám, po pádu naběhne sám a na požádání se zastaví čistě. Proces spuštěný z SSH relace s ní zaniká. tmux a screen ho udrží naživu i po odpojení, proto je používá tolik návodů, ale ani jeden nic nespouští při bootu a ani jeden si nevšimne, že proces skončil. O pádu serveru se dozvíš, až ti někdo napíše.

systemd zvládá všechny tři věci a přidává věci, které terminálový multiplexer nikdy mít nebude:

  • Řízené zastavení. systemd pošle signál, který si zvolíš, počká tak dlouho, jak povolíš, a teprve pak přitvrdí. Se správným signálem je každé plánované zastavení zároveň uložením.
  • Prohledávatelný log. Všechno, co server vypíše, jde do journalu, s časovými značkami, přežije restarty a dá se filtrovat podle času i vzoru.
  • Pravidlo restartu s brzdou. Server se po selhání restartuje, ale když padá ve smyčce, systemd to vzdá, místo aby disk zatěžoval rozbitým světem.
  • Limity zdrojů. Strop paměti, váha CPU a omezení souborového systému jsou vždy jeden řádek.
  • Timery. Plánované restarty a zálohy, které se logují, vidíš je v jednom seznamu a mohou záviset na samotné službě.

Přicházíš o interaktivní konzoli. Dedicated server Valheimu ale stejně nečte příkazy ze standardního vstupu - admin příkazy se píšou v konzoli F5 herního klienta a píše je někdo uvedený v adminlist.txt - takže u téhle hry je ztráta téměř nulová. Pokud chceš připojitelnou konzoli z jiných důvodů, je to hlavní argument pro LinuxGSM, který spouští server uvnitř tmuxu a obaluje ho vlastními nástroji.

Startovací skript, který unit spouští#

systemd by měl spouštět skript, ne přímo binárku, protože server potřebuje dvě proměnné prostředí a pracovní adresář. Unit nesměřuj na přibalený start_server.sh; SteamCMD ho při každé aktualizaci a validate obnoví, takže tvoje argumenty zmizí s další záplatou. Drž si vlastní kopii:

/home/valheim/server/start_valheim.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

Pro systemd je podstatné exec. Bez něj skript běží jako proces shellu a server je jeho potomek a signál, který systemd při zastavení pošle, dopadne na shell. Bash nepředává signály potomkovi na popředí tak, jak bys čekal, takže server může signál pro čisté zastavení úplně minout a po vypršení timeoutu ho někdo zabije. S exec se shell nahradí procesem valheim_server.x86_64, server se stane hlavním procesem služby a signál jde přímo k němu.

Všechny argumenty na tom řádku jsou popsané v přehledu spouštěcích argumentů Valheimu. Dva stojí za to zvolit u služby vědomě: -saveinterval (výchozí 1800 sekund) omezuje, o kolik přijdeš při pádu, a -logFile, který vynech, pokud chceš log v journalu.

Soubor unit řádek po řádku#

/etc/systemd/system/valheim.service
[Unit]Description=Valheim dedicated serverWants=network-online.targetAfter=network-online.targetStartLimitIntervalSec=600StartLimitBurst=4[Service]Type=simpleUser=valheimGroup=valheimWorkingDirectory=/home/valheim/serverExecStart=/home/valheim/server/start_valheim.shKillSignal=SIGINTTimeoutStopSec=120Restart=on-failureRestartSec=15[Install]WantedBy=multi-user.target
bash
$ sudo systemctl daemon-reload$ sudo systemctl enable --now valheim$ systemctl status valheim

K čemu který řádek je:

ŘádekProč tam je
Wants= / After=network-online.targetStart až po zprovoznění sítě, aby registrace u Steamu při bootu neselhala
StartLimitIntervalSec=600, StartLimitBurst=4Víc než čtyři starty za deset minut a systemd to přestane zkoušet
Type=simpleSkript zůstává na popředí; systemd ho sleduje přímo
User= / Group=Herní server nikdy nespouštěj jako root
WorkingDirectory=Cesta ke knihovnám ve skriptu je relativní k instalaci
KillSignal=SIGINTsystemctl stop se chová jako Ctrl+C, což svět uloží
TimeoutStopSec=120Jak dlouho systemd čeká na uložení, než pošle SIGKILL
Restart=on-failure, RestartSec=15Návrat po pádu, nejdřív s pauzou
WantedBy=multi-user.targetNa co se enable napojí, aby se služba spouštěla při bootu

V současných verzích systemd patří nastavení start limitu do [Unit]. Starší verze přijímaly StartLimitInterval= v [Service]; pokud systemctl status varuje před neznámým klíčem, zkontroluj v man systemd.unit na svém stroji, jaký zápis očekává.

Čisté zastavení: SIGINT, timeouty a uložení#

Tahle část unitu rozhoduje o tom, jestli tě reboot něco stojí. Valheim drží svět v paměti a na disk ho zapisuje každých -saveinterval sekund. Čisté ukončení ho zapíše naposledy; cokoli míň ne.

Když s výše uvedeným unitem spustíš systemctl stop valheim, proběhne tohle:

  1. systemd pošle SIGINT hlavnímu procesu - díky exec je to server.
  2. Server zaloguje, že se vypíná, uloží svět a skončí. U malého světa to trvá sekundu nebo dvě; u dlouho hraného světa s velkými základnami to může trvat znatelně déle a pomalé disky to ještě natáhnou.
  3. Pokud proces po TimeoutStopSec pořád běží, systemd pošle SIGKILL a zaloguje, že zastavení vypršelo.

Než tomu uvěříš, jednou to schválně ověř:

bash
$ sudo systemctl stop valheim$ journalctl -u valheim -n 40 --no-pager

V posledních řádcích výstupu chceš před ukončením procesu vidět uložení světa a od systemd prosté Stopped Valheim dedicated server. Pokud místo toho vidíš State 'stop-sigterm' timed out. Killing. nebo Main process exited, code=killed, status=9/KILL, server buď nestihl skončit včas, nebo signál nikdy nedostal. Zkontroluj v tomto pořadí: že KillSignal=SIGINT je v unitu a po jeho přidání jsi spustil daemon-reload; že skript používá exec; a že TimeoutStopSec stačí pro tvůj svět.

systemctl restart je zastavení následované startem, takže dostane stejné čisté zastavení. systemctl kill valheim ne - ve výchozím stavu posílá SIGTERM všem procesům v unitu - a stejně tak ne OOM killer v jádře, výpadek proudu nebo pád hostitele. Proti nim chrání jen krátký interval ukládání a zálohy uložené jinde. Zálohy serveru Valheim a poškození světa popisují, jak vypadá napůl zapsaný svět a jak se z něj zotavit.

Pravidlo restartu a smyčky pádů#

Restart=on-failure restartuje server, když skončí s nenulovým kódem, když ho zabije nečekaný signál nebo když vyprší timeout - a po systemctl stop ho nerestartuje, což je přesně to, co chceš. Alternativy:

PravidloRestartuje poPoužij, když
noNičemChceš každý konec vyšetřit ručně
on-failurePádech, zabití, nenulových kódechBěžná volba pro herní server
on-abnormalSignálech a timeoutech, ne nenulových kódechServer z nějakého důvodu končí nenulovým kódem schválně
alwaysVšem, včetně čistého ukončeníTady málokdy správně; záměrné vypnutí ve hře se hned vrátí

RestartSec=15 je pauza před každým restartem. Dává UDP portům starého procesu čas na uvolnění a brání tomu, aby smyčka pádů běžela plnou rychlostí.

Brzdou je start limit. Pokud je soubor světa poškozený nebo aktualizace hry rozbila mod pro BepInEx, server spadne při každém startu. Bez limitu ho systemd restartuje donekonečna, což zaplní journal tisíci stejných chyb a pohřbí první, nejužitečnější výskyt. S StartLimitBurst=4 za deset minut systemd označí unit jako selhaný a přestane:

bash
$ systemctl status valheim# Active: failed (Result: start-limit-hit)$ journalctl -u valheim -b --no-pager | tail -n 80$ sudo systemctl reset-failed valheim$ sudo systemctl start valheim

Než cokoli resetuješ, přečti si log. Běžné chyby při startu - chybějící steamclient.so, obsazený port, chyba preloaderu BepInEx, svět, který se nenačte - mají každá rozpoznatelný řádek a pád serveru Valheim při startu je vyjmenovává.

Logy v journalctl#

Bez argumentu -logFile server vypisuje na standardní výstup, systemd ho zachytí a z journalu se stane log serveru. Příkazy, které budeš opravdu používat:

bash
# follow the log live$ journalctl -u valheim -f# everything since the current boot$ journalctl -u valheim -b# a time window$ journalctl -u valheim --since "2026-10-14 19:00" --until "2026-10-14 23:00"# search: connections, the join code, errors$ journalctl -u valheim -g "Got connection|join code|Exception"# the last 200 lines without the pager$ journalctl -u valheim -n 200 --no-pager

Log Valheimu je upovídaný a na některých distribucích se journal drží jen v paměti, takže po rebootu zmizí. Pokud /var/log/journal neexistuje, nastav v /etc/systemd/journald.conf Storage=persistent a restartuj systemd-journald. Aby journal nerostl bez omezení, nastav ve stejném souboru SystemMaxUse= - pro jeden herní server bohatě stačí 500M - nebo si aktuální zabrané místo zkontroluj přes journalctl --disk-usage.

Druhá možnost je soubor: přidej na startovací řádek -logFile /home/valheim/valheim.log a server bude psát tam místo do journalu. To vyhovuje těm, kdo mají rádi tail a grep na obyčejném souboru, jenže pak je rotace tvoje starost, přes logrotate s copytruncate, protože server drží soubor otevřený. Vyber si jedno; rozdělení logu mezi obě místa každé vyšetřování zhorší. Co řádky znamenají - start, join kód, připojení, chyby, na které stojí za to reagovat - najdeš v článku o logu serveru Valheim.

Aktualizace: při každém startu, nebo ručně#

Unit výše hru neaktualizuje. Můžeš ho k tomu přimět jedním řádkem navíc v [Service]:

ini
ExecStartPre=/usr/games/steamcmd +force_install_dir /home/valheim/server +login anonymous +app_update 896660 +quit

Pak každý start, včetně každého restartu a každého bootu, nejdřív zkontroluje nový build serveru. Pro vanilla server je to pohodlné: když vyjde záplata Valheimu a hráči vidí Incompatible version, spraví to systemctl restart valheim.

Pro server s mody je to špatná volba. Záplata hry obvykle rozbije mody pro BepInEx, dokud je autoři nedoženou, a automatická aktualizace znamená, že restart v pět ráno ti může nechat server, který padá ve smyčce, dokud si toho někdo nevšimne. Na serveru s mody nech ExecStartPre pryč a aktualizuj záměrně: zastav server, zálohuj, spusť SteamCMD ručně pod uživatelem valheim, ověř, že tvoje mody jsou aktualizované, a spusť znovu. Dvě menší poznámky: kontrola aktualizace přidá ke každému startu čas, který SteamCMD potřebuje, a když aktualizace selže - Steam nedostupný, plný disk - selže ExecStartPre a server se vůbec nespustí. Předřaď cestě - (ExecStartPre=-/usr/games/steamcmd ...), aby se server při selhání kroku aktualizace spustil na starém buildu. Otázku načasování pro skupiny rozebírá aktualizace serveru Valheim a oprava neshody verzí.

Timery: týdenní restarty a noční zálohy#

Timery systemd dělají to, co cron, a pro herní server mají dvě výhody: jejich běhy se logují v journalu vedle výstupu samotného serveru a systemctl list-timers ukazuje, kdy se který spustí příště. Timer jsou dva soubory: .timer, který říká kdy, a .service, který říká co.

Týdenní restart, brzy v pondělí ráno:

/etc/systemd/system/valheim-restart.service
[Unit]Description=Restart the Valheim server[Service]Type=oneshotExecStart=/usr/bin/systemctl restart valheim.service
/etc/systemd/system/valheim-restart.timer
[Unit]Description=Weekly Valheim restart[Timer]OnCalendar=Mon *-*-* 05:00:00[Install]WantedBy=timers.target

Noční záloha celého adresáře se savy, spouštěná pod uživatelem valheim:

/home/valheim/backup_valheim.sh
#!/bin/bashset -euo pipefaildest=/home/valheim/backupsmkdir -p "$dest"tar -czf "$dest/valheim-$(date +%F-%H%M).tar.gz" \    -C /home/valheim/.config/unity3d/IronGate Valheimfind "$dest" -name 'valheim-*.tar.gz' -mtime +14 -delete
/etc/systemd/system/valheim-backup.service
[Unit]Description=Back up Valheim worlds[Service]Type=oneshotUser=valheimExecStart=/home/valheim/backup_valheim.sh
/etc/systemd/system/valheim-backup.timer
[Unit]Description=Nightly Valheim backup[Timer]OnCalendar=*-*-* 05:10:00Persistent=true[Install]WantedBy=timers.target
bash
$ chmod +x /home/valheim/backup_valheim.sh$ sudo systemctl daemon-reload$ sudo systemctl enable --now valheim-restart.timer valheim-backup.timer$ systemctl list-timers 'valheim*'$ systemd-analyze calendar "Mon *-*-* 05:00:00"

Záloha běží v pondělí deset minut po restartu, takže v ty dny archivuje svět uložený chvíli předtím. V ostatní dny běží proti živému serveru a archiv pořízený uprostřed ukládání může zachytit napůl zapsaný soubor. Buď nastav timer na čas hned po restartu každý den, nebo nech skript kopírovat nejnovější kompletní dvojici z vlastní rotace -backups Valheimu. Persistent=true spustí zmeškanou zálohu při dalším bootu, pokud byl stroj v 05:10 vypnutý; u timeru restartu ho nech vypnutý, protože pozdní dohánění by server restartovalo uprostřed večera. Pozor, cesta k savům výše je výchozí; pokud používáš -savedir, archivuj tu, kde Valheim drží své soubory vyjmenovává všechna umístění.

Záloha na stejném disku jako svět chrání před špatným uložením a před ničím jiným. Archivy kopíruj i mimo stroj; jeden způsob ukazují zálohy herního serveru na S3. A protože vanilla Valheim nemá na straně serveru žádné vysílání do hry - ani RCON, ani konzoli na stdin - o okně restartu informuj hráče na Discordu, ne jako varování ve hře.

Limity, zabezpečení a víc než jeden server#

Pár řádků v [Service] stojí za přidání, jakmile základ funguje:

ini
MemoryMax=6GNoNewPrivileges=truePrivateTmp=trueProtectSystem=fullNice=-5

MemoryMax= je tvrdý strop vynucovaný přes cgroups: když ho server dosáhne, jádro ho zabije bez uložení, což je lepší než swapování celého stroje do úplného zastavení, ale pořád je to pád. Nastav ho výrazně nad běžnou pracovní sadu serveru - průvodce pamětí pro Valheim má reálná čísla - nebo nejdřív použij MemoryHigh=, který brzdí, místo aby zabíjel. ProtectSystem=full zpřístupní /usr, /boot a /etc službě jen pro čtení; nepřidávej ProtectHome=, protože server i jeho savy žijí v domovském adresáři. Nice=-5 dává serveru malou prioritu před další prací na sdíleném stroji.

Pro více světů na jednom stroji z unitu udělej šablonu valheim@.service s EnvironmentFile=/etc/valheim/%i.env a startovacím řádkem poskládaným z proměnných jako $NAME, $WORLD, $PORT a $PASSWORD. Každá instance potřebuje vlastní dvojici portů, minimálně o dva vzdálenou (2456, pak 2458), vlastní název světa a ideálně vlastní -savedir. Spouštěj je jako valheim@main a valheim@test. Počítání portů je v článku porty Valheimu 2456-2458 vysvětleně.

Pokud nemůžeš používat root vůbec, stejný unit funguje jako uživatelská služba v ~/.config/systemd/user/, spravovaná přes systemctl --user. Odhlášení přežije, jen když je pro daného uživatele zapnutý lingering (loginctl enable-linger valheim, což jednou root potřebuje). Širší úvod do unitů, závislostí a limitů mimo Valheim najdeš v službách systemd pro tvoje aplikace.

FAQ#

Ukládá Valheim, když ho systemd zastaví?

Ano, pokud unit pošle SIGINT a signál dorazí k procesu serveru. To znamená KillSignal=SIGINT v unitu a exec ve startovacím skriptu. S výchozím SIGTERM nebo s shellem mezi systemd a serverem uložení zaručené není.

Jak dlouhý má být TimeoutStopSec?

Dost dlouhý na nejtěžší uložení plus rezervu. 120 sekund je pohodlných pro téměř každý svět. Pokud journal někdy ukáže vypršení zastavení a SIGKILL, zvyš ho - a zkontroluj disk, protože tak pomalé uložení obvykle ukazuje na úložiště.

Proč systemctl hlásí start-limit-hit?

Server spadl víckrát, než dovoluje StartLimitBurst v rámci StartLimitIntervalSec, takže to systemd přestal zkoušet. Skutečnou chybu najdeš v journalctl -u valheim -b; oprav ji a před dalším startem spusť systemctl reset-failed valheim.

Mám na restarty použít timer systemd, nebo cron?

Funguje obojí. Timery logují každý běh v journalu, ukazují příští běh v systemctl list-timers a díky Persistent=true umí dohnat zmeškané běhy, což se hodí u záloh. Cron je v pořádku, pokud už v něm spravuješ všechno ostatní; syntaxi popisují výrazy cronu vysvětleně.

Můžu přes systemd zadávat příkazy do serveru?

Ne smysluplně. Dedicated server Valheimu nemá konzoli na stdin ani RCON ve vanille. Admin příkazy se spouštějí z konzole F5 herního klienta hráči uvedenými v adminlist.txt a funguje to stejně, ať je server spuštěný jakkoli.