Valheim Field guide

How to run a Valheim server on Ubuntu: Steam, crossplay and backups

Installation, player connections and a recoverable new-world backup on your own VPS.

How to run a Valheim server on Ubuntu: Steam, crossplay and backups

Run a new, unmodded Valheim world as a Linux service, choose how players connect and keep its saves outside the directory SteamCMD updates. You need a fresh Ubuntu 24.04 x86_64 VPS, a public IPv4 address, SSH access and a user with sudo. This guide targets the stable server distributed through Steam, with sources checked on October 12, 2026.

Use a VPS region close to your group. Leave memory and disk space for the operating system, world growth and backups; advertised player slots do not prove a particular VPS can sustain them. Valheim's 1.0 FAQ describes the game as designed for 1–10 players.

Choose Steam or crossplay first#

For a Steam-only group, omit -crossplay. For players using other supported platforms, add it. These modes have different connection paths:

ModeConnection pathVPS inbound rule
SteamDirect game connectionUDP 2456–2457 for the example below
CrossplayPlayFab relay; use a join code or public addressNo game-port forwarding is needed for relay access

The dedicated-server manual specifies the base port and base+1. Crossplay does not accept local or loopback addresses. Keeping outbound networking available matters for the relay; opening arbitrary inbound ports does not fix its registration.

Steam connections use inbound UDP; crossplay uses a relay. Backups take a separate path after the process stops.

Install SteamCMD under a game account#

Run the following on the VPS. The 32-bit library supports SteamCMD; the audio and atomic libraries support Valheim's Linux server:

bash
sudo apt update
sudo apt install -y ca-certificates curl lib32gcc-s1 libatomic1 libpulse0 libpulse-dev nano ufw
sudo adduser --system --group --home /srv/valheim valheim
sudo install -d -o valheim -g valheim -m 750 /srv/valheim/steamcmd /srv/valheim/server /srv/valheim/data
sudo -u valheim -H curl -fsSLo /srv/valheim/steamcmd/steamcmd.tar.gz https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz
sudo -u valheim -H tar -xzf /srv/valheim/steamcmd/steamcmd.tar.gz -C /srv/valheim/steamcmd
sudo -u valheim -H /srv/valheim/steamcmd/steamcmd.sh +force_install_dir /srv/valheim/server +login anonymous +app_update 896660 validate +quit

The account owns the installation and has a persistent HOME; it does not need administrator rights. Confirm that /srv/valheim/server/start_server.sh and the dedicated-server executable exist. A failed download is not a reason to continue into service setup. Keep the reported build information in your administration notes.

Configure a launcher that updates will preserve#

Copy the shipped Linux launcher outside the downloaded directory:

bash
sudo -u valheim cp /srv/valheim/server/start_server.sh /srv/valheim/start.sh
sudo chmod 700 /srv/valheim/start.sh
sudo -u valheim nano /srv/valheim/start.sh

Keep the environment exports from the installed build, including its Steam and library settings. Replace its server-launch command with the following. Replace the example password before starting; keep it distinct from the server name. Remove any duplicate launch command or interactive wait after it. The final launch should use exec so systemd tracks the actual server process:

bash
exec /srv/valheim/server/valheim_server.x86_64 -nographics -batchmode -name "Our Valheim World" -port 2456 -world "Friends" -password "REPLACE_WITH_RANDOM_SECRET" -savedir /srv/valheim/data -public 0

This creates a new world called Friends. -savedir explicitly separates persistent data from program files; -public 0 keeps the example out of the public list. For crossplay, append -crossplay to this same command. Use a join code from the crossplay workflow.

Inspect the manual supplied alongside the installed server if its launcher differs. Preserve its environment setup rather than replacing it with an old script from a hosting tutorial.

Start once in the foreground from the server directory:

bash
sudo -u valheim -H /bin/bash -c 'cd /srv/valheim/server && /bin/bash /srv/valheim/start.sh'

Wait for startup, then press Ctrl+C and wait for the process to finish. No player needs to join during this first run. If a library is missing, fix that error before continuing.

Install the service#

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

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

[Service]
Type=simple
User=valheim
Group=valheim
WorkingDirectory=/srv/valheim/server
Environment=HOME=/srv/valheim
ExecStart=/bin/bash /srv/valheim/start.sh
KillSignal=SIGINT
TimeoutStopSec=180
SendSIGKILL=no
Restart=no
UMask=0027

