Run a Valheim Server as a systemd Service

If your Valheim server is a shell script you launched over SSH, it dies the moment that session ends and it doesn’t come back after a reboot. systemd fixes both, and adds two things you’ll come to rely on: automatic restart after a crash, and a clean shutdown path that lets the server save the world before it exits. This assumes a native Linux install with a dedicated valheim user, as set up in Install a Valheim Dedicated Server on Ubuntu Without Docker.

Why the shutdown path matters most

A killed server can lose the last stretch of play. Valheim saves periodically, not continuously. If systemd hard-kills the process, everything since the last autosave is gone — and repeated hard kills are how worlds end up needing a rollback.

So give it time to exit gracefully. The server handles a normal termination signal by saving and shutting down, but that takes a moment on a large world. A unit with a short stop timeout will impatiently escalate to SIGKILL and undo the whole point.

And prefer a manual save before planned work. An admin running the console save command immediately before a restart is the cheapest insurance there is.

The unit file

Create /etc/systemd/system/valheim.service:

[Unit]
Description=Valheim dedicated server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=valheim
Group=valheim
WorkingDirectory=/home/valheim/server
ExecStart=/home/valheim/start-valheim.sh
Restart=on-failure
RestartSec=15
TimeoutStopSec=120
KillSignal=SIGINT
KillMode=mixed

[Install]
WantedBy=multi-user.target

What each choice is doing:

  • User=valheim runs it unprivileged. Note that this also decides where the world files go — the server writes into that user’s home, under /home/valheim/.config/unity3d/IronGate/Valheim/. Change the user later and you’ll appear to have lost your world.
  • ExecStart points at your own start script, not the one that shipped with the server — updates overwrite the bundled one.
  • Restart=on-failure brings it back after a crash but leaves it alone when you stop it deliberately. Use Restart=always if you’d rather it come back even after a clean exit.
  • RestartSec=15 avoids a hot restart loop when something is genuinely broken.
  • TimeoutStopSec=120 is the important one: generous time to save before systemd escalates.
  • KillSignal=SIGINT sends the interrupt the server treats as “shut down cleanly”, matching what Ctrl+C does in a terminal. If your build responds better to plain SIGTERM, drop this line — systemd’s default is SIGTERM, and both are worth testing on your install rather than assumed.
  • After=network-online.target avoids starting before the network is usable at boot.

Your start script must run the server in the foreground (no &, no screen) for Type=simple to track it correctly.

Enable and start

sudo systemctl daemon-reload
sudo systemctl enable --now valheim
sudo systemctl status valheim

enable handles boot; --now starts it immediately. status should show it active and, after a minute or two, the log lines from world loading.

Reading the logs

Everything the server prints goes to the journal:

journalctl -u valheim -f

Useful variations:

journalctl -u valheim --since "1 hour ago"
journalctl -u valheim -p err
journalctl -u valheim -b

The last one shows only the current boot, which is what you want after an unexpected restart. If the journal is filling your disk, cap it with SystemMaxUse in /etc/systemd/journald.conf rather than deleting files by hand.

Day-to-day commands

sudo systemctl restart valheim
sudo systemctl stop valheim
sudo systemctl start valheim
sudo systemctl disable valheim

Always stop the service before updating the server files. Patching a running install is how you get a half-updated server that starts and immediately dies:

sudo systemctl stop valheim
steamcmd +force_install_dir /home/valheim/server +login anonymous +app_update 896660 validate +quit
sudo systemctl start valheim

Scheduled restarts, if you want them

A nightly restart is a reasonable habit on a long-running server: it releases memory that has crept up over days and gives you a predictable moment to take a backup. A systemd timer is tidier than cron here because it can act on the unit directly.

Create /etc/systemd/system/valheim-restart.timer:

[Unit]
Description=Nightly Valheim server restart

[Timer]
OnCalendar=*-*-* 05:30:00
Persistent=true

[Install]
WantedBy=timers.target

And /etc/systemd/system/valheim-restart.service:

[Unit]
Description=Restart the Valheim server

[Service]
Type=oneshot
ExecStart=/bin/systemctl restart valheim

Then:

sudo systemctl daemon-reload
sudo systemctl enable --now valheim-restart.timer
systemctl list-timers | grep valheim

Pick an hour nobody plays, and tell your group it exists — an unexplained disconnect at the same time every night generates more support questions than the restart saves.

Troubleshooting

Service fails immediately. Run your start script by hand as the valheim user first. If it fails there too, it isn’t a systemd problem — check the library path, the app-ID variable, and the password rules (at least five characters, not contained in the server name).

Starts, then exits with success. Your script backgrounds the server or wraps it in screen. Type=simple needs the process to stay in the foreground.

Permission denied. The script isn’t executable, or the install directory is owned by a different user than User=.

World looks empty after a change. You changed the service user. The world lives in that user’s home directory, not next to the binary.

Restart loop. Something is genuinely broken and Restart is hiding the error. Check journalctl -u valheim -b from the top, and raise RestartSec while you investigate.

Once the unit is in place, the server becomes infrastructure: it comes back after a power cut, it restarts itself if it falls over, and its logs are one command away.