Installation and Configuration of an ARMA 3 Linux Dedicated Server

This guide is intended to show ARMA 3 server administrators how to get up and running with a fully functional ARMA 3 Dedicated Server. The installation described here was performed in Ubuntu 12.04; you may need to adapt slightly if you run a different Linux flavor. Hopefully by sharing the experience with the ARMA 3 community and consolidating the information into a single post, we’ll save a few fellow server admins some headaches down the road.

Overview

Our ultimate goal for server organization is to run several server instances using a single installation: public, private, and test instances. Each instance will have its own set of missions, mods, and configuration settings.

This is by no means a Linux tutorial, so some command line familiarity is assumed. We are also assuming you have full control over your entire server filesystem and are able to install new applications (otherwise, how’d you get the server there??). Some of the commands are also specific to our particular Linux flavor (Ubuntu 12.04) and the bash shell; you may need to adapt to your flavor as necessary. I also don’t do any detailed discussion of file permissions, but essentially, the user that will be running the server process(es) will need ownership of just about everything we make.

By the end of this post, your server installation will look something akin to:

whatever directory you want/
  steam/ — SteamCMD installation files
  arma3/
    install/ — Directory for the core installation files
    client/ — Theoretically, a Headless Client could go here, but there’s not one for Linux
    mods/ — Central location for all mods used across all instances
    public/ — Public server configuration, mostly symlinks back to install
    private/ — Private server configuration, mostly symlinks back to install
    test/ — Test server configuration, mostly symlinks back to … yea … install

We hope this helps!

Preparation

The first step is to choose where you want to install each of the tools we’ll be using. You’ll want to come up with an install path for each one. The table below summarizes the applications we’ll be using and how their installation paths will be referenced from now on:

  • SteamCMD: <STEAM_INSTALL>
  • ARMA 3 Server: <A3_INSTALL>

Wherever you see the above References in this document, replace that with your chosen path. Go ahead and create all of these directories now. I happen to like having all of the tools in the same place, but you can install them wherever you want. Just make it easy for yourself and any other admins you’ll be sharing with to remember.

You will also need a Steam account for installing and updating the server files. Be aware that using this account with SteamCMD will log that account out of any other sessions. We created and use a dedicated Steam account for Black Sh33p to prevent any disruptions to other accounts. This account does not need to own an ARMA 3 license to install the server.

Install Other Support Utilities

lib32gcc1 and lib32stdc++6

SteamCMD requires some 32-bit utilities to be installed. You will need to install them:

$ sudo apt-get install lib32gcc1
$ sudo apt-get install lib32stdc++6

If you have a 32-bit OS already, then you can:

  1. Skip this step
  2. Upgrade to a 64-bit OS
  3. Repeat this step and continue

UPDATE: As of server version 1.10, the Java dependency has been removed. Installing Java is no longer necessary for running the ARMA 3 Dedicated Server.

Install SteamCMD

With all prerequisites in place, we’re ready to get Steam installed. That’s as simple as:

$ cd <STEAM_INSTALL>
$ wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz
$ tar -xvzf steamcmd_linux.tar.gz
$ ./steamcmd.sh
…
Steam> login anonymous

This will update Steam to the latest version and voila; Steam is ready to roll. To exit the Steam shell:

Steam> quit

You can find a much more detailed guide to using SteamCMD here: https://developer.valvesoftware.com/wiki/SteamCMD

Install ARMA 3 Server

Before we even have the server installed, we know we want to make updating our server installation as painless as possible, so we’re going to write a script for that. As it turns out, the same script that updates the server will also install it, which is why we’re creating this first.

In your chosen <A3_INSTALL>, create a new executable file called a3update:

$ cd <A3_INSTALL>
$ touch a3update
$ chmod u+x a3update
$ vi a3update

Add the following contents to the file:

#!/bin/bash
<STEAM_INSTALL>/steamcmd.sh +runscript <ARMA_INSTALL>/a3update.txt

Save and exit the file. This script executes the SteamCMD program, telling it to follow the instructions you’ve placed in <ARMA_INSTALL>/a3update.txt. As you’ve probably guessed, we’ll create that file next:

$ vi a3update.txt

with the following content:

