Setting Up Valheim

I recently started getting into Valheim. I’ve been playing it cooperatively with some good friends of mine, and soon after starting a world we decided we needed a dedicated server. We’re four people with very different schedules (I work, they’re at uni) so it really was a no-brainer.

Setting up your own server is pretty easy, although there were some pitfalls. To document those, and also to show how I did it differently (because of course I did), I’m writing this blog post.

The first thing you need to do is to install SteamCMD. This is a CLI-client for Steam that you need to install the dedicated server. After you install it, it’s a good idea to create a separate user for your games:

useradd -m steam

I added an directory in the home folder of the steam user called Valheim. To install it to that folder, you need to enter the following command

steamcmd +login anonymous +force_install_dir /home/steam/Valheim +app_update 896660 +exit

You can get the ID (896660) from this steam database. Just search for Valheim, and it should come up. You can also use the command above to update your server.

Most guides recommend you use the Bash script inside the folder to start the server.

export templdpath=$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=./linux64:$LD_LIBRARY_PATH
export SteamAppId=892970


echo "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 through your local router & firewall.
./valheim_server.x86_64 -name "server_name" -port 2456 -world "world_name" -password "your_password"

export LD_LIBRARY_PATH=$templdpath

I decided against it, because we might as well use a systemd service file. After all, that’s what they’re designed for! The systemd service file should look a little like this:

[Unit]
Description=Valheim Headless Server
After=network-online.target

[Service]
WorkingDirectory=/home/steam/Valheim/
ExecStart=/home/steam/Valheim/valheim_server.x86_64 -name "server_name" -port 2456 -world "world_name" -password "your_password"
KillSignal=SIGINT
Environment="LD_LIBRARY_PATH=./linux64:$LD_LIBRARY_PATH"
Environment="SteamAppId=892970"
Environment="TERM=xterm"

[Install]
WantedBy=multi-user.target

One important thing to note is the line Environment="TERM=xterm". For some reason, unity games need TERM set to xterm. Otherwise the game doesn’t work. Since I’m using tmux (with TERM set to tmux-256color), I have to set it to xterm. I also set the other Environment variables that were in the Bash script.

One thing you need to do is change your firewall to allow ports 2456-2458. If you use nftables it should look like this.

net filter {
    chain input {
        type filter hook input priority 0;
        policy drop;
        iif lo accept

        # Early dropping of invalid packets:
        ct state invalid drop

        # Accept traffic originating from us
        ct state established,related accept

        # Valheim
        tcp dport 2456-2458 accept
        udp dport 2456-2458 accept
    }

    chain output {
        type filter hook output priority 0;
        policy accept;
        oif lo accept
    }
}

If you had a previous world you need to copy it over. On windows, it can be found in C:\Users\user\AppData\LocalLow\IronGate\Valheim\worlds. In that folder you should have two files. You need to copy those two files into ~/.config/unity3d/IronGate/Valheim/worlds. If you don’t have that folder, you can just run the binary once to create it.

After that, you’re technically ready to go. I was faced with one more problem though: the Server uses about 30% of my total CPU resources, even when no one is connected! This is a needless waste of my resources, since my machine runs 24/7. So I decided I would only start it when people actually wanted to play. My electric bill will thank me.

But when I relayed this decision to my friends, the wailing and lamentations began. “How will we be able to play it whenever we want? We can’t live with this! We need a way to start the server ourselves!!”. My assurances of a swift reaction when contacted via Discord, fell on deaf ears. So I wracked my brain. How can I make sure my (mischievous) friends can start (and stop!) the server themselves, without giving them shell access to my machine?

My solution consisted of two components

Systemd/User is a way of creating systemd units that can be controlled by the user. They are placed in the users home directory (~/.config/systemd/user/). They can then be controlled by passing the --user flag when running systemd commands. This allowed me to circumvent giving them root/sudo access, which is necessary for normal systemd operation.

NB: If you want to use systemd/User configuration, you have to configure lingering. this makes sure that the service is not stopped after the user has logged out:

loginctl enable-linger steam

After that I needed to find a way for them to execute commands without being able to log in. And SSH has a way of doing that! In the authorized_keys file (which contains the public keys for authentication) you can set a custom command that will be executed when they connect via SSH. So for each user (key) you get the following line in authorized_keys.

# Limited users (can only start, stop, and query status of valheim server)
command="./manage_valheim.sh $SSH_ORIGINAL_COMMAND" ssh-rsa KEY_GOES_HERE

The variable $SSH_ORIGINAL_COMMAND contains the command they enter on the command line when using SSH. This command can be either start, stop, or status. The command is parsed with manage_valheim.sh, a Bash script.

#!/bin/bash

SCTL="systemctl --user"

function usage() {
	echo "Usage: start stop status"
}

case $1 in
	start)
		$SCTL start valheim.service
		;;
	stop)
		$SCTL stop valheim.service
		;;
	status)
		$SCTL status valheim.service
		;;
	*)
		echo "Command not recognized!"
		usage
		;;
esac

The script parses user input and then starts the appropriate action (start, stop, or status). This way, the users that have public keys in authorized_keys can “manage” the server without having complete shell access.

Now my friends are happy, because they have an easy, user friendly way of managing the server. I’m happy because they don’t have any more access than they need. And, perhaps most importantly, my electric bill is happy.

Thanks for the read, I hope you enjoyed it. And I hope it will help you in setting up your own Valheim server. And one last thing: Play Valheim! It’s a great game, shout-out to the Developer IronGate Studio. You guys did a great job!


Articles from blogs I read - Generated by openring