Building a Dedicated Valheim Server on Ubuntu Server 20.04

In the last couple of weeks Valheim has been growing in popularity at a rapid pace, and a few folks at work and myself definitely jumped on the viking themed bandwagon. I decided to spin up a quick VM on my home server to create a dedicated server. While doing it I noticed there isn't a ton of great documentation on the way I did it, so I figured why not do it myself.

Table of Contents

Notes to get started

First of all, it's worth mentioning, there are a few routes to host a dedicated server. Doing so on a Linux based VM absolutely isn't necessary, but if you have the resources available to you it's potentially a lot cheaper to run, and gives you finer control over many aspects compared to a dedicated game hosting service.

As mentioned, I have a home server running Proxmox I already host a number of VMs on, so for me it made sense to just do this there. However, this can easily be done on AWS, Linode, DigitalOcean, or many other hosted solutions. This document is intended as a step by step guide assuming you're already sitting at an Ubuntu Server 20.04 bash shell. I may add some extra info later about getting to that point.

If you are creating a VM, I've read a lot of people are running servers just fine with 2 vCPUs and 2-4GB RAM. Storage wise the game needs very little, it's ~1GB total including things like logs and whatnot. My VM is a bit more robust as I have the resources available to do so. I did 4 vCPUs, 4GB RAM, and 64GB of storage. I also used Ubuntu Server 20.04 for this as it's my go-to VM OS.

Also, while a lot of this guide will be basically a "copy/paste guide" so you could do this without much previous knowledge of linux, future maintenance will almost certainly require some background knowledge on navigating linux and using it's built in tools. Given that the game is still in early access, there's also a very good chance the server software for the game could change drastically with time and this guide could get out of date quickly. At the very bottom of this page you'll find a timestamp for when it's been last edited, please use that to gauge if it's still valuable to you.

Getting the basics installed

With a fresh Ubuntu Server 20.04 instance, I'll make a suggestion to start. I like to have a simple little shell script that checks for and applies updates to the system. It will also tell you if you need to restart the server. To create this file run the following commands:

touch chkupdates.sh
chmod +x chkupdates.sh
nano chkupdates.sh

With the file created and open, copy/paste the following in:
#!/bin/bash
echo '#########################'
echo '# Performing apt update #'
echo '#########################'
sudo apt update
echo '##########################'
echo '# Performing apt upgrade #'
echo '##########################'
sudo apt upgrade
echo '#########################'
echo '# Do we need to reboot? #'
echo '#########################'
if [ -f /var/run/reboot-required ];
then
  echo 'Yup, you should reboot.'
else
  echo "Nope, you're good."

fi

I also recommend running that file right away to make sure the system is fully updated before continuing.

With the system running and updated, we can begin installing Valheim. To do this we'll use the LinuxGSM project. This a great project designed to install many different self-hosted games and game-adjacent tools (such as TeamSpeak), as well as basic maintenance for these. LinuxGSM typically recommends creating a dedicated user for installing and running the tools. Given that this VM server is being setup only to run the game, I think it's not necessary in this regard. HOWEVER, if you are going to running many game servers on one device/VM, it is the right decision to create dedicated users. More information from LinuxGSM on Valheim server itself is available here and here.

First, we need to get some tools and systems added to make everything work. The following command will do the brunt of the work:

sudo dpkg --add-architecture i386; sudo apt update; sudo apt install curl wget file tar bzip2 gzip unzip bsdmainutils python util-linux ca-certificates binutils bc jq tmux netcat lib32gcc1 lib32stdc++6 steamcmd

The following is optional, but highly recommended. Gamedig will allow LinuxGSM to get more information from the game server. This helps a lot of the basics of running the server, namely showing the current number of active players. If you're futzing around and need to restart knowing if you're about to kick someone out is a good idea. The following commands will setup and install nodejs, npm, and game dig.

sudo apt remove --purge nodejs npm
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt update && sudo apt install -y nodejs
npm install gamedig -g
sudo npm install gamedig -g
sudo npm update -g
sudo npm list -g gamedig