// Stop the script if any commands fail
@ShutdownOnFailedCommand 1
// Do not prompt for a password, use the one specified in the login command
@NoPromptForPassword 1
// Login to the given steam account
login <steam account> <steam password>
// Set the directory where A3 is/will be installed
force_install_dir <A3_INSTALL>/install
// Install or update the files for App ID 233780, the A3 server
app_update 233780 validate
// Exit the Steam shell
quit

Save and exit the file. Now, you’re ready to install the server:

$ ./a3update

Grab a beer or six, because this could take a while, but when it’s all done, you’ll have a brand new ARMA 3 Server installed at <A3_INSTALL>/install(or whatever path you specified to Steam for force_install_dir).

Create the First Instance

Congratulations, your server is installed! Unfortunately, it’s not quite fully baked. There are a few kinks to work out before we actually fire it up. First, though, we’ll create our instance structures. As I said, the Black Sh33p eventually want to have three instances running: a public server, a private server, and a test server. If you only plan on running a single instance, this will still work for you, but it will give you some redundant files. I suggest reading anyway to get a grasp of the logic, and then adapt it for your situation.

Let’s start to create that infrastructure now. I’ll put all the commands together first, then break them down into groups with the reasoning we’re following:

$ cd <A3_INSTALL>
$ mkdir public
$ cd public
$ mkdir keys
$ mkdir mpmissions
$ mkdir userconfig
$ mkdir mods
$ mkdir serverconfig
$ touch start.sh
$ chmod u+x start.sh
$ ln -s <A3_INSTALL>/arma3server arma3server
$ ln -s <A3_INSTALL>/addons addons
$ ln -s <A3_INSTALL>/battleye battleye
$ ln -s <A3_INSTALL>/dta dta
$ ln -s <A3_INSTALL>/curator curator
$ ln -s <A3_INSTALL>/kart kart
$ ln -s <A3_INSTALL>/heli heli
$ ln -s <A3_INSTALL>/mark mark
$ ln -s <A3_INSTALL>/libsteam_api.so libsteam_api.so
$ ln -s <A3_INSTALL>/libsteam.so libsteam.so
$ ln -s <A3_INSTALL>/libtier0_s.so libtier0_s.so
$ ln -s <A3_INSTALL>/libvstdlib_s.so libvstdlib_s.so
$ ln -s <A3_INSTALL>/steam_appid.txt steam_appid.txt
$ ln -s <A3_INSTALL>/steamclient.so steamclient.so
$ cd keys
$ ln -s <A3_INSTALL>/keys/a3.bikey a3.bikey

If you understood all that, then you’re better at this than me, and you can skip down to Test Vanilla Configuration.

UPDATE: There used to be symlinks here for some case-sensitivity issues in folder names (e.g. you needed to create MPMissions instead of mpmissions). These issues have since been resolved, so the symlinks are no longer necessary.

Here’s what each set of commands is doing and why:

$ cd <A3_INSTALL>
$ mkdir public
$ cd public
$ mkdir keys
$ mkdir mpmissions
$ mkdir userconfig
$ mkdir mods
$ mkdir serverconfig

This group of directories will house the configuration for our public server. As I said before, each instance will have its own set of Missions, Keys, Mods, and config files. That’s what these directories are for.

$ touch start.sh
$ chmod u+x start.sh

These two commands create a new executable file that we’ll use as a convenient script to start the server and modify startup parameters (we’ll describe that in detail later).

$ ln -s <A3_INSTALL>/arma3server arma3server
$ ln -s <A3_INSTALL>/addons addons
$ ln -s <A3_INSTALL>/battleye battleye
$ ln -s <A3_INSTALL>/dta dta
$ ln -s <A3_INSTALL>/libsteam_api.so libsteam_api.so
$ ln -s <A3_INSTALL>/libsteam.so libsteam.so
$ ln -s <A3_INSTALL>/libtier0_s.so libtier0_s.so
$ ln -s <A3_INSTALL>/libvstdlib_s.so libvstdlib_s.so
$ ln -s <A3_INSTALL>/steam_appid.txt steam_appid.txt
$ ln -s <A3_INSTALL>/steamclient.so steamclient.so

These commands essentially make a virtual copy of the server installation files by creating symbolic links to the actual installation. The files aren’t actually copied, so we save a lot of hard drive space.

$ ln -s <A3_INSTALL>/curator curator
$ ln -s <A3_INSTALL>/kart kart
$ ln -s <A3_INSTALL>/heli heli
$ ln -s <A3_INSTALL>/mark mark

