Skip to content

Host Steam dedicated servers using Docker hosts or Kubernetes

License

Notifications You must be signed in to change notification settings

thetestgame/docker-steam-server

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

steam® Steam (SteamCMD)

This is NOT an official Valve steam docker container.

Build Steam Docker Image and Deploy

Generic Steam dedicated server using Docker.

This provides a core installation of steamcmd to host dedicated servers. Both linux and windows servers (via wine) can be hosted using this image.

How it Runs

The docker image contains a base ubuntu install with wine (windows support) and an up to date steamcmd utility installed.

After launching the container:

  1. Permisssions are propagated for user steam.

  2. OS is updated (if enabled).

  3. steamcmd is updated (if enabled).

  4. specific steam dedicated server is updated (if enabled).

  5. Execution passed to /data/custom_server as root.

    • You must create this script in your /data directory and set it executable.
    • See custom server for documentation.

Example Configurations

Fully working examples of different dedicated servers.

Version Tags

Tag Description
stable Ubuntu 24.10: wine, steamcmd (package).
latest Ubuntu 24.10: winehq STABLE packages, steamcmd (package). This WILL break.
experimental Ubuntu 24.10: winehq STAGING packages, steamcmd (package). This WILL break.
  • Containers are automatically rebuilt weekly.

Parameters

Parameter Function Default
SERVER_DIR Location for server files. /data/server
STEAM Location of steamcmd client. /steam
PLATFORM Platform to force specify when auto updating. linux or windows. windows
STEAM_APP_ID Steam application ID for auto updating. 0
STEAM_APP_EXTRAS Optional. Additional options and values for steam app update, e.g setting BETA versions. ``
UPDATE_OS Update core OS on startup. 1 enable, 0 disable. 1
UPDATE_STEAM Update steamcmd on startup. 1 enable, 0 disable. 1
UPDATE_SERVER Update dedicated server specified by STEAM_APP_ID on startup. 1 enable, 0 disable. 1
PUID User ID to run steamcmd under as well as mount permissions. 1000
PGID Group ID to run steamcmd under as well as mount permissions. 1000
LANG Language environment to use in containers. en_US.UTF-8
LANGUAGE Language environment to use in containers. en_US:UTF-8
LC_ALL Language environment to use in containers. en_US.UTF-8

Ports

Default ports exposed by the container. Additional ports for servers can be exposed during docker configuration.

See Required Ports for Steam for a detailed list of steam ports.

Port Protocol Required? Description
27015 UDP Mandatory Gameplay traffic.
27015 TCP Optional SRCDS RCON port.
27016 UDP Optional Steam announce traffic.

Volumes

Volume Function
/data User data location for images.

User/Group IDs

When using data volumes (-v flags), permissions issues can occur between the host and the container. For example, the user within the container may not exists on the host. This could prevent the host from properly accessing files and folders on the shared volume.

To avoid any problem, you can specify the user the application should run as.

This is done by passing the user ID and group ID to the container via the PUID and PGID environment variables.

To find the right IDs to use, issue the following command on the host, with the user owning the data volume on the host:

id <username>

Which gives an output like this one:

uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),4(adm),24(cdrom),27(sudo),46(plugdev),113(lpadmin)

The value of uid (user ID) and gid (group ID) are the ones that you should be given the container.

Detailed Usage Instructions

Details how to setup a new server from scratch. See Example Configurations for working examples.

docker-compose (windows dedicated server)

---
version: "3"
services:
  steam:
    image: thetestgame/steam:stable
    restart: unless-stopped
    ports:
      - 27015:27015
      - 27015:27015/udp
      - 27016:27016/udp
    environment:
      - PUID=1000
      - PGID=1000
      - UPDATE_OS=1
      - UPDATE_STEAM=1
      - UPDATE_SERVER=1
      - PLATFORM=windows
      - STEAM_APP_ID=443030
      - TZ=America/Los_Angeles
    volumes:
      - /my/docker/server/data:/data
      - /etc/localtime:/etc/localtime:ro