With this done we're ready to actually install linuxgsm and the Valheim server!

wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh && bash linuxgsm.sh vhserver
./vhserver install

You now have a Valheim server! There's a bit more to do, though.

Configuring LinuxGSM and the Valheim server settings

Now we want to go configure our server settings. Lets change directory into where the config files are to make this easier.

cd ~/lgsm/config-lgsm/vhserver
ls

You'll see a number of files. The main ones we care about are _default.cfg and common.cfg. To make our life easy in the future, the best idea is to make backups while we're working. The main thing right now is making a copy of common.cfg then copying _default.cfg to make a new common.cfg.

mv common.cfg common.cfg.old
cp _default.cfg common.cfg

The reason we do this is so in the future, if LinuxGSM needs to make changes, _default.cfg is left alone. As the server admin when there are updates to LinuxGSM or the game server you can check _default.cfg to see if you need to make updates to your common.cfg file. The common.cfg is where we'll be storing our settings for the server, things like the server name, passwords, enabling/disabling public access (adds it to or hides it from the in game community list), etc. By doing the above we allow the scripts to maintain themselves, gives us an idea of what they used to look like (in case you make mistakes), and easily make changes without fear of being able to recover from mistakes.

We can edit our config with a simple nano common.cfg command. You only want to change what is inside the quotes for each option. The main settings to change are as follows and all listed at the top of the config file:

  • servername: This is your server name. If you are creating a public server, it's what is listed in the community server list.
  • serverpassword: If you want to lock your server behind a password, enter it here.
    • If you don't want to require a password, simply have a line that lines serverpassword = "" and you'll have an open server.
  • port: by default this is set to 2456. This is the main game port. It also uses 2457 by default for "query" which is how something like Steam can find information about the server.
    • If you change this, the query port will be whatever you enter +1, so if you set the port to 5454, the query port will be 5455 for instance.
  • gameworld: by default, this will equal server name. If you are importing a game world, you'll want this to equal the name of the game world.
    • More about this later. Most people will suggest allowing the gameworld for your server to be freshly created, personally I wanted to carry my single player map in.
  • public: This changes whether the server shows up in the community server list or not. Setting it to 1 makes it public, setting it to 0 makes it hidden.
    • Personally I set to this 0. I setup my server for myself and folks from work, and while a password is likely enough to ensure this hiding it reduces the random-stumbler issue which will save you some bandwidth of someone just door-knocking your server.

There are a number of other settings to check. Scrolling down to see them will give you some more info on each, including links to the LinuxGSM docs on each.

  • stats: set this to on or off. The installer asks you if you want to do this. Personally I left it on, LinuxGSM is a great project but reliant on those of us using it to help make it better. The decision is yours, but I encourage you to help the project!
  • displayip: If you are going to get advanced, such as using a reverse proxy or something, you may want to change what the IP is shown as. The majority of users can ignore this setting.
  • Alert settings: Check the documentation for this. Each alert type will require different settings. I setup a discord alert for us and the documentation made it super easy.
  • updateonstart: I recommend setting this to on. It will make it so any time the server is started it checks for an update first. Highly recommend this for compatibility with your players.
  • Backup settings
    • maxbackups: When you start using backups, this sets a limit for how many backups to keep. More later on this.
    • maxbackupdays: this will set the maximum age for a backup. Each time a backup is run, it checks the other backups and removes anything older than this number.
    • stoponbackup: while not strictly required, highly recommended to leave this on. Stopping the server first means any backups created will be far less likely to corrupt your map, and will ensure the logs are fully updated to when the backup is finished. I can't say it will completely avoid corruptions, but it is significantly safer.
  • Logging settings
    • consolelogging: Enables or disables keeping logs from the game server console. Right now Valheim logs are not great in my opinion, but I'm an adamant believer of logging whatever you can. As is, the logs will show you when a player connects with their character name and a Steam ID value. If you'll be adding folks to an admin list, ban list, etc. this can be helpful.
    • logdays: like the maxbackupdays above, what is the oldest log to keep.