These are symbolic links to the DLC content. Any future DLC will also need to be added like this.

$ cd keys
$ ln -s <A3_INSTALL>/keys/a3.bikey a3.bikey

This makes a symlink to the standard ARMA 3 key so that if you turn checkSignatures on for your sever (highly recommended), users can still join even if you’re only running vanilla.

Test the Vanilla Configuration

At this point, we’re ready to actually test the server with the vanilla configuration and missions:

$ cd <A3_INSTALL>
$ ./arma3server -world=empty

At this point, you should see a wall of text start to roll down the console. Once the text stops and you see a message about the version number of the server, it should be all ready to go. Launch your ARMA 3 client and connect. The server will have the same name as your server machine’s hostname. Join, select a mission, and have fun in your own server!

Create your own Configuration

As you (hopefully) have just seen, your server is up and running and ready to accept client connections and all your crazy missions; however, you probably want more than just the default settings. Next, we create our own set of server configuration files:

$ cd <A3_INSTALL>/public/serverconfig
$ touch server.cfg basic.cfg server.Arma3Profile server.Arma3Profile~

The config files can be named anything you want, just make sure that you map them to the correct parameter when we create the startup script. The ARMA server accepts three different config files, each with its own parameter and purpose:

  • server.cfg maps to -config (Reference: http://community.bistudio.com/wiki/server.cfg)
  • basic.cfg maps to -cfg (Reference:http://community.bistudio.com/wiki/basic.cfg)
  • server.Arma3Profile maps to -name (Reference: http://community.bistudio.com/wiki/server.armaprofile)

I will leave the specifics of setting each file’s content to you, but notice that initially we created a file named server.Arma3Profile~. This is intended as a backup of server.Arma3Profile. While it’s always good practice to keep backup copies of config files, this one is especially important. If you ever make modifications to the Profile configuration, and for any reason ARMA cannot read it correctly, it will overwrite your Profile settings with a blank file. If you’re wondering, then yes, I absolutely did learn this the hard way. So, any time you make changes to server.Arma3Profile, I highly recommend you back those changes up to server.Arma3Profile~:

$ cd <A3_INSTALL/public/serverconfig
$ cp server.Arma3Profile server.Arma3Profile~

At this point, we’ve created and tweaked all of the necessary configuration files. We just need to tell the server that we want it to use these files. This is where our handy start.sh we created will come in:

$ cd <A3_INSTALL>/public
$ vi start.sh

Add the following content to the file:

#!/bin/bash
# Wrapper file to start the A3 server
# Server installation path
serverConfigDir=”<a3_install>/public/serverconfig”
# Network settings used in -cfg param
networkConfig=”$serverConfigDir/basic.cfg”
# Server configuration settings used in -config param
serverConfig=”$serverConfigDir/server.cfg”
# Server profile and difficulty settings used in -name param
profileName=”public”
# Server-side mods
mods=””
# Start server
./arma3server -cfg=”$networkConfig” -config=”$serverConfig” -name=”$profileName” -mod=”$mods” -world=empty -port=2302 -noSound

Save and exit the file.

If you’ve run an ARMA server on Windows before, you may notice that the -profiles parameter is missing (if you haven’t, don’t worry about it). According to this article, -profiles has no effect in the Linux server. Instead, it simply expects that all Profiles exist in the same path: ~/.local/share/Arma 3 — Other Profiles/. You must create a .Arma3Profile file at this location with the same name that you’ve used for the -name parameter (in this case, public):

$ cd ~/.local/share/Arma\ 3\ -\ Other\ Profiles/public
$ ln -s <A3_INSTALL>/public/serverconfig/server.Arma3Profile public.Arma3Profile

My hope is that BI implements the -profiles parameter for Linux, as this path is pretty ugly. I have an open request to fix this here.

Notice that instead of making a file for the profile, we just make another symlink back to the appropriate file in our instance’s serverconfig folder. This keeps all of our server configuration files in a single place, not scattered about the hard drive. The symlink name uses the same -name we specified in start.sh.

Mod Installation

If you’re anything like us at Black Sh33p, then you freakin’ love mods. ARMA has by far and away one of the greatest communities in all of gaming, and Bohemia Interactive deserves all the credit in the world for being so open and supportive as to allow us to add and modify their game. So, how do we get those mods into our server setup? Well, if you recall, a long time ago we created a directory: <A3_INSTALL>/mods.

Upload any and all server-side mods you want to this folder. Use SSH, FTP, SCP — however you want to get them there is fine with me. Once they’re there, it’s a very simple matter to get them running on your server instance.

Let’s say you put @cba_a3 in there; here’s how you get that on your server :

$ cd <A3_INSTALL>/public/mods
$ ln -s <A3_INSTALL>/mods/@cba_a3 @cba_a3

More symlinks! This keeps all of the mod files in a single spot, so we only have to update them in one place when new versions are released.

The last step is to tell the server to load the mod in start.sh:

#!/bin/bash
# Wrapper file to start the A3 server
# Server installation path
serverConfigDir=”<A3_INSTALL>/public/serverconfig”
# Network settings used in -cfg param
networkConfig=”$serverConfigDir/basic.cfg”
# Server configuration settings used in -config param
serverConfig=”$serverConfigDir/server.cfg”
# Server profile and difficulty settings used in -name param
profileName=”public”
# Server-side mods
mods=”mods/@cba_a3"
# Start server
./arma3server -cfg=”/$networkConfig” -config=”$serverConfig” -name=”$profileName” -mod=”$mods” -world=empty -port=2302 -noSound

Notice that since we stored our symlink in our instance’s mods folder, we need to specify that relative path in the -mod parameter. For multiple mods, the mods variable becomes:

mods=”mods/@cba_a3;mods/@ffis;mods/@task_force_radio”

We installed the @a3mp mod on our server (as every good ARMA group should), and at the time, I received some errors in the log that led me to believe I needed to rename all files in the mod pack to all lowercase names. I did, and it works. See Concerns for more information.

Create Moar Instances

Since we don’t actually need full copies of the server installation or mods all over the place, creating new instances becomes extremely easy. If you’re not running multiple instances, you’re done!

The quickest way to make a new instance is to simply copy an existing one into a new folder. For example, I’ve already created my public instance, and now I want to spin up the private one:

$ cd <A3_INSTALL>
$ cp -dr public/* private/

The -d tells the cp command to make copies of the symlinks themselves instead of the content that they point to. All the necessary files are now ready to go in my private configuration folder, I just need to tweak the settings. For each instance, you’ll want to make the following tweaks:

  1. Modify start.sh with the appropriate paths, config files, and parameters
  2. Modify server.cfgbasic.cfg, and server.Arma3Profile with the new instance’s settings
  3. Create the appropriate folder and symlink in ~/.local/share/Arma 3 — Other Profiles/

Modify Port Configuration

The new instance must use different ports than any other running instances.

By default, the server instance uses port 2302. You must update these in start.sh by modifying the -port parameter.

My recommendation is to simply add 10 to each port number for each successive instance, like so:

  • Instance 1: -port 2302
  • Instance 2: -port 2312
  • and so on…

In the past, you needed to set steamport and steamqueryport in server.cfg; this is no longer necessary in ARMA 3. These will default to the game port +1 and +2, respectively.

Concerns

  • We have seen incredibly long load times on the server side to load any map, especially anything from the @a3mp pack (on the order of 5–10 minutes). It seems to be due in no small part to an excessive amount of logs that get generated due to thousands of “String BLAHBLAH_BLAH not found” messages. Once the server fully loads the mission on its side, everything works fine. Connecting players load the maps in a very reasonable amount of time; it’s just the server itself that seems to take forever to load the maps. If you’re not constantly switching maps/missions on the server, it shouldn’t be a big deal, but it’s definitely noticeable for us as we typically run several shorter missions back-to-back on different maps.
  • We’re seeing slightly lower server framerates than expected. An empty mission with just a single player caps out around 31 FPS according to #monitor. We’ll be continually tweaking our basic.cfg to see if that helps.
  • Placing any more than 30–40 AI brings the server to about 15 FPS. Perhaps this is normal, but it’s somewhat disappointing.

TL;DR?

Too bad; read it if you want to understand server setup.

Special Thanks (because I can)

  • The Black Sh33p — for your patience during the setup of all of this, and for being a kick-ass community
  • Bohemia Interactive — for making a kick-ass game
  • All of you — for reading this far. You kick-ass, too!