docker-compose (linux dedicated server)

---
version: "3"
services:
  steam:
    image: thetestgame/steam:stable
    restart: unless-stopped
    ports:
      - 27015:27015
      - 27015:27015/udp
      - 27016:27016/udp
    environment:
      - PUID=1000
      - PGID=1000
      - UPDATE_OS=1
      - UPDATE_STEAM=1
      - UPDATE_SERVER=1
      - PLATFORM=linux
      - STEAM_APP_ID=294420
      - TZ=America/Los_Angeles
    volumes:
      - /my/docker/server/data:/data
      - /etc/localtime:/etc/localtime:ro

Custom Server

/data/custom_server is the script that will be called when the docker container is launched. This is under your control to allow you to setup the server however you wish. You must create this script and it must be executable.

supervisord has been provided for service convenience.

Dedicated server files are installed automatically to ${SERVER_DIR}, and all docker environment variables are avaliable for use.

Do any pre-launch configuration here (e.g. update or install mods, backups, etc.). Any files created will belong to root so ensure that permissions are changed.

Remember to drop privileges before launching server, this will ensure minimum exposure if there are vulnerabilities in the game, as well as prevent any permissions issues with server files.

su - steam -c 'your server launch command'

Your specific launch command will vary based on what server you install. Check dedicated server documentation for that game.

Linux Example

This will launch a Left 4 Dead srcsd_run linux dedicated server.

su - steam -c "/data/server/srcds_run -console -game left4dead -map l4d_hospital01_apartment -port 27015 +maxplayers 4 -nohltv +exec server.cfg"
  • this example would launch a Left 4 Dead dedicated server (222840).

Windows Example

All flavors of wine are installed (wind, wine32 and wine64). Check specific dedicated server documentation and forums for launching a dedicated windows server under wine for your game.

su - steam -c "xvfb-run --auto-servernum \
  wine64 ${SERVER_DIR}/ConanSandbox/Binaries/Win64/ConanSandboxServer-Win64-Test.exe -nosteamclient -game -server -log"
  • This example lauches a conan exiles dedicated server (443030).

It is important to note that we must bring up a lightweight window manager to launch these servers. This is what xvfb-run --auto-servernum does.

Dedicated Server with NO Saves / Saved States

For servers that don't require saving of state between reboots, a simple bash script will handle the server just fine:

Windows

# This will run wine (for windows servers) and launch the server.
su - steam -c "xvfb-run --auto-servernum \
  wine64 ${SERVER_DIR}/ConanSandbox/Binaries/Win64/ConanSandboxServer-Win64-Test.exe -nosteamclient -game -server -log"

Linux

# launch the dedicated linux server under the steam user.
su - steam -c "/data/server/startserver.sh \
  -configfile=/data/server/serverconfig.xml"

Dedicated Server requiring Saves / Saved States (Bash)

If the dedicated server requires specific saving of state on shutdown, bash can be used to manage the shutdown process. This works for simplier dedicated servers. More complex servers should consider the included supervisord process manager.

Ensure that the docker container is given more than 10 seconds for shutdown if needed:

services:
  steam:
    image: thetestgame/steam:latest
    restart: unless-stopped
    stop_grace_period: 1m
    ...

/data/custom_server:

#!/bin/bash
#
# Runs as Root. Drop privileges.
#
# Capture kill/term signals and send SIGINT to gracefully shutdown conan
# server.
PROCESS_WAIT_TIME=25
WATCHDOG_TIME=300

function shutdown() {
  echo 'Shutting down server ...'
  if [ "$(pgrep -n Conan)" != '' ]; then
    echo "Sending SIGINT to Conan server (max ${PROCESS_WAIT_TIME} secs) ..."
    kill -SIGINT `pgrep -n Conan`
    sleep ${PROCESS_WAIT_TIME}
  fi
  if [ "$(pgrep wine)" != '' ]; then
    echo "Sending SIGINT to wine processes (max ${PROCESS_WAIT_TIME} sec) ..."
    kill -SIGINT `pgrep wine`
    sleep ${PROCESS_WAIT_TIME}
  fi
  exit 0
}
trap shutdown SIGINT SIGKILL SIGTERM