I checked thru all the other settings and I'm personally happy to leave them alone. At least at the time of writing, everything else is safe to leave untouched.

When you're done making your changes hit ctrl+X to close, and it will prompt you if you want to save, hit Y.

Setting up automated tasks

Now we want to setup some automated items. We'll setup automatically starting the game server on VM bootup, as well as a number of cronjobs to run things without much input from you.

First, lets setup automatically starting the server. As we're using Ubuntu 20.04, we can do this most easily with a systemd entry. You'll need sudo access to do this.

First, run the following command:

sudo nano /etc/systemd/system/vhserver.service

Now copy/paste the following:

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

[Service]
Type=forking
User=jp
WorkingDirectory=/home/<user>
RemainAfterExit=yes   #Assume that the service is running after main process exits with code 0
ExecStart=/home/<user>/vhserver start
ExecStop=/home/<user>/vhserver stop
Restart=no

[Install]
WantedBy=multi-user.target

Before saving and closing this we need to check a couple entries. You'll notice a few entries have <user> in the lines. Remove the <user> part and replace it with your user name on the server. For instance, my server's user name is jp, so I use /home/jp for each item. That should do it, though.

Why are we doing this? Many linux daemons run as different users, and have different working directories. Even if a command is set up inside of standard environment directories, certain daemon systems need to be explicitly told where a command is with a full path. This is also true of crontab, which we'll be using shortly.

Now we need to get systemd to recognize and run things. First we'll reload systemd and then enable it so it starts at boot.

sudo systemctl daemon-reload

sudo systemctl enable vhserver.service

Now if you restart the VM the server will startup shortly after boot. You may have noticed that early on in the file it says it requires and waits for network-online.target. This tells systemd to not try starting the game server until the network service is actually functioning.

Next we'll setup a number of cronjobs to automate some of the micro-management type things we need to do with the server. Cronjobs are setup with crontab. This is a file that has a series of lines that dictate when something should happen, and what should happen. Most of the time crontab is run as root, but what we're setting up for crontab to run are scripts that are inside our user folder, we can run crontab as the user that has all of this. If you created a new user, such as vhserver, for this you'll run crontab as vhserver. to start editing the crontab we just run crontab -e and start adding lines.

Before talking about what we'll be adding, you need to know how to use crontab scheduling. I won't go into extreme detail, or even a gloss over of it. Instead, I recommend visiting crontab.guru for assistance making your own schedule. I set my scheduled tasks that do or can restart the server to run very early in the morning to avoid interrupting my players. As such, you may want to just replicate my settings. If however you need to adjust the times, crontab.guru will help you figure out the right beginning to each entry to schedule them appropriately.

This is a copy/paste of my crontab, and I'll explain each item a bit more in detail. Like the systemd service file earlier, change <user> appropriately for your needs.

# update check and update LGSM every sunday at 4am
0 4 * * 0 /home/<user>/vhserver update-lgsm > /dev/null 2>&1

# validate vhserver every sunday and wednesday at 4:15am (also performs a restart)
15 4 * * 0,3 /home/<user>/vhserver validate > /dev/null 2>&1

# backup vhserver every day at 3:45am (also performs a restart)
45 3 * * * /home/<user>/vhserver backup > /dev/null 2>&1

# update vhserver every day at 4am (restarts if update is performed)
0 4 * * * /home/<user>/vhserver update > /dev/null 2>&1

# monitor vhserver every 5 minutes (makes sure it's running)
*/5 * * * * /home/<user>/vhserver monitor > /dev/null 2>&1

