Host a Valheim Dedicated Server using Azure Container Instances

Jake Lunn
12 min readMar 26, 2021

Before we dive in, here’s some caveats.

Price

Azure is expensive. If you are looking for a cheap alternative to other dedicated server hosts, then Azure probably isn’t it. Azure is primarily marketed toward Enterprise-level applications and deployments, and they definitely charge like it. You can use their Price Calculator here to get an idea of what it would cost. As of writing, you’re probably looking at at least $90 a month.

If you are lucky enough to have Azure credit through your workplace, or are willing to spend a little to learn a little, then read on!

Some basic features are simply missing

If you are coming from the world of Docker containers, kubernetes, etc. then you will likely notice that there are some de facto features in container hosting that are simply missing from Azure Container Instances. There are two features, in particular, which will be a thorn in our side:

  1. You can’t open a single port to both UDP and TCP for a single container — you must choose 1. This will not block us from hosting Valheim, but it does appear to block the server from showing up on the public server list. This means your users will need to direct-connect via the Join by IP option.
  2. You can’t create multiple mounts to the same volume. This is a very counter-intuitive flaw of ACI that virtually every other container host does not have an issue with.

Azure Container Instances, aka ACI, is starting to be notorious for missing some of this basic functionality. Feel free to wander on over to their feedback site to get an idea of what all is missing (and how mad some people are about it).

All of that said, we can still host Valheim on it!

Getting started with the Docker image

There is a fantastic docker image over here that’s all ready to use. It comes with automatic updating and server restarts, too! Please read the documentation to get an idea of everything you can do with that docker image — including (optionally) installing the ValheimPlus mod for your server.

This article won’t dive too much into the docker image itself; we will primarily focus on deploying it to Azure.

Prerequisite Downloads

There’s some tools that you will need in order for this to go smoothly.

  1. The Azure CLI (for deploying to Azure)
  2. Azure Storage Explorer (for browsing your server files)

Note: We will be using the Azure CLI to deploy to Azure in this article. You can optionally deploy through the Azure web portal, but the YAML file we create later is only usable through the CLI. Trust me, it’s a one-line command that is much easier than configuring via the portal.

Authenticating with the Azure CLI

Before we start doing commands, we’ll need to authenticate with Azure in the CLI. Open a new powershell or cmd prompt and type az and then hit enter. You should see an Azure welcome message to confirm that Azure CLI was installed correctly. If you don’t see anything, try closing and re-opening the command prompt window. If that still doesn’t work, make sure you ran the Azure CLI installer (linked above).

Run the following command:

az login

You will be prompted for your credentials in a web browser. Once you are logged in, return to the command prompt window and you should see a print-out of your authenticated account information, as well as your default subscription.

Note: If you have multiple subscriptions, you may have to change contexts to the subscription that you want to use. To change your subscription you can use the command az account set --subscription <name or id>

For more info on using the Azure CLI, see Microsoft’s documentation here.

Step 1: Azure Resource Group Setup

Create a Resource Group in Azure for grouping our valheim server resources together. Make sure you put it in whatever region you will want to host the valheim server.

You’ll want to come up with a resource group name. A common naming convention is <service-short-name>-<region>, e.g. valheimserver-eastus

If you already know how to create an RSG, you can skip to creating an Azure Storage account. Otherwise, here’s two methods:

Via Azure CLI

In PowerShell or command prompt, run the following azure cli command:

az group create --name <YourRsgName> --location <LocationName>

Allow a few moments for the RSG to be created.

If you’re not sure on the region name, you can type the command az account list-locations to print out a list of acceptable regions for your azure account. Choose a region that is close to you and the people who will be playing on your server. There are also minor pricing differences between regions which you can explore here.

Example: az group create --name valheimserver-eastus --location eastus

Via the Portal

  1. Navigate to portal.azure.com and log-in to your Azure account.
  2. On the left hand side, click the fly-out menu and choose “Create a resource”
  3. In the search box type “Resource group” and then create a Resource group.
  4. You can name this whatever you want. A common naming convention is <service-short-name>-<region>, e.g. valheimserver-eastus

Step 2: Azure Storage Setup

The next step is setting up Azure File Storage. This is where our non-temporary server files will live. Containers are temporary — they can be deleted and re-deployed at any moment, and we need to make sure some important files are not deleted along with them.

A few things to note:

1. We are creating a Premium File Storage Account. Why premium? Because Premium storage is low-latency SSD storage that is necessary for our server’s I/O-intensive workload. Choosing a non-Primary file share option would result in higher latency read/write actions that would cause issues with the server. Imagine if your hard-drive was connected to your computer over the internet — that’s essentially what’s happening with this file storage. That’s why we need to make sure it’s ultra-low latency.

2. This storage account is FileShare-only — meaning other things that often come enabled with storage accounts, like blob storage, azure queues, etc. are not included with this variant of azure storage account.

Via Azure CLI

In PowerShell or command prompt, run the following azure cli command:

az storage account create -n <storage account name> -g <rsg name> -l <location name> --sku Premium_LRS --kind FileStorage

Example: az storage account create -n filestgeastus -g valheim-eastus -l eastus --sku Premium_LRS --kind FileStorage

You can name your storage account whatever you like. I chose filestgeastus.

Via Portal

  1. Navigate to portal.azure.com and log-in
  2. On the left hand side, click the fly-out menu and choose “Create a resource”
  3. Search for “Storage Account” and click create.
  4. Make sure you choose the resource group you created before
  5. Name your storage account (e.g. filestgeastus)
  6. Choose the same location as your resource group
  7. Performance: Premium
  8. Account kind: FileStorage
  9. Replication: Locally-redundant storage (LRS)
  10. Skip to the Review + create tab and click Create

Account Name and Account Key

You will need your account name and account key for later steps. I suggest pasting them somewhere for easy reference now.

Your account name is just the name you chose for your storage account. I chose filestgeastus, for example.

You can get the key via the Azure Portal by going into your Storage Account resource, clicking “Access Keys” on the left-hand menu, then revealing the 2 keys and copying one (either one works). Make sure you copy just the key and not the connection string.

You can also get this via the Azure CLI via the command: az storage account keys list -g <resource-group-name> -n <storage-account-name>

Copy the value of either key1 or key2. Either one will work — they just provide an alternative key in-case you need it.

Step 3: Create the File Share

This is basically a sub-step of the previous step, but after creating the Storage Account we’ll need to create the file share. You can do this via the Azure Portal, Azure Storage Explorer, or Azure CLI.

Via Azure CLI

Use the following command (command reference):

az storage share create --name <YourFileShareName> --quota 100 --account-name <YourStorageAccountName> --account-key <YourStorageAccountKey>

Your account key and account name are from Step 2. Refer to that step if you don’t have them readily available.

The quota is the maximum amount of storage space, in GB, your file share will need. Unfortunately Azure’s minimum value for this is 100GB, so we can’t go lower than that. Valheim uses a very small amount of storage, so technically we could’ve gotten away with ~10GB of storage.

You will want to remember the name of the file share for the next step.

Step 4: Create the YAML File

Next we’ll be setting up our YAML file, which we will post to Azure via the CLI to actually do the deployment. I chose to use YAML because it closely mirrors configuration with docker, docker-compose, and kubernetes — and it’s just easier to read than an ARM template. It also has more options than are available in the Azure Portal itself.

Go ahead and create a .yml file and open it up in your favorite text editor.

The official YAML reference for ACI is here.

Full YAML Deployment File (valheim.yml)

Below is the full YAML deployment file. If you want, you can copy/paste the below into your own file and fill out all of the <> with your parameters. If you don’t understand exactly what’s going on in the file below, then keep reading and I’ll break down each section. If you want to skip ahead to the deployment, then skip down to Step 5.

YAML Breakdown: Metadata

The top section of the YAML file is our basic metadata. This tells Azure how to consume this file, what version of the API to use, etc.

Line 3 and Line 4 are important here.

The location node needs to be the location you used for your resource group and file storage.

The name node is what your container group resource will show up as in Azure. I used valheimserver for mine, just to be clear on what it is. You can name it however you like.

YAML Breakdown: Properties

The next section is the Properties section, and you’ll notice it pretty much encompasses the rest of our file’s definitions. This is because the Properties node is an umbrella for everything in our container group. Technically you can have multiple containers in a group, all defined under this Properties node.

The osType property is rather straightforward. Your containers can be either Windows or Linux, and this is where that is set. We are using Linux because they are lighter, faster, and cheaper.

YAML Breakdown: Properties \ Volumes

Here we are defining volumes that can be accessed by our containers. We will be using our file share as our volume.

The name can be anything. It’s primarily so that our container can reference it later.

