Intro

Cube 2: Sauerbraten is an old-school first-person shooter game that feels very similar to Quake and Unreal Tournament. While it’s easy to get the game up and running as a client/player, running a game server is non-trivial, thanks to the awful documentation. Truely, it is one of the worst documented systems I’ve had to work with, ever.

This blog post serves as my way of documenting for myself how I got this running, and hopefully will be helpful to the 13 other people in the world that still play this game. As I learn more about hosting Sauerbraten servers (and explore different modded server setups), I’ll update this blog post (and maybe tweet if I do, who knows. No promises).

System Requirements

Runing a Sauerbraten server takes minimal compute, which is fun. I did my testing in a Docker container on a Digital Ocean droplet that had 1 CPU and 1 GB of RAM, so just about any average potato can host a Sauerbraten server. In terms of network requirements, you’ll need to expose a pair of TCP and UDP ports (via firewall/port forwarding/etc.) if you want other people not on your network to play on the server, and/or if you want it in the master server list.

Downloading the Server Binaries

The server binaries are distributed as apart of the tarball that contains the client binaries/assets/etc. Unfortunately, the license for Sauerbraten does not allow redistributing partial archives, only the full archive or the source code, so you have to download the full ~1 GB archive to get the server binaries. Download the latest version from their official SourceForge project for your platform.

(you can also use a pre-made Docker environment, click here for details)

Configuring the Server

The server settings are stored in a file called server-init.cfg, which is located at the root of the Sauerbraten directory (from the tarball downloaded above).

root@7c93bc65eca8:/srv/sauerbraten# tree -L 1
.
|-- README.html
|-- bin_unix
|-- data
|-- docs
|-- packages
|-- sauerbraten_unix
|-- server-init.cfg
`-- src

You can view a reference copy of the config here.

To the Sauerbraten developers' credit, the config options in server-init.cfg have (fairly) good comments. Sometimes it’s not super obvious the impact that specific values will have, but the comments provide a good starting point to experiment from.

There are a few options you’ll probably need to set:

  • serverip and serverport to make sure the network settings are correct and it can be accessible. I have the serverip set to 0.0.0.0 so it binds to all interfaces (makes things easier in Docker), and the default 28785 for serverport.
  • publicserver controls how the server can be accessed and managed in-game.
    • A value of 0 allows for anyone to claim master on the server, and it shows as “open” in the server browser.
    • A value of 1 requires players to auth to claim master, and it shows as “auth” in the server browser
    • A value of 2 is the same as 0, but disables a master from setting the server as “Private” (details below).
    • You probably want 0 or 1, most likely 1.
  • serverdesc controls the description for the server, which is shown in the server browser. This is objectively the most important configuration option, make sure you pick a good one.
  • servermotd allows you to set a message that is shown to players when they connect to your server. This is probably the second most important option, have fun with it.

Server Authentication

There are different types of mastermode on a server:

  • Open: Any player can claim master on the server
  • Veto: Not sure what this does, I’ve never seen it on a server. Probably affects map voting or something.
  • Locked: Only players with the proper authentication can claim master, and people joining the server are put into spectate mode until a master puts them on a team
  • Private: Only players with the proper authentication can connect to the server.

When a server’s publicserver setting is 1, you have to authenticate to the server in order to claim master. Similarily, if the server is private, you have to authenticate in order to connect. Historically, this could be done using a pre-shared key/password, but that functionality appears to be broken in the current version (at least, I couldn’t figure out how to make it work).

The preferred mode of authentication is to use a challenge-response scheme that relies on public/private keypairs generated by the user. The only documentation I found for this was in the docs for Remod, a Sauerbraten server mod, so here is my documentation of how to do this in a bit more detail than Remod has it.

Client Setup

First, you have to generate a keypair. Open Sauerbraten, and press T to bring up the chat input. Type /genauthkey [password] (e.g., /genauthkey goodpass123) and press Enter, which will show a keypair in the log. Luckily, this gets logged on disk so you don’t need to manually transcribe those numbers.

Exit the game, and go to the $SB_DATA directory. This is a variable I have invented (you’re welcome), and this is it’s corresponding value on the different operating systems:

  • Windows: C:\Users\yourusernamehere\Documents\My Games\Sauerbraten
  • macOS: ~/Library/Application Support/Sauerbraten
  • Linux: ~/.sauerbraten (this may vary, I tested on Ubuntu 18.04)

In the $SB_DATA directory, there will be a log.txt file that has the game console output for the most recent execution. This file gets overwritten everytime you run the game, so be aware of that. Save the public and private keys that it shows for future use.

Next, create a file in the $SB_DATA directory called autoexec.cfg. Here, you will add your private key, along with a couple other pieces of information:

authkey "ingameusername" "123privatekey123" "authdomain.lan"
  • The ingameusername should match the username you set for yourself in Sauerbraten
  • The 123privatekey123 should be the long private key number from log.txt
  • The authdomain.lan should be a domain that you share with the server owner (probably yourself) that needs to be set in the server config. It doesn’t have to actually be a valid DNS record, but a username + domain combination needs to be unique (I think…)

This autoexec.cfg can also be edited in-game, if you click on “options..” in the main menu, and go to “cfg” on the far right.

Server Setup

There are a couple things that have to be set in the server’s server-init.cfg. First, set the serverauth variable to the same domain that is used on the client (e.g., “authdomain.lan”). Second, add a new line to the end of the file that looks like this:

adduser ingameusername authdomain.lan 123publickey123 3
  • The ingameusername should be your/the player’s username that they set in the client menu
  • The authdomain.lan should be the same value that the client has in their autoexec.cfg and the server has in the serverauth field
  • The 123publickey123 should be replaced with the long public key number from the client’s log.txt output
  • The 3 denotes the permissions associated with that user. 2 is for master (shown in green on the scoreboard), 3 is for admin (shown in purple).

Note that it may not be required for the adduser/authkey domain to be the same as the serverauth domain, but it is the easiest way to make sure there aren’t any issues.

Authenticating to the Server

When you connect to the server, you can do /auth authdomain.lan (replacing authdomain.lan with the proper domain), which should respond with a message about you successfully authenticating to the server, and your name should be in green or purple on the scoreboard now (depending on the permissions set for your user above)

Starting the Server

Manually

Go into the root Sauerbraten directory (it should have the server-init.cfg file), and run ./bin_unix/linux_64_server (or the corresponding path for other operating systems) to start the server.

Docker

To simplify things, I put together a Dockerfile and accompanying docker-compose.yml that makes it a bit easier to run the server. You can view it on Docker Hub and GitHub.

Create this docker-compose.yml and do docker-compose up to start the server (assuming you have your finished server-init.cfg in the current directory):

version: '3'

services:
  srv:
    image: captaingeech/cube2srv:latest
    ports:
      - "28785:28785/tcp"
      - "28785:28785/udp"
      - "28786:28786/tcp"
      - "28786:28786/udp"
    volumes:
      - ${PWD}/server-init.cfg:/srv/sauerbraten/server-init.cfg

Closing Thoughts

Overall, it’s pretty easy to run a Sauerbraten server once you figure out how, but my goodness the documentation is awful. Hopefully this helps, if I got anything wrong, get in touch with me and I will update this.