[Install]
WantedBy=multi-user.target

SIGINT follows the documented Ctrl+C shutdown path. Automatic restarts are disabled so a repeated startup or save failure remains visible. If shutdown times out, investigate the process and logs before archiving; this unit does not force-kill it at the timeout.

bash
sudo systemctl daemon-reload
sudo systemctl enable --now valheim
sudo systemctl status valheim --no-pager
sudo journalctl -u valheim -n 100 --no-pager

Open the correct route and test a join#

First allow your actual SSH port. The example assumes port 22; substitute yours before enabling UFW. Check the provider firewall too. For Steam mode:

bash
sudo ufw allow 22/tcp
sudo ufw allow 2456:2457/udp
sudo ufw enable
sudo ufw status verbose
sudo ss -lunp

For crossplay, omit the 2456:2457 rule when initially configuring the firewall. If switching an existing Steam server, leave the known-working route until the relay join succeeds, then remove the obsolete rule deliberately.

For Steam, enter VPS_IP:2456 in the game's address entry. For crossplay, use the active join code, or the public address as documented. A Steam Deck running the Steam version does not by itself require switching to the crossplay backend.

An active service and UDP socket establish only local readiness. Join from a player's external connection, enter the password, make a small world change, disconnect and rejoin. After a controlled service restart, check that the change remains:

bash
sudo systemctl restart valheim
sudo journalctl -u valheim -n 100 --no-pager

Back up the complete save directory#

Stop the service and confirm both service state and process exit:

bash
sudo systemctl stop valheim
sudo systemctl is-active valheim
sudo systemctl show valheim -p MainPID -p SubState
sudo journalctl -u valheim -n 60 --no-pager

inactive, MainPID=0 and completed shutdown in the log are the expected checks. If the server is still stopping or failed to stop, resolve that first. Do not archive a moving save.

Archive the whole data directory and launcher. Iron Gate's release notes confirm a changed save format in 1.0. A recipe that copies only an old .db/.fwl pair is not a general current backup procedure.

bash
set -e
sudo install -d -m 700 /var/backups/valheim
VALHEIM_BACKUP="/var/backups/valheim/valheim-$(date -u +%Y%m%dT%H%M%SZ).tar.gz"
sudo tar -czf "$VALHEIM_BACKUP" -C /srv/valheim data start.sh
sudo tar -tzf "$VALHEIM_BACKUP"
install -d -m 700 "$HOME/gamehost-backup-export"
sudo install -m 600 -o "$(id -u)" -g "$(id -g)" "$VALHEIM_BACKUP" "$HOME/gamehost-backup-export/valheim-backup.tar.gz"
sudo systemctl start valheim

Run the archive block together; set -e stops it on an error before restarting the service. The export file is created with mode 600 inside your own private directory, while the dated archive remains root-private.

On your computer, retrieve that copy over SSH; use the same SSH login that ran the archive commands and substitute the public address. For a custom SSH port add -P YOUR_SSH_PORT:

bash
scp SSH_USER@VPS_IP:gamehost-backup-export/valheim-backup.tar.gz ./valheim-backup.tar.gz

Then run rm -- "$HOME/gamehost-backup-export/valheim-backup.tar.gz" on the VPS. Keep the dated archive, service file and installed-build record elsewhere too. Listing an archive is not a restore test: rehearse restoration on a separate instance, with the matching server version and an isolated port, before relying on it.

Update deliberately and diagnose failures#

Before an update, repeat the stopped backup, omitting the final sudo systemctl start valheim in the archive block. Confirm MainPID=0 again before running the same SteamCMD installation command. Inspect the updated launcher/manual for environment changes, then start the service and repeat the client check. If you already restarted after the backup, stop the service and verify shutdown again first. Updates belong in a maintenance window, not every service startup.

ObservationNext check
Server does not startRead journalctl; confirm installed executable, retained environment exports and libraries.
Steam player times outConfirm UDP 2456–2457 in both firewalls and the public address; a TCP web-port test does not check this route.
Crossplay fails with a local addressUse the join code or public address; inspect relay registration and outbound access.
A new world appearsStop before making progress; compare -world, -savedir and the selected backup. Keep a copy of all existing data before changing paths.
Update appears ineffectiveConfirm SteamCMD targets /srv/valheim/server and the service starts that same installation.

These checks narrow the failure without deleting the world or opening an unrelated range of ports.