The azureFile node is where we put our file share credentials. You will need to provide your file share name, storage account name, and storage account key from Step 2 here.

With YAML, you can wrap strings in “quotation” marks or you can just write them out. So either of these lines would be acceptable:

shareName: "my-cool-share"
shareName: my-cool-share

YAML Breakdown: Properties \ ipAddress

In the Properties > ipAddress node, we are setting up a Public IP Address for our container to utilize. This will end up being the IP address that your players connect to.

The type is Public, since this container is internet-facing.

The dnsNameLabel can be anything — it will be the name of the URL that goes with your IP address. For example, if you were to put “mycoolserver” you would get a URL like mycoolserver.eastus.azurecontainer.io as your DNS URL. The eastus would change to whatever region you chose.

You are also unblocking ports for this IP address under the ports node.

YAML Breakdown: Properties \ containers

Here’s where the bulk of our container configuration goes.

The name is your choice, but I recommend something simple like valheimserver .

Under the properties of the container, the image is the name of the docker image we are using. This is all docker needs in order to go out and download the image.

The environmentVariables are where we define the environment variables for our container. You can see more possible environment variables here. The four I’ve listed in the YAML file are the minimum ones we need to provide in order to get a server going.

The ports node defines the ports we need to open for our container. Again, we will be opening ports 2456 and 2457 to allow connections to our Valheim server to pass through.

The resources nodes are where we request the resources that our server will be utilizing. Valheim recommends 2 Cores and 4GB of RAM for a dedicated server, so we requested 2 CPU and 4GB of memory for our container.

The volumeMounts node is where we tell our container how to mount our file share volume. The name needs to match what we named our volume in the root Properties \ Volumes node. The mountPath tells our container where to mount the volume in the container. It’s important we choose the /config path, because that is where our map files and backups will be on the container itself.

Step 5: Deploy!

With our YAML file complete, we are ready to deploy. Before we do, though, you must answer this question: Are you wanting to start a new world? Or are you wanting to bring an existing one?

If you have an existing world you wish to bring, you will need to upload that world to the file storage before we deploy the container so that it loads that world instead of creating a new one when it starts up.

If you want to just create a new world, you can skip the Uploading Existing World section.

Uploading Existing World

First open Azure Storage Explorer. You’ll need to authenticate with your Azure Account. On the left-hand side click Manage Accounts, then Add an account…

In the window that pops up, click Subscription > Azure. You’ll then get a pop-up window to login to your Azure account. Once that’s done, you should see your subscription in the explorer view. Navigate to Storage Accounts > YourStorageAccountName > File Shares and you should see your share listed.

At the root of your file share, go ahead and create a “worlds” folder.

Then you’ll need to navigate to your local Valheim installation folder (e.g. C:\Users\<username>\AppData\LocalLow\IronGate\Valheim\worlds and drag your world files (e.g. MyWorld.db, MyWorld.db.old, MyWorld.fwl, MyWorld.fwl.old) into the storage explorer window to upload them. Give those time to finish uploading, and you should be all set to continue.

Deploying the YAML File

In Azure CLI, first navigate to the directory that you have the YAML file in. For me I saved it in C:\Deployment so I navigated there with cd c:\deployment.

Then do the following command:

az container create -g <YourResourceGroupName> -f <YourYamlFileName>

Your resource group name is the name of the resource group we created way back on step 1. Your yaml file name is whatever you named your yaml file (with the extension included). So for me it was valheim.yml

If everything is groovy, you should see a “Running…” message appear while Azure starts to deploy your resources. After not too long, if you go to your Resource group in the Azure Portal you should see your container instance appear.

After Deployment

To check that everything is working, let’s click into our container instance in the Azure Portal.

If your status shows “Running” then your container is already actively running. Over on the right-hand side is your IP Address, which is what you’ll use in-game to connect to the server.

On the left hand side if you click Containers, you can see your valheimserver container. If the State is not “Running,” and instead shows something like “Creating” — then you may need to wait a bit longer for it to spin up.

Under the Logs tab you will start to see the actual console output from your server once it’s started.

Note: If the “Restart count” column is greater than 0, then that means your container is having issues starting — likely because of a configuration issue with the YAML deployment. This can vary widely, so I recommend looking in the Events or Logs tabs for clues on what is going on, or running the az container show command to get details on any errors that the container might be encountering at startup.

If your container shows running and you’re seeing logs, then go ahead and startup Valheim and try connecting!

--

--