function start_server() {
  su - steam -c "xvfb-run --auto-servernum wine64 ${SERVER_DIR}/ConanSandbox/Binaries/Win64/ConanSandboxServer-Win64-Test.exe -nosteamclient -game -server -log"
}

function watch_server() {
  if ps aux | grep [C]onanSandboxServer > /dev/null; then
    echo 'Server is running ...'
  else
    echo 'Starting server ...'
    start_server &
  fi
}

while true; do
  watch_server
  # Using background with wait enables signal trap capture.
  sleep ${WATCHDOG_TIME} &
  wait
done

Dedicated Server requiring Saves / Saved States (Supervisord)

supervisor has been provided for service convenience. If you want to manage you server with a process manager just set /data/custom_server to:

/usr/bin/supervisord -c /etc/supervisor/supervisord.conf

Then place all of your supervisord configuration files in /data/supervisord and ensure that the correct permissions are set. Supervisord will launch as root, and you should execute your server with user=steam to drop privileges for your processes.

A good supervisord example using a Conan Exiles server is located here.

Ensure that the docker container is given more than 10 seconds for shutdown if needed:

services:
  steam:
    image: thetestgame/steam:latest
    restart: unless-stopped
    stop_grace_period: 1m
    ...

Winetricks

winetricks is installed to /usr/bin/winetricks and may be used in custom_server to apply specific patches; remember to switch to the steam user when executing this commands.

custom_server

su - steam -c "winetricks dotnet472"
su - steam -c "winetricks vcrun2013"

Building

Both debian-slim and ubuntu images build within about 2-3MB of each other, so only the ubuntu base is used. build using included makefile:

Main steam image with ubuntu wine repository:

sudo make steam

Steam image using winehq repository:

sudo make latest

Troubleshooting

Failed to determine free disk space for ... error 75

This happens when steamcmd is downloading an app because the underlying data store cannot be queried for a quota. Common with ZFS backed data stores. Either set an explicit qouta or ignore it.

sudo zfs set quota=2T zpool1/docker

Windows (wine) takes ~5 minutes to launch on first boot

Wine may block on boot events during the first boot. This is expressed by an approximate 5 minute pause during these messages:

"0014:err:ole:get_local_server_stream Failed: 80004002"

_"_wine_kernel_init boot event wait timed out"

Subsequent boots will not see the delay. This should be mitigated in the container build already, but can manually be run with:

wineboot --update
xvfb-run --autoservernum wineboot --update

This is a suspected issue with the GCC build toolchain, but has not been resolved yet. See:

'cat: hlds.{PID}.pid: No such file or directory'

This happens when srcds_run cannot write a PID to the autogenerated PID file.

Manually specify a PID file to use in the container that the steam user has access to.

srcds_run ... -pidfile /data/server/{GAME}.pid

Could not find steamclient.so or [S_API FAIL] SteamAPI_Init() ... or a local steamclient.dll.

The Steam Linux shared library could not be found in your path.

Be sure to use su - steam -c to load the full steam user profile.

Link to the local steamclient.so file, or copy it to where your server binary is executed. The default location is in the steam user directory:

/steam/.steam/steamcmd/linux{32,64}/steamclient.so

ln -s -f /steam/.steam/steamcmd/linux32/steamclient.so /steam/.steam/sdk32/steamclient.so

Licensing

Steam Logo, SteamCMD ©2019 Valve Corporation. Steam and the Steam logo are trademarks and/or registered trademarks of Valve Corporation in the U.S. and/or other countries.

Packages

No packages published

Languages

  • Makefile 72.0%
  • Shell 28.0%