Introduction
This guides explains how to set up automatic update for a dedicated Valheim server with Docker. Automatic update is exciting because it minimizes server downtime as a human no longer needs to manually update and restart the server, giving a true 24/7 server uptime experience.
This guide assumes you have already successfully set up a dedicated server. It builds on the previous guide Host Valheim with Docker that covers the basics of running a dedicated server at home. I recommend reading through the previous guide if you haven’t already, as this guide will reference many ideas and keywords introduced previously.
If you’re quite familiar with Valheim servers, Docker, and Bash, feel free to jump straight to using the image I built:
- Docker Hub: sethmachineio/valheim-server
- GitHub: valheim-server-docker
Why automatic update
The idea behind automatic update is simple: if there’s a newer version of the Valheim server, upgrade the current server to it. Updating the Valheim server is necessary due to Valheim’s client-server model: whenever the game gets new content, the servers also get updates. Further, updates to the game are pushed unilaterally–players have no choice whether to update or not. If there is a version mismatch between a game client and a server, players cannot join the server! This means there is no way around updating the server.
The “easy” way to do the update is have the human admin be notified when an update is available. The human admin needs to shut down the server, perform the update, and then restart the server. These are all manual steps that have a single point of failure: the human admin needs to be available. Imagine the admin is sick, loses internet connection, or otherwise is unavailable for a longer period of time; there is the potential for unacceptable downtime for a dedicated server.
Automatic update further reduces manual administration of the server since no human needs to be involved, allowing it to be closer to a true 24/7 uptime experience. Valheim is still in its infancy and we can continue to expect a stream of new content and bug fixes that automatic update will handle without friction.
In summary:
- New game clients cannot join an outdated server. To keep the server running 24/7 requires updating it as soon as new content is available.
- Automatic update removes the need for a human administrator to detect the update, stop the server, update the server, and restart it. This can enable the server to run 24/7 on the latest updates without having to wait for an admin to perform the update.
The challenge of automatic update
OK, so if you’ve gotten this far you may be sold. Automatic update sounds fantastic! Unfortunately, the Valheim server itself comes with no automatic update feature. That means it is up to us to come up with a system that can perform all the steps for automatic update. This adds additional complexity to our dedicated server software, making it harder to understand, debug, and maintain.
Another issue is that updating requires stopping the current server. This can lead to a slew of different problems for players such as:
- How can players be warned that the server is updating (and therefore that they’ll be kicked off)?
- Should players or an admin be able to delay or stop an update? Imagine players are still on the old client (a new Valheim update was sent out while they are still playing). The old server will work fine for these players until they update their game client.
- How can players be told the update is complete and the server is back online so they can continue playing instead of manually checking the server list?
To keep this automatic update guide simple, we won’t cover how to handle the challenges associated with notifying players about updates and any impact it could have on an ongoing game. Notifications about server status are very important and merit a separate guide.
Steps for automatic update
The idea behind automatic update is simple: update the server whenever a new version is available. This can be broken down into several steps:
- Detect that new updates are available and that the server is outdated
- Stop the current running server so updates can be performed
- Perform the actual update and validate the server is updated
- Start up the server again
Each of these steps is simple to understand but the implementation of each may not be straightforward. We will cover each step and see how they can be orchestrated together to build a system for automatic update.
Environment for testing
When setting out to build an automatic update system, it is key verify that it behaves as expected before use on an actual server. Automatic update requires stopping the server, updating it, and starting it up again. If any of these operations fail, the server will be unusable until an admin is available to correct the issue. Thus, it is critical to verify these steps work before adding the automatic update feature to a real Valheim server. This is often how real world software is tested in order to minimize customer impact when adding new features.
Verifying that automatic update works is tricky, since (1) we cannot predict when a new update is coming in and (2) a fresh download of the Valheim server with Steamcmd will always yield the latest version. To verify that our automatic update works, we can use an outdated version of the Valheim server. If our code is written correctly, then (1) we expect the server to update to the latest version and (2) we are able to play on the updated server.
For testing purposes, I’ll be using an outdated copy of the Valheim server (version 0.146.8) so that we can trigger an automatic update. The image is available here: sethmachineio/valheim-server:0.146.8.
Logging
The demands of automatic update require orchestrating several different steps: detecting an update, shutting down the server, updating the server, and starting it backup. In the previous guide we built a simple system: startup the server once and shutdown the server once. Our new automatic update system can potentially start up, update, and shut down an infinite number of times. To handle this massive increase in complexity, we will want keep track of the state of automatic update to understand how it is behaving as it runs for real, which will help in debugging any unforeseen issues going forward. Enter logging, which is exactly what is sounds: keep track of key state about our system as it performs different steps as human readable text. Previously we had used just echo
statements, but these require heavy modification to be of use in our new, more complex system (e.g. timestamps, which function the message came from, etc.).
For logging we will use b-log which runs out of the box with logging levels like INFO
, WARN
, and ERROR
.
To view these logging statements from a running Docker container, use docker logs <container-name>
, e.g. docker logs valheim-server
. It is also possible to save the output to a log file for additional inspection.
Set up outdated server
Here is how we can setup an environment to test automatic update:
Pull down the outdated Valheim server docker image:
docker pull sethmachineio/valheim-server:0.146.8
Run the Docker image as a named container. You can make up parameters as we’re only interested in getting the old Valheim server copy:
docker run --name=old-valheim -d \
-p 2456:2456/udp -p 2457:2457/udp -p 2458:2458/udp \
-v /Users/sdworman/valheim-data:/home/steam/valheim-data \
--env VALHEIM_SERVER_NAME="sethmachine" \
--env VALHEIM_WORLD_NAME="MadeUpWorld" \
--env VALHEIM_PASSWORD="HardToGuessPassword" \
sethmachineio/valheim-server:0.146.8Make a
dev
directory in order to separate files used only local development:mkdir dev/
Copy all of the Valheim server contents from the running image to your local machine.
docker cp old-valheim:/home/steam/valheim-server/ dev/
The old server files should now be copied over. Verify with
ls dev/valheim-server
on your local machine:% ls dev/valheim-server
LinuxPlayer_s.debug linux64 start_server_xterm.sh valheim_server.x86_64
UnityPlayer.so server_exit.drp steam_appid.txt valheim_server_Data
UnityPlayer_s.debug start-valheim-server.sh steamapps
Valheim Dedicated Server Manual.pdf start_server.sh steamclient.soStop and delete the old container:
docker stop old-valheim && docker rm old-valheim
Write a new Dockerfile that copies over the old server files instead of downloading it from Steam. This looks nearly identical to the Dockerfile from the previous guide.
FROM cm2network/steamcmd:latest
# need to be ROOT to install new programs
USER ROOT
RUN apt-get update && apt-get install git -y
# where Steam is installed
ENV STEAM_DIR = "/home/steam/Steam"
# where steamcmd is installed
ENV STEAM_CMD_DIR = "/home/steam/steamcmd"
# where the Valheim server is installed to
ENV VALHEIM_SERVER_DIR "/home/steam/valheim-server"
# clone the latest b-log from git, remove git to reduce image size, then allow the Steam user to use b-log
RUN cd ${STEAM_DIR} && git clone https://github.com/idelsink/b-log.git && apt-get remove git -y && chown -R steam:steam b-log/
USER steam
# install the Valheim server
COPY --chown=steam dev/valheim-server ${VALHEIM_SERVER_DIR}
# RUN ./steamcmd.sh +login anonymous \
# +force_install_dir $VALHEIM_SERVER_DIR \
# +app_update 896660 \
# validate +exit
# where world data is stored, map this to the host directory where your worlds are stored
# e.g. docker run -v /path/to/host/directory:/home/steam/valheim-data
ENV VALHEIM_DATA_DIR "/home/steam/valheim-data"
# don't change the port unless you know what you are doing
ENV VALHEIM_PORT 2456
# server and world name are truncated after 1st white space
# you must set values to the server and world name otherwise the container will exit immediately
ENV VALHEIM_SERVER_NAME=""
ENV VALHEIM_WORLD_NAME=""
ENV VALHEIM_PASSWORD "password"
# the server needs these 3 ports exposed by default
EXPOSE 2456/udp
EXPOSE 2457/udp
EXPOSE 2458/udp
VOLUME ${VALHEIM_DATA_DIR}
# copy over server start script
COPY --chown=steam start-valheim-server.sh ${VALHEIM_SERVER_DIR}
WORKDIR ${VALHEIM_SERVER_DIR}
ENTRYPOINT ["./start-valheim-server.sh"]Note the “install” command is now just copying over the old Valheim server:
COPY --chown=steam dev/valheim-server ${VALHEIM_SERVER_DIR}
. A copy of start script can be found here: start-valheim-server.sh.Create a new test image as needed:
docker build -t old-valheim-server/old-valheim-server -f Dockerfile --no-cache .
.Dockerfile
is the name of the Dockerfile in the current directory.
We will be using this Dockerfile as a basis for writing automatic update and will frequently rebuild it as we add and test additional functionality to support automatic update.
Detect server updates
Find local build ID
Now we have a way to run an outdated Valheim server, we need to find a way to know there is an update available. Unfortunately, the Valheim server does not provide any native functionality to do this. Instead, we will need to examine the server’s build ID. Steam apps (e.g. the Valheim server) indicate version through a buildid (build ID). We can view all the build IDs of the Valheim server here: Valheim Server builds. As of April 19, 2021, the latest build ID is 6508109. As the Valheim server is a Steam app, we can find the build ID by examining its local app manifest file.
The manifest can be found here in the Valheim server files: valheim-server/steamapps/appmanifest_896660.acf
. Within the Docker container, the full path is /home/steam/valheim-server/steamapps/appmanifest_896660.acf
. A description of the format can be found here: ACF Format. Here is what the file looks like:
% cat dev/valheim-server/steamapps/appmanifest_896660.acf |
Of note is the line "buildid" "6315977"
which tells us the build ID of the local Valheim server. Local here means the copy of the Valheim server we have downloaded already (as opposed to the latest or remote version). Build ID 6315977 means we’re about 3 builds behind, the latest being 6508109 (as of April 19th, 2021).
We will extract the build ID using a text processing tool called pcregrep. pcregrep allows writing regular expressions that can match patterns that span multiple lines. The multiline functionality will be needed later for finding the remote/latest build ID. Alternative approaches include: (1) Python libaries to parse the ACF format and (2) native Linux grep. We won’t use Python in order to minimize our dependency footprint (it can add nearly 1 GB to the Docker image size). grep is not an option as it does not support multiline pattern matching which will be needed.
Now to get the local build ID programmatically:
Modify the Dockerfile so the first 3 lines look like:
FROM cm2network/steamcmd:latest
USER root
RUN apt-get update && apt-get install pcregrep -y && apt-get install git -yRe-build the Docker image and run it as a named container, e.g.
valheim
.Enter the running container using
docker exec -it valheim /bin/bash
.Enter the directory that contains the manifest, e.g.
cd /home/steam/valheim-server/steamapps
Verify the app manifests exists, e.g.
cat appmanifest_896660.acf
.Pipe output to
pcregrep
and look for “buildid”:cat appmanifest_896660.acf | pcregrep "buildid"
:"buildid" "6315977"
The line with the build ID is now returned. We only want the numbers, so we need to modify the regular expression further:
cat appmanifest_896660.acf | pcregrep -o1 -M '"buildid".*"([0-9]+)"'
. This should output “6315977”!
The regular expression essentially says: find the line with build ID and then give me back all the numbers surrounded by quotes. Don’t worry if the regular expression looks like voodoo; what is important is that we now have a reliable way to get the local build ID!
Now we can reliably find the build ID of our local Valheim server. If we can find the the latest (remote) build ID and compare this to our local build ID, we can know whether the server needs to be updated (i.e. the build IDs do not match).
Find remote build ID
Fortunately, Steamcmd provides a few methods to query Steam about the latest build IDs of a Steam app. +app_info_update
provides the most recent “app info”, which will contain the latest build ID for the Valheim server. +app_info_print
will dump this information to standard output (stdout) from which the remote build ID can be extracted. For more details on the command line options, see Steamcmd Command Line Options.
Within the Docker container, the following command should return the latest info for the Valheim server: /bin/bash /home/steam/steamcmd/steamcmd.sh +login anonymous +app_info_update 1 +app_info_print 896660 +quit > valheim-app-info
. Note I’ve saved the output to a local file for further examination. Recall that 896600 is the Steam app ID for the Valheim server. You should see the following output, which is quite verbose (I cut off the parts about Steam updating):
"896660" |
Of interest is the line starting with “branches” followed by “public”. The “buildid” under “public” should contain the latest build ID:
"branches" |
In this case it contains an even more outdated build ID 6287700. Running cat valheim-app-info | grep "6508109"
doesn’t seem to yield anything either (6508109 is the latest build ID as of April 19th, 2021).
It turns out Steam caches the app info of all installed apps. When Steamcmd requests updated app info, it will first look at the local cache. If the cache doesn’t exist, only then will it ask Steam for the latest app info. In the Docker container, the cached app info (for all Steam apps installed, not just Valheim) can be found at /home/steam/Steam/appcache/appinfo.vdf
. Let’s delete appinfo.vdf
and then re-run the command:
rm /home/steam/Steam/appcache/appinfo.vdf |
Now look for the latest build ID: cat valheim-app-info | grep "6508109"
. This should yield the following output:
"buildid" "6508109" |
The relevant section of the output now looks like:
"branches" |
To extract the latest build ID we will use regular expressions again. This time the regular expression will need to span multiple lines (we want the “buildid” inside “public” and not any other “buildid” lines). As an aside, the actual output format is called VDF (Valve Key Files Format). Unfortunately, there is no Linux package to parse VDF (though Python libraries do exist, e.g. ValvePython).
Here is what the regular expression looks like that pulls out the public build ID:
cat valheim-app-info | pcregrep -o1 -M '"branches".*\n*.*{\n*.*"public".*\n*.*{.*\n*.*"buildid".*"([0-9]+)"' |
This should output the latest build ID 6508109!
Compare build IDs
It is now possible to extract the local build ID (version of the Valheim server currently being run) and the remote build ID (latest version of the Valheim server). These two build IDs can be compared to determine if the server has to be updated. There’s a lot to keep track of, so it makes sense to begin organizing our automatic update code into different script files. Below is what I’ve come up with for a 1st iteration of checking if the server needs to be updated. The file is named update-valheim-server.sh
:
|
Note that the script references environment variables defined in both the Dockerfile and the original start-valheim-server.sh
, and also defines new ones that keep track of local build ID (VALHEIM_SERVER_LOCAL_BUILD_ID
), remote build ID (VALHEIM_SERVER_REMOTE_BUILD_ID
), the Valheim server app manifest (VALHEIM_SERVER_APP_MANIFEST
), and Steam’s app info cache (STEAM_CACHED_APP_INFO
).
The update loop
In the previous section we were able to find the local build ID and the remote build ID of the Valheim server. When the local build ID and the remote build ID are not the same, it means our local Valheim server needs to be updated. Ideally we would want to update as soon as the remote build ID changed. However, there’s no magical way to know that the remote build ID has changed other than by running findAndSetRemoteValheimServerBuildId
over and over again (as an aside, SteamWebPipes would allow for listening for new builds but it is far too complex to cover here). This means we will need some mechanism to periodically query for the remote build ID and then compare to the local build ID while the Valheim server is running.
This is the update loop, which every so often will need to query Steam to find the latest build ID and compare to the build ID of the current server. The update loop needs to run forever and will only terminate if the Docker container itself is stopped. In Bash, the loop might start to look like this:
while true |
Some important details:
$VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY
controls how often the update is checked for- sleep pauses the process for the specified duration, e.g.
sleep 30s
would sleep for 30 seconds before continuing to execute code. Note that this means the update loop and the Valheim server must necessarily run in different processes–checking for an update should not impact what the server is doing and vice versa. $VALHEIM_SERVER_LOCAL_BUILD_ID
,$VALHEIM_SERVER_LOCAL_BUILD_ID
variables keep track of what the local and remote build IDs are at all timesshutdownValheimServer
,updateValheimServer
,assertLocalBuildIsLatest
andstartValheimServer
are all functions that we will have implement later.
In regard to $VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY
, what duration should be chosen? A very short value, e.g. 30 seconds, will waste a lot of resources just to confirm the server is up to date (it is unlikely an update comes out every 30 seconds) and Steam could potentially throttle or block our request. A longer duration, e.g. 2 hours, risks having the server unusable for up to 2 hours if an update has been pushed out to clients already. For a heavily used server, a lower value such as 5, 10 or 15 minutes may be best. The frequency chosen is the absolute maximum amount of time a server would not be joinable from a newer game client. It is best to use short durations like 5s for locally debugging and confirming that automatic updating (as we are doing in this guide). The auto update frequency will be an additional parameter that can be customized at runtime when launching the server rather than hardcoded.
We will now implement the functions from above that we had left undefined. Where possible, we will abstract each function to its own script file to logically organize the automatic update system.
start-valheim-server.sh
This script defines the startValheimServer
function. It also creates the VALHEIM_SERVER_PID
variable that keeps track of the process ID of the server. The process ID allows to shut down the server without losing data.
|
Some important details:
- This is more or less a copy paste of
start-valheim-server
script in the previous guide - the
&
operator at the end a command means to launch that process in the background - the
$!
operator provides the process ID (pid) of the last process launched in the background (in this case, the Valheim server process) VALHEIM_SERVER_PUBLIC
is a new parameter from recent updates that controls whether the server is visible in the join list.
shutdown-valheim-server.sh
This script defines the shutdownValheimServer
function that shuts down the Valheim server process (not necessarily the Docker container). Note that it references VALHEIM_SERVER_PID
from the start-valheim-server.sh
script. There is an additional function shutdownValheimServerAndExit
which shuts down the Valheim server and exits the Docker container. When the server is shut down just for an update, we don’t want to exit the container and should use shutdownValheimServer
. If the Docker container itself is requested to stop, e.g. docker stop valheim-server
, then shutdownValheimServerAndExit
should be run.
|
Some important details:
- use
shutdownValheimServerAndExit
when stopping the whole Docker container - use
shutdownValheimServer
when stopping the Valheim server for an update (and intending to start it again when the update is finished) kill -2
sends aSIGINT
interrupt signal to the Valheim server (equivalent to CTRL+C), which triggers it to shutdown correctly (no loss of data).
update-valheim-server.sh
This is a continuation of update script that we wrote in Detect Server Updates which finds the local and remote build IDs. Let’s expand it further to include update loop and the update logic.
|
Some important details:
assertLocalBuildIsLatest
checks to see that the local and remote build IDs are the same after an update. If this is not true, then something has gone wrong and this will alert us in an error log statement.updateValheimServer
runs the Steamcmd command needed to update the server to the latest version.updateValheimServerIfNewerBuildExists
updates the Valheim server on startup so that whenever a stopped container is resumed (e.g.docker start valheim-server
) it is updated without going through the update loop. This function is only meant to run once when the container starts and never again.checkForAndUpdateValheimServer
gets the latest remote build ID, compares it to the local build ID, and if they are different, performs the update. This involves stopping the Valheim server (shutdownValheimServer
), updating it (updateValheimServer
), and then starting it again (startValheimServer
).startUpdateLoop
runs forever and executescheckForAndUpdateValheimServer
at the frequency dictated by$VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY
. If the value were 30m, then the loop would check for an update every 30 minutes.trap 'shutdownValheimServerAndExit' SIGTERM
intercepts any SIGTERM signals and then requests the Valheim server to stop in order to shut down without data loss (e.g. the container is stopped viadocker stop valheim-server
).wait $sleep_pid
allows the sleep process to be interrupted by an interrupt signal, i.e. when the Docker container is stopped (docker stop valheim-server
). Without this, the sleep would not terminate and the Valheim server would force killed, potentially resulting in loss of data.
valheim-server-entrypoint.sh
To handle the different runtime parameters and actually kick off the Valheim server and update loop, we will use an entrypoint script. The entrypoint will also allow a user to disable the automatic update feature if they wish to manually control updates (perhaps running a legacy server, etc.).
|
Some important details:
- the
source
command effectively imports all the variables and functions of another script, so they can be re-used in the entrypoint and all of its child processes. VALHEIM_SERVER_UPDATE_ON_START_UP
is a runtime parameter that controls whether to update the server whenever starting the container for the first time rather than waiting for the update loop to detect an update.VALHEIM_SERVER_AUTO_UPDATE
enables the auto update feature; if set to 0 then the container will simply run the Valheim server at its current version. Any other value will enable auto update. Some users may wish to disable auto update if they are running a legacy server or want full control of updates.terminateUpdateLoop
handles stopping the update loop if the container is stopped, e.g.docker stop valheim-server
. It handles the SIGTERM signal from Docker and then redirects it to update loop process, which causes it to executeshutdownValheimServerAndExit
.
How it all works
The organization of the scripts is key to making the automatic update process function correctly. In this case, there are at least 4 different processes at work within the Docker container that are running all the time:
- The entry point process, which Docker executes when it starts (i.e.
valheim-server-entrypoint.sh
) - The update loop (from
startUpdateLoop
) - The sleep process (the pause before checking for an update)
- The Valheim server
In Bash, a process is only aware of its immediate child processes. The update loop process is an immediate child of the entry point. The sleep process and the Valheim server are immediate children of the update loop. This is why startValheimServer
is done in the update loop rather than in the entry point script. If Valheim was instead started in the entry point, then the update loop would be unable to stop the server (VALHEIM_SERVER_PID
would resolve to an empty string). However, when automatic update is disabled, we do start Valheim in the entry point, as it is simply meant to run forever and never be stopped within the container.
This process hierarchy is illustrated in how the container is stopped with automatic update:
When the container is stopped, Docker sends a SIGTERM signal to the entry point process. In the entry point, the signal is trapped with trap 'terminateUpdateLoop' SIGTERM
. This intercept’s the SIGTERM and executes the code in terminateUpdateLoop
. The function sends a SIGTERM to the update loop process via kill -15 $VALHEIM_SERVER_UPDATE_LOOP_PID
. The update loop traps this SIGTERM as well via trap 'shutdownValheimServerAndExit' SIGTERM
. The method shutdownValheimServerAndExit
sends a SIGINT to the Valheim server and then exits with 0.
Updated Dockerfile
We now need to update the Dockerfile to use these new scripts and create the new parameters that control how automatic update works. Here is what our updated Dockerfile should look like:
FROM cm2network/steamcmd:latest |
Note we will still use the outdated server until we verify the automatic update behaves as expected, as done with COPY --chown=steam dev/valheim-server ${VALHEIM_SERVER_DIR}
.
Testing automatic update
Rebuild the Docker image with the updated Dockerfile and scripts, e.g. docker build -t valheim/auto-update -f Dockerfile --no-cache .
Make sure the script files and the dev/valheim-server
are in the current directory when building the image.
Verify it automatically updates
Run the image in a new container using these parameters:
docker run --name=valheim-server -d \
-p 2456:2456/udp -p 2457:2457/udp -p 2458:2458/udp \
-v /home/sethmachine/valheim-data:/home/steam/valheim-data \
--env VALHEIM_SERVER_NAME="OutdatedServer" \
--env VALHEIM_WORLD_NAME="OutdatedWorld" \
--env VALHEIM_PASSWORD="HardToGuessPassword" \
--env VALHEIM_SERVER_UPDATE_ON_START_UP=0 \
--env VALHEIM_SERVER_AUTO_UPDATE=1 \
--env VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY=10s \
valheim/auto-updateNote you will need to substitute the local worlds directory
/home/sethmachine/valheim-data
with an actual directory on your computer.VALHEIM_SERVER_UPDATE_ON_START_UP
is set to 0 so we can test the update loop.VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY
is set to 10 seconds to give us time to tail log files right before the update happens.Optionally, choose a longer frequency update such as 5 minutes (5m) and verify the server is outdated in the Valheim list. Five minutes is chosen so the server can fully start and be listed on Valheim. Attempting to join it should result in an error.
Tail the logs of the running container in a separate terminal, e.g.
docker logs -f valheim-server
. You should see output like below (note yours may be colored differently):[2021-05-15 15:11:26.426][WARN ][main:51 ] Experimental auto update is enabled. The server will automatically update and restart when a new version is detected
[2021-05-15 15:11:26.429][INFO ][main:52 ] Updates to the server will be checked every 10s
[2021-05-15 15:11:26.432][INFO ][main:57 ] Valheim server update loop PID is: 9
[2021-05-15 15:11:26.432][INFO ][startValheimServer:14 ] Starting the Valheim server
[2021-05-15 15:11:26.435][INFO ][startValheimServer:15 ] LD_LIBRARY_PATH: ./linux64:
[2021-05-15 15:11:26.437][INFO ][startValheimServer:17 ] Valheim port is: 2456
[2021-05-15 15:11:26.440][INFO ][startValheimServer:18 ] Valheim server name is: OutdatedServer
[2021-05-15 15:11:26.442][INFO ][startValheimServer:19 ] Valheim world name is: OutdatedWorld
[2021-05-15 15:11:26.444][INFO ][startValheimServer:24 ] The Valheim server is set to public visibility. It will be visible in the server list. Players will still need to enter the password to join
[2021-05-15 15:11:26.446][INFO ][startValheimServer:37 ] Valheim server PID is: 17
[2021-05-15 15:11:26.448][INFO ][startServerAndUpdateLoop:111] Sleeping for 10s before checking for Valheim server updateAfter 10 seconds, the log output should begin to change and show the automatic update steps:
[2021-05-15 15:11:36.452][INFO ][checkForAndUpdateValheimServer:89 ] Checking to see if the Valheim server needs to be updated
[2021-05-15 15:11:36.458][INFO ][findAndSetLocalValheimServerBuildId:30 ] The local build ID is 6315977
[2021-05-15 15:11:36.461][INFO ][findAndSetRemoteValheimServerBuildId:44 ] Querying the remote server for the latest build ID for the Valheim server
[2021-05-15 15:11:57.070][INFO ][findAndSetRemoteValheimServerBuildId:56 ] The remote server build ID is 6663905
[2021-05-15 15:11:57.073][INFO ][checkForAndUpdateValheimServer:96 ] Updating the Valheim server from 6315977 (old) to 6663905 (new)
[2021-05-15 15:11:57.075][WARN ][shutdownValheimServer:19 ] Shutting down the Valheim server. PID is: 17
[2021-05-15 15:12:01.043][INFO ][updateValheimServer:69 ] Updating the Valheim serverThe logs should then show Steam updating the server:
WARNING: setlocale('en_US.UTF-8') failed, using locale: 'C'. International characters may not work.
Redirecting stderr to '/home/steam/Steam/logs/stderr.txt'
[ 0%] Checking for available updates...
[----] Verifying installation...
Steam Console Client (c) Valve Corporation
-- type 'quit' to exit --
Loading Steam API...OK.
Connecting anonymously to Steam Public...Logged in OK
Waiting for user info...OK
Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
Update state (0x61) downloading, progress: 0.11 (1048576 / 979372945)
Update state (0x61) downloading, progress: 5.85 (57256869 / 979372945)
Update state (0x61) downloading, progress: 87.31 (855081381 / 979372945)
Update state (0x61) downloading, progress: 94.83 (928751241 / 979372945)
Update state (0x61) downloading, progress: 98.07 (960498577 / 979372945)
Update state (0x61) downloading, progress: 99.79 (977275793 / 979372945)
Update state (0x101) committing, progress: 0.00 (0 / 979372945)
Success! App '896660' fully installed.Finally, the server should start back up again. It will still check for updates but since it is now up to date, nothing should happen:
[2021-05-15 15:12:20.379][INFO ][findAndSetLocalValheimServerBuildId:28 ] The local build ID was updated from 6315977 to 6663905
[2021-05-15 15:12:20.384][INFO ][assertLocalBuildIsLatest:64 ] The local build ID is the same as the latest remote build ID
[2021-05-15 15:12:20.390][INFO ][startValheimServer:14 ] Starting the Valheim server
[2021-05-15 15:12:20.393][INFO ][startValheimServer:15 ] LD_LIBRARY_PATH: ./linux64:./linux64:
[2021-05-15 15:12:20.398][INFO ][startValheimServer:17 ] Valheim port is: 2456
[2021-05-15 15:12:20.402][INFO ][startValheimServer:18 ] Valheim server name is: OutdatedServer
[2021-05-15 15:12:20.406][INFO ][startValheimServer:19 ] Valheim world name is: OutdatedWorld
[2021-05-15 15:12:20.409][INFO ][startValheimServer:24 ] The Valheim server is set to public visibility. It will be visible in the server list. Players will still need to enter the password to join
[2021-05-15 15:12:20.412][INFO ][startValheimServer:37 ] Valheim server PID is: 164
[2021-05-15 15:12:20.418][INFO ][startServerAndUpdateLoop:111] Sleeping for 10s before checking for Valheim server update
[2021-05-15 15:12:30.426][INFO ][checkForAndUpdateValheimServer:89 ] Checking to see if the Valheim server needs to be updated
[2021-05-15 15:12:30.432][INFO ][findAndSetLocalValheimServerBuildId:30 ] The local build ID is 6663905
[2021-05-15 15:12:30.435][INFO ][findAndSetRemoteValheimServerBuildId:39 ] Deleting cached app info: /home/steam/Steam/appcache/appinfo.vdf
[2021-05-15 15:12:30.440][INFO ][findAndSetRemoteValheimServerBuildId:44 ] Querying the remote server for the latest build ID for the Valheim server
[2021-05-15 15:12:35.529][INFO ][findAndSetRemoteValheimServerBuildId:56 ] The remote server build ID is 6663905
[2021-05-15 15:12:35.533][INFO ][checkForAndUpdateValheimServer:94 ] The Valheim server is already up to date with build ID 6663905Optionally, verify the server is updated in the list and attempt to join it once it has started up again.
We should verify that the server stops gracefully after an update. Run
docker stop valheim-server
and see this output:[2021-05-15 15:14:53.989][INFO ][terminateUpdateLoop:33 ] Terminating the update loop. PID is 9
[2021-05-15 15:14:53.993][WARN ][shutdownValheimServerAndExit:7 ] Shutting down the Valheim server. PID is: 164Inspect the exit code to make sure it is zero (a non-zero exit code would mean a problem):
valheim-server-docker % docker inspect valheim-server --format='{{.State.ExitCode}}'
0Delete the container:
docker rm valheim-server
If you observe similar output, it means the automatic update is working!
Verify it updates on start up
Each time the server is started up, we can check for update rather than wait on the loop to execute. This is potentially faster, as the update is run before the server actually starts. If it is updated on start up, we expect the update loop to not execute. Updating on start up also allows for updating the server without rebuilding the Docker image.
- Run the image in a new container using these parameters:
docker run --name=valheim-server -d \
-p 2456:2456/udp -p 2457:2457/udp -p 2458:2458/udp \
-v /home/sethmachine/valheim-data:/home/steam/valheim-data \
--env VALHEIM_SERVER_NAME="OutdatedServer" \
--env VALHEIM_WORLD_NAME="OutdatedWorld" \
--env VALHEIM_PASSWORD="HardToGuessPassword" \
--env VALHEIM_SERVER_UPDATE_ON_START_UP=1 \
--env VALHEIM_SERVER_AUTO_UPDATE=1 \
--env VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY=10s \
valheim/auto-update - Tail the log files of the container, e.g.
docker logs -f valheim-server
. Instead of starting the server, it should immediately begin performing an update, as shown below:[2021-05-16 00:39:05.678][INFO ][main:28 ] Attempting one time update of the Valheim server on start up
[2021-05-16 00:39:05.680][INFO ][updateValheimServerIfNewerBuildExists:75 ] Checking to see if the Valheim server needs to be updated
[2021-05-16 00:39:05.686][INFO ][findAndSetLocalValheimServerBuildId:30 ] The local build ID is 6315977
[2021-05-16 00:39:05.688][INFO ][findAndSetRemoteValheimServerBuildId:44 ] Querying the remote server for the latest build ID for the Valheim server
[2021-05-16 00:39:19.405][INFO ][findAndSetRemoteValheimServerBuildId:56 ] The remote server build ID is 6663905
[2021-05-16 00:39:19.408][INFO ][updateValheimServer:69 ] Updating the Valheim server - Continue tailing the logs and verify that it the update loop does not update the server:
[2021-05-16 00:39:39.660][WARN ][main:51 ] Experimental auto update is enabled. The server will automatically update and restart when a new version is detected
[2021-05-16 00:39:39.664][INFO ][main:52 ] Updates to the server will be checked every 10s
[2021-05-16 00:39:39.667][INFO ][startValheimServer:14 ] Starting the Valheim server
[2021-05-16 00:39:39.667][INFO ][main:57 ] Valheim server update loop PID is: 93
[2021-05-16 00:39:39.671][INFO ][startValheimServer:15 ] LD_LIBRARY_PATH: ./linux64:
[2021-05-16 00:39:39.674][INFO ][startValheimServer:17 ] Valheim port is: 2456
[2021-05-16 00:39:39.676][INFO ][startValheimServer:18 ] Valheim server name is: OutdatedServer
[2021-05-16 00:39:39.679][INFO ][startValheimServer:19 ] Valheim world name is: OutdatedWorld
[2021-05-16 00:39:39.682][INFO ][startValheimServer:24 ] The Valheim server is set to public visibility. It will be visible in the server list. Players will still need to enter the password to join
[2021-05-16 00:39:39.686][INFO ][startValheimServer:37 ] Valheim server PID is: 101
[2021-05-16 00:39:39.690][INFO ][startServerAndUpdateLoop:111] Sleeping for 10s before checking for Valheim server update
[2021-05-16 00:39:49.662][INFO ][checkForAndUpdateValheimServer:89 ] Checking to see if the Valheim server needs to be updated
[2021-05-16 00:39:49.667][INFO ][findAndSetLocalValheimServerBuildId:28 ] The local build ID was updated from 6315977 to 6663905
[2021-05-16 00:39:49.670][INFO ][findAndSetRemoteValheimServerBuildId:39 ] Deleting cached app info: /home/steam/Steam/appcache/appinfo.vdf
[2021-05-16 00:39:49.674][INFO ][findAndSetRemoteValheimServerBuildId:44 ] Querying the remote server for the latest build ID for the Valheim server
[2021-05-16 00:39:54.476][INFO ][findAndSetRemoteValheimServerBuildId:56 ] The remote server build ID is 6663905
[2021-05-16 00:39:54.479][INFO ][checkForAndUpdateValheimServer:94 ] The Valheim server is already up to date with build ID 6663905 - Stop the container and verify the exit code is 0:
valheim-server-docker % docker stop valheim-server
valheim-server
valheim-server-docker % docker inspect valheim-server --format='{{.State.ExitCode}}'
0 - Delete the container:
docker rm valheim-server
If you observe similar output, it means the update on startup feature is working as expected.
Verify disabling auto update
This is to confirm that the server still works if automatic update is turned off. Turning off automatic update may be useful if you want to run a specific version of the Valheim server, or otherwise want to control when updates happen. In most cases for a server running 24/7, keeping automatic update on is recommended.
- Run the image in a new container using these parameters:
docker run --name=valheim-server -d \
-p 2456:2456/udp -p 2457:2457/udp -p 2458:2458/udp \
-v /home/sethmachine/valheim-data:/home/steam/valheim-data \
--env VALHEIM_SERVER_NAME="OutdatedServer" \
--env VALHEIM_WORLD_NAME="OutdatedWorld" \
--env VALHEIM_PASSWORD="HardToGuessPassword" \
--env VALHEIM_SERVER_UPDATE_ON_START_UP=0 \
--env VALHEIM_SERVER_AUTO_UPDATE=0 \
--env VALHEIM_SERVER_AUTO_UPDATE_FREQUENCY=10s \
valheim/auto-update - Tail the logs and verify the server starts but does not update with
docker logs -f valheim-server
.[2021-05-16 00:47:10.197][INFO ][startValheimServer:14 ] Starting the Valheim server
[2021-05-16 00:47:10.200][INFO ][startValheimServer:15 ] LD_LIBRARY_PATH: ./linux64:
[2021-05-16 00:47:10.205][INFO ][startValheimServer:17 ] Valheim port is: 2456
[2021-05-16 00:47:10.208][INFO ][startValheimServer:18 ] Valheim server name is: OutdatedServer
[2021-05-16 00:47:10.210][INFO ][startValheimServer:19 ] Valheim world name is: OutdatedWorld
[2021-05-16 00:47:10.212][INFO ][startValheimServer:24 ] The Valheim server is set to public visibility. It will be visible in the server list. Players will still need to enter the password to join
[2021-05-16 00:47:10.214][INFO ][startValheimServer:37 ] Valheim server PID is: 14 - Wait for the Valheim server to finish starting up. Then stop the container and verify the exit code is 0:
valheim-server-docker % docker stop valheim-server
valheim-server
valheim-server-docker % docker inspect valheim-server --format='{{.State.ExitCode}}'
0 - Delete the container:
docker rm valheim-server
Be sure to wait for the server to fully start up before stopping the container, otherwise you may see a non-zero exit code.
Usage
The automatic update feature removes the need to keep rebuilding the Docker image whenever Valheim has an update, since it will update itself within the container. This means even if the Docker image’s Valheim server is out of date, the container will run at the latest version once the update has completed. Further, if the container is stopped, it will continue to use the updated Valheim server when started up again. However, if the container is deleted, then it may go through updates if the Docker image uses an older version of the server. Existing worlds can continue to be used without issue as long as the right worlds directory is chosen when starting the container.
You’ll first start the server like this:
docker run --name=valheim-server -d \ |
At some point the server will stop itself, update, and restart when a new update comes in. If ever the server is stopped (either you shut it down manually or the host machine was turned off unexpectedly), the container itself will still exist and have the updated server. Simply start it up again with docker start valheim-server
(or however the container is named) and it should be up to date.
If you need to execute a manual update sooner than the auto update, simple stop the container and then start it again. Make sure VALHEIM_SERVER_UPDATE_ON_START_UP
is set to 1. Starting it again will trigger a check for an update immediately.
Final thoughts
We were able to create a system for automatically updating a Valheim server to enable running it truly 24/7 unsupervised. We organized the different functions of starting, stopping, and updating the Valheim server into separate script files to handle the added complexity of automatic update. We also examined how to forward signals through multiple processes with Bash.
The automatic update Docker image is available on Docker Hub and the corresponding Dockerfile and scripts on GitHub:
- Docker Hub: sethmachineio/valheim-server
- GitHub: valheim-server-docker
Feel free to leave a comment if you found this helpful, have any feedback, or are stuck on any parts of this guide. I’ll do my best to respond and help you!