# check-update vhserver every hour (will only send an alert)
0 * * * * /home/<user>/vhserver check-update > /dev/null 2>&1

  1. The first entry runs every Sunday at 4am, and simply updates the LinuxGSM scripts. This shouldn't interrupt the game server. You could run it more frequently but it's generally not needed.
  2. The second entry runs a validate on the server files every Sunday and Wednesday at 4:15am. The validate will stop the game server, perform a check against Steam, and overwrite any necessary items. If you will be modifying your game files (with mods or changes to DLL's), you do not want to this and should either comment out the entry with a # at the beginning of the line or remove it entirely. However, if you plan to run a "generic" server, it's a good way to ensure the server is up to date, the game server files are not corrupted, and things are solid.
    1. In the future Valheim may have more "official" mod support and validating will probably not break it. As is, the mods are changing core files in the install, and thus will get over written every validate.
  3. The third entry creates a backup every day at 3:45am. As I configured my common.cfg file to perform a restart during backups, it will stop the server, create a backup, and start the server again. The backup created is a full copy of the home directory, so it will include the game map which is stored in a hidden folder.
    1. The rules for how many backups to keep and for how long were setup in common.cfg as well. I personally set both entries to 7. I want a daily backup for a full week, and nothing more. The idea being the world will have changed due to players building and whatnot enough in a week that anything older is not necessary, and anything more frequent than once a day feels like over kill to me.
  4. The forth entry simply performs a update every day at 4am. If there is no update available, it doesn't do anything. If an update is available it stops the server to update.
  5. The fifth entry performs a monitor command every 5 minutes. This monitor command allows LinuxGSM to ensure the server is up and working, and if not will send an alert and attempt to restart the server.
  6. The sixth entry performs a check-update every hour. Check-update will not actually do anything besides see if an update is available, and if one is it will send an alert.

What is the > /dev/null 2>&1 stuff? Crontab is running the vhserver script that LinuxGSM makes. If you run the commands manually, such as ./vhserver backup, you'll see it outputs some text. That text won't be going anywhere when run automatically by crontab, or at least it shouldn't. In reality, the tty shell in Unix systems is where all such output gets dumped to. While it doesn't break anything, it's pointless. So this chunk of code after the actual command tells the commands to dump it's output into the ether, never to be seen.

With that done you now have a Valheim game server with a number of automated starting, updating, validating, and backup systems running. Now's a good time to perform a system reboot to ensure it's working!

sudo reboot

# when the system is back up, lets see if the server is running

./vhserver details

# if status shows as ONLINE, you're good!

Optional steps that may be necessary given your circumstances

There are number of semi-optional steps to perform now. The most important is setting things up so other players can safely access your server.

Firewall Configuration: If running on a hosted service like AWS, Linode, DigitalOcean, etc.

As you're running on a hosted service, we need to enable our firewall. Most hosted services provide little to no firewall protection as they don't know what you'll be hosting and it's safer for them to leave things wide open and expect you to provide your own protections. It's time to setup those protections.

DigitalOcean has fantastic documentation in this regard. You can find a wonderful doc here: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-20-04

While that guide is a fantastic reference, I think for this there are a limited number of instructions from it you really need.

  1. Follow the prerequisites, then steps 2 thru 4 on that guide. This will ensure ufw firewall is installed, then set a default policy of allowing all outgoing connection types (so your server can connect to whatever it wants) but deny/block all incoming connection types. Then you allow specific incoming connection types, such as SSH, that you actually need. Lastly it enables the firewall. This basic 4 steps will lock down your VM so only SSH will work, which you need to perform continued work on it.
  2. Next, step 5 is a little generic but I recommend reading it so you understand what's happening. For our needs, we need to refer back to our common.cfg file to get the port number, and open it along with the query port. (NOTE: I've read a number of folks saying you also need to open one more port above the query port. I haven't tested if it's actually needed or not, the default ports are not used by anything else on such a basic Ubuntu VM, so it's safe to just open it if you left the port at default). You would enter the following two commands:
    1. sudo ufw allow <your port>:<your port +2>/tcp
      sudo ufw allow <your port>:<your port +2>/udp
    2. By default, Valheim requires 3 ports: 2456, 2457, 2458. This is a port range of 2456-2458. So, above, the command would look like sudo ufw allow 2456:2458/tcp and again with /udp at the end

This will setup basic firewall rules which allow you to SSH to the server from anywhere, as well as allow anyone to connect to the game server, but deny all other traffic. It leaves the server open to connect to other things as it wants so things like server updates will still work.

The linked DigitalOcean above also includes instructions for limiting connections to specific IP addresses or IP ranges if you'd like. This would allow even further control to specific users if you'd like, but would also mean you need to micromanage the firewall rules as your player's IP address can change frequently.

Hosted at home port-forwarding requirements

If you are hosting your game server at home, you will need to setup some port-forwarding on your home router's firewall. If you've seen other documents like this I'm sure you've seen a number of folks already saying this: Each router and firewall is different, and providing instructions for each is well outside the scope of this document.

There is a good collection of port forwarding guides for different routers available at https://portforward.com/router.htm which can help you. Find the instructions for your router, and simply enter the ports as necessary. 

By default, Valheim requires 3 ports: 2456, 2457, 2458. This is a port range of 2456-2458. However, if in common.cfg you changed your port, you will use a port range of <your port>-<your port+2>. The +2 is because Valheim will want to use your port for the game, your port +1 for queries (player counts, is the server up, etc.), and your port+2 for... something else folks online say is necessary but I haven't tested to confirm if it is.

Importing a World

This is by no means necessary, but many folks will want to do it. It's luckily fairly easy, too. I will note, if you are hoping to start a brand new adventure with your friends, it's likely best to just use a freshly generated world. I had purposely started building up my game world to use as a basis for the server, so I imported mine.

First off, I'm going to assume your attempting to import a game world from a single player campaign. Your single player game world maps can be found in specific folders:

  • Windows: C:\Users\<user>\AppData\LocalLow\IronGate\Valheim\worlds
  • Linux: /home/<user>/.config/unity3d/IronGate/Valheim/worlds
  • Mac OS X: GREAT QUESTION, FRIEND. I dunno.

If you've only made one world, you'll only see 3 files. A steamcloud.vdf, <game world name>.db, and <game world name>.fwl. The .db and .fwl files are the important ones. You can simply zip the worlds folder to get them packed up for easy transport to the server.

If you have many worlds, you will want to find the .db and .fwl files for the specific world you want. The file name will include the name of the world, so just look for that and zip them.

With that zip, we need to get it over to your server. I use Ubuntu Desktop on my laptop, so I simply did the following:

scp <worlds zip file> <username>@<server name or IP>:/home/<username>

SCP is a command line tool to copy files to a remote device with SSH. If you're on Windows there are many SCP based tools, but I've used WinSCP in the past and liked it. If you're using PuTTY to SSH to your device from Windows I believe it supports SCP natively in some way as well.

With the file now on the VM, we need to unpack it and move the files. SSH back into the machine if you've left it, and we can run the following commands:

cd
mkdir imported-worlds
mv <worlds zip file> imported-worlds
cd imported-worlds
unzip <worlds zip file>

Now, depending on your zip tool or how you did it, you may have a folder named worlds or you may have the world files listed here. For cleanliness, it's why we created a new directory and moved the file into it. enter the command ls to see, and if it's created a new directory simply cd <new directory>. Now, we need to move the world files we want to import to where the Valheim server can see it.

mv <world name>.* ~/.config/unity3d/IronGate/Valheim/worlds/

This will move both the world files to where the Valheim game server looks for worlds files.

Great, we now have the world files in the right place. However, we now need to tell the server to look at and load that world. Lets change back to home directory and edit the common.cfg file to do that.

cd
nano lgsm/config-lgsm/vhserver/common.cfg

The setting we want to change is gameworld. Setting this equal to the name of the game world file name (without the file extension) it'll tell LinuxGSM to start the Valheim server with that map. For instance, my game world is named Terry. So, I have a Terry.db and a Terry.fwl file in my worlds folder. In common.cfg, I set gameworld="Terry" and that's it. Restart the game server with a quick ./vhserver restart and when you connect you'll see your imported game world.

Speaking of, lets talk about how we connect.

Why'd you name your world Terry? I dunno, what'd you name your world? Something all viking themed because you're boring? Live a little man, give stuff people-names.

Connecting to your server

Connecting in Game

In game, you can now join a server by entering the IP. Currently, it doesn't appear to save this so you'd need to enter the IP every time. That said, it's quite easy to connect quickly.

Open the game, create or select a character, and click START. It will let you create or join a local world on the Start Game tab, but we want to use the Join Game tab to connect to a remote world. From there, click the Join IP button. Enter <server IP>:<port>. If a password was set, it will prompt you for a password. As an example, if your server is running on IP address 192.168.0.101 and you changed the port to 5454, you would enter 192.168.0.101:5454.

Adding to Steam Servers List

For a more permanent solution, we'll need to add the Valheim server to our Steam favorite servers list. On the very top of the Steam window, select View in the menu, and then select Servers.

In the window that opens, select the Favorites tab. If you've Favorited servers in games you play via Steam there may be a lot of servers listed here. I cleared mine out to reduce confusion for the sake of this document, but you can use the CHANGE FILTERS button on the bottom right to filter for specific games in the future. For now we're just adding another by clicking the ADD A SERVER button on the bottom right.

In the new window that opens, you'll want to enter the following then click ADD THIS ADDRESS TO FAVO...

<server IP>:<port>

As an example, if your server is running on IP address 192.168.0.101 and you changed the port to 5454, you would enter 192.168.0.101:5455 Note, you need to use the port you set +1 because Steam needs to use the Query port that Valheim uses.

Once added you'll be returned to the second screenshot above.

Connecting from Steam Server List

Simply double click the entry or select it and click CONNECT on the bottom right and you'll be prompted for a password by Steam. This password can be anything, the actual password prompt will be in game.

IMPORTANT NOTE: Right now there is a bug with either Valheim's server code or Steam, where the list will show the server information for a moment then suddenly display <not responding>. This is still the easiest way to connect consistently without needing to enter the IP and port every single time. To work around the bug, simply hit REFRESH on the bottom and as quickly as you can double click the server entry. If you are prompted for a password, you'll be able to connect.

When connecting, Valheim will load directly to the character select screen. Pick your character, and if you set a password you'll be prompted for it when Valheim itself starts to connect to the server.

Add yourself as Admin on the server

Valheim uses a Steam ID number to know who you are on the server. When you're connected to the game, if you hit F2 it will show some server stats including connected players. To the right of the player names you'll see a long number, that's what we need. Alternatively, you can get this number from the console logs, but admittedly they're kind of a mess and hard to figure out exactly, so I recommend getting the Steam ID from the in game F2 menu. With your Steam ID noted, lets add you to the admin list.

cd
nano .config/unity3d/IronGate/Valheim/adminlist.txt

To add yourself to the list, go to the bottom of the file and enter your Steam ID number. As the file already says, if you want to add multiple entries, you need to enter them one per line.

Once you're setup as an admin, in game you can hit F5 to get access to on-server commands. Right now they allow you to add others as admin, kick users, ban users, and see a bit of information like the current ban list and some server stats.

For most users, doing such administrative tasks in game will be best. However, if you ever need to, in the same directory as the adminlist.txt there is a bannedlist.txt and permittedlist.txt that will black list or white list Steam IDs respectively.

Conclusion

And that's it. You now have a dedicated Valheim server running on linux. It is set to automatically start, it will automatically do validations and backups, and can notify you of updates for the game server as well as applying those updates. For security, it's setup to only allow certain kinds of connection thru, as well. You can log in semi-regularly, and run ./chkupdates.sh to ensure Ubuntu and it's underlying items are also updated.

My server has hit a peak of 7 users logged in at once, and when we were bunched up we were experiencing some server lag. When we spread out the lag mostly went away. I was monitoring the performance stats of the VM while doing this and both bandwidth, CPU usage, and memory usage were all well under control and not brushing up against any limits. I have read that Valheim, both the server and client, have a hard-coded cap of 64KB/s network traffic, and when players bunch up it starts to to hit that cap and create lag. There are ways to edit the DLL files to increase those hard-coded caps, however when updates or validates are run these changes will be "corrected." I'm simply waiting for IronGate to hopefully increase these limits.

All that said, you are done. Go forth, enjoy Valheim, and share in the glory!

This article was updated on 21/02/22 17:33:13