Dedicated Valheim server with insights

In this blog post, I will talk about how I have set up our server on Google Cloud, installed Valheim, and added some metrics to Grafana Cloud. Valheim is a brutal exploration and survival game for 1-10 players, set in a procedurally-generated purgatory inspired by viking culture. At Fullstaq where I work, we wanted to be able to play this game on our own server!

But Wiard, you are a Kubernetes fanboy, why a VPS?

I like Kubernetes. Yet it’s not the solution to everything. What I wanted was a minimum effort, maximum satisfaction. Hosting a game-server, especially one like Valheim is not that suitable for a cloud-native build. Especially when I only want one server. It requires a volume, it cannot be scaled over multiple instances/pods nor is there any way to make it highly available. I also need multiple TCP & UDP ports to be available, which is doable in Kubernetes but it’s not that simple as an HTTP load balancer.

Google Cloud Compute Engine

I manually added an instance “e2-medium (2 vCPUs, 4 GB memory)” with the image “ubuntu-1604-xenial-v20210211” and gave it a 30GB SSD persistent disk.

I also gave it a network tag “valheim” for our firewall setup later on.

Why manual and not via Terraform or any other form of infra-as-code? Because it’s just a one-time thing. It’s going to be a temporary project. Let me show you this XKCD https://xkcd.com/1205/

time

Firewall

For TCP I opened: 2456-2458,27015-27030,27036-27037 For UDP: 2456-2458,4380,27000-27031,27036 The source range is 0.0.0.0/0 (everything) and the target we do by our tag “valheim”.

firewall

Linux GSM

Linux Game Server Manager is something I found while using Google on how to host a Valheim server. https://linuxgsm.com/ - It’s pretty great to just set something up.

Let me talk you through on how to set this up;

Adding dependecies:

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 libsdl2-2.0-0:i386 libsdl2-2.0-0

Adding the user (which needs sudo rights)

sudo adduser vhserver

Adding sudo rights

sudo visudo

And then add the following:

vhserver ALL=(ALL) NOPASSWD:ALL

Next we move towards our user and start installing things:

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

And follow the instructions that follow in the install.

I recommend reading the usage of vhserver here: https://linuxgsm.com/lgsm/vhserver/

Configuration

Next we add a file for our gameserver that overrides the defaults:

vi /home/vhserver/lgsm/config-lgsm/vhserver/vhserver.cfg

In which you can add the following:

steammaster="true"
servername="YourServerName"
# Minimum password length is 5.
serverpassword="yourpassword"
port="2456"
gameworld="${selfname}"
public="1"

You also could view the configuration in /home/vhserver/lgsm/config-lgsm/vhserver/_default.cfg and change values of this by adding them to /home/vhserver/lgsm/config-lgsm/vhserver/common.cfg

Getting insights

So I also wanted to monitoring our server or alteast have some insights. Therefor I will use Prometheus with a Prometheus node exporter and Grafana cloud.

setting up Grafana cloud

Go to: https://grafana.com/signup/cloud/connect-account?pg=prod-cloud&plcmt=hero-btn1

Which gives free forever access:

When you are all set, login and go to: https://grafana.com/orgs/{your-org-name}/api-keys and generate an API key with the role MetricsPublisher

Save this data for our next steps, as we are going to write Prometheus data to this.

Prometheus setup

I’m just going to copy/paste my commands. If you want more information on what/how, I would recommend reading other guides on how Prometheus works and how to properly set this up.

sudo useradd --no-create-home --shell /bin/false prometheus
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo mkdir /etc/prometheus
sudo mkdir /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus
cd ~
curl -LO https://github.com/prometheus/prometheus/releases/download/v2.25.0/prometheus-2.25.0.linux-amd64.tar.gz
tar xvf prometheus-2.25.0.linux-amd64.tar.gz
sudo cp prometheus-2.25.0.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.25.0.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus
sudo chown prometheus:prometheus /usr/local/bin/promtool
sudo cp -r prometheus-2.25.0.linux-amd64/consoles /etc/prometheus
sudo cp -r prometheus-2.25.0.linux-amd64/console_libraries /etc/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus/consoles
sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries
rm -rf prometheus-2.25.0.linux-amd64.tar.gz prometheus-2.25.0.linux-amd64

We are also going to use a node exporter:

curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.1.1/node_exporter-1.1.1.linux-amd64.tar.gz
tar -xvf node_exporter-1.1.1.linux-amd64.tar.gz
sudo cp node_exporter-1.1.1.linux-amd64/node_exporter /usr/local/bin/

Setting up Prometheus configuration

sudo vi /etc/prometheus/prometheus.yml

Adding the folowing with the API key data we have created in our Grafana cloud step.

global:
  scrape_interval: 15s

remote_write:
- url: https://prometheus-us-central1.grafana.net/api/prom/push
  basic_auth:
    username: your-grafana-cloud-user
    password: your-grafana-cloud-password

scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'node'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9100']

And finish with setting the right chown:

sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml

Now we add a service for Prometheus:

sudo vi  /etc/systemd/system/prometheus.service

Adding:

[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
    --config.file /etc/prometheus/prometheus.yml \
    --storage.tsdb.retention=1d \
    --storage.tsdb.path /var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries

[Install]
WantedBy=multi-user.target

And a service for our node exporter:

sudo vi /etc/systemd/system/node_exporter.service

Adding:

[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --collector.systemd --collector.processes

[Install]
WantedBy=multi-user.target

And enabling and starting everything:

sudo systemctl daemon-reload
sudo systemctl start prometheus
sudo systemctl enable prometheus
sudo systemctl start node_exporter
sudo systemctl enable node_exporter

Now we can also start our game server with:

./vhserver start

Grafana dashboard

Next we can go to Grafana and add a dashboard. I have used this one: https://grafana.com/grafana/dashboards/1860 which can be added by importing a dashboard and inputting ID: 1860

When metrics are coming in, you eventually should end up with something like this:

grafana

Enjoy playing Valheim!

I'm working on releasing a monthly newsletter which will contain resources about: Cloud-native, Security, "DevOps", and a big focus on Observability. If you happen to like my blog posts, consider subscribing to my newsletter list!

comments powered by Disqus