Running a Server

KF2 Dedicated Server in Docker on a VPS with Workshop Maps

This page follows an English Steam guide written as a set of "tips for future me" on running a Killing Floor 2 dedicated server inside Docker on a VPS, including custom Workshop maps. It builds on the community image dwurf/docker-kf2 and fills in the steps that the image documentation skips. For a plain SteamCMD install without containers, see KF2 Dedicated Server via SteamCMD.

Requirements

  • Comfort with Linux and Docker commands, and an idea of why Docker is preferable to a direct install.
  • A VPS with at least 30 GB of disk (more with custom maps), SSD storage (otherwise map changes are slow), 2 GB of RAM and a few CPU cores. Future KF2 updates will make the default server install larger.
  • An SSH client and an FTP client. The author uses MobaXterm, which combines both.

Set up the Docker image

  1. Pull the image: docker pull dwurf/docker-kf2
  2. On a RHEL host, allow IPv4 forwarding to containers: sysctl -w net.ipv4.ip_forward=1, then systemctl restart docker.
  3. Create the directories for server files: mkdir -p $HOME/{kf2,kf2_steamdir}
  4. Set the owner: sudo chown 1000 $HOME/{kf2,kf2_steamdir}. This fix came from a closed issue in the image's GitHub repository, so check closed issues when something fails.

Create the container

Build your own docker run command rather than relying on the quick example, because the variables you pass are what the server reloads after a restart. Example:

docker run -d -t --name kf2 -p 0.0.0.0:20560:20560/udp \
-p 0.0.0.0:27015:27015/udp \
-p 0.0.0.0:7777:7777/udp \
-p 0.0.0.0:8080:8080 \
-v $HOME/kf2:/home/steam/kf2server \
-v $HOME/kf2_steamdir:/home/steam/steam \
-e KF_SERVER_NAME=EnterServerNameHere \
-e KF_MOTD="Some Sort of Welcome Message" \
-e KF_DISABLE_TAKEOVER=true \
-e KF_ENABLE_WEB=true \
-e KF_ADMIN_PASS=ChangeMe \
-e KF_GAME_PASS=1234 \
-e KF_DIFFICULTY=1 \
-e KF_GAME_LENGTH=1 \
-e KF_GAME_MODE=Survival \
dwurf/docker-kf2:latest

The author strongly recommends enabling web access and an admin password for easy map and mode switching, and disabling takeover if you do not want the server used publicly when nobody is on it. The image has more variables, such as the starting map.

The first start downloads about 30 GB of server files. Use docker ps -a to find the container ID (it also lists stopped containers) and docker logs <ID> to watch the download.

Test with the default maps

Either join through the in-game server browser, or open http://<server-ip>:8080 and log in as admin with your admin password. The page can take a few minutes to appear. If you get an "invalid form data" error, wait a minute and reload because the server was not fully started yet.

WebAdmin tips

  • Ignore the image documentation's instruction to run an update command to change settings.
  • Settings changed in WebAdmin do not always survive a container restart. The docker run variables are the defaults WebAdmin shows.
  • In Change Map, pick the map and the game type (Survival, Endless), then put ?Difficulty=1?GameLength=0 into "Additional URL variables". Difficulty runs from normal up through hard, suicidal and Hell on Earth; game length is 4, 7 or 10 waves (the short, medium and long options).
  • Do not use General > Game to change these values. It only sometimes applies after a map load, whereas Change Map always works.
  • Map Cycles lets you see every map on the server, but the author prefers editing the config file (see below).
  • Under General > Administration, enable "Admin can pause". In game, open the console with the tilde key, run AdminLogin <password> and then pause.

Add custom Workshop maps

The image's game.yml approach for adding maps did not work for the author, so everything is done by hand. Stop the container before editing (docker stop, then docker start <ID>; plain stop and start worked better than restart).

Free space (optional)

If you only use custom maps, delete unused default map folders in /root/kf2/KFGame/BrewedPC/Maps/ to regain about 6 GB. Keep at least BioticsLab, which is the default start map after a restart. Do not delete the environment files in /root/kf2/KFGame/BrewedPC/Packages/Environment. Many Workshop maps use them, and without them players fall through the map in random places. If you later recreate the container, delete the kf2 and kf2_steamdir directories and start over to restore the default maps.

Find map names and Workshop IDs

On your own PC, open C:\Program Files (x86)\Steam\steamapps\workshop\content\232090 (232090 is the Steam app ID of KF2). Each numbered folder is a Workshop ID. Inside BrewedPC is the .kfm map file, and its file name is the real map name, which may differ from the Workshop title. Example: map KF-NachtDerUntoten_TraderPod, ID 1551913612.

LinuxServer-KFEngine.ini

At the bottom of /root/kf2/KFGame/Config/LinuxServer-KFEngine.ini add one line per map, with a comment so you know which ID is which:

[OnlineSubsystemSteamworks.KFWorkshopSteamworks]
ServerSubscribedWorkshopItems=1551913612 // KF-NachtDerUntoten_TraderPod

LinuxServer-KFGame.ini

Keep an unedited copy first. If you removed default maps, delete them from the GameMapCycles line and delete their [KF-<Map> KFMapSummary] sections. For each Workshop map add a section at the bottom:

[KF-NachtDerUntoten_TraderPod KFMapSummary]
MapName=KF-NachtDerUntoten_TraderPod
MapAssociation=1
ScreenshotPathName=UI_MapPreview_TEX.UI_MapPreview_Placeholder

After the next start the server may add or change fields in these sections, for example when the map author supplied a screenshot or game mode flags. That is normal.

Then edit GameMapCycles so it lists only your Workshop maps as one long line with no line breaks:

GameMapCycles=(Maps=("KF-Arid_Zedlands","KF-BikiniAtoll","KF-DeepingWall","KF-NachtDerUntoten_TraderPod"))

Start the container again and wait a few minutes. The server downloads the maps into /root/kf2/KFGame/Cache with the same structure as on a PC. Check that the maps show up in Change Map or Map Cycle in WebAdmin.

More KFGame.ini changes

Most of the docker run variables and WebAdmin settings end up in KFGame.ini, and editing it directly was the most reliable method for the author. The Welcome Screen settings live there too, as does the "admin can pause" option.

Closing thoughts

The author spent about two days on game.yml troubleshooting and manual map setup because good Docker server guides are scarce, and wrote this as a reference. For other server topics see KF2 dedicated server complete guide and Linux systemd user service.

FAQ

How much disk space does a Docker KF2 server need?
Plan for 30 GB or more without custom maps. Workshop maps add roughly 100-400 MB each. Deleting unused default maps can free about 6 GB once the server runs.
Which ports must be open for the Docker server?
UDP 20560 (Steam), UDP 27015 (query), UDP 7777 (game) and TCP 8080 for WebAdmin.
Where do I put Workshop map IDs?
In LinuxServer-KFEngine.ini under [OnlineSubsystemSteamworks.KFWorkshopSteamworks], one ServerSubscribedWorkshopItems line per map.
Why do WebAdmin changes disappear after a restart?
Settings changed in WebAdmin do not always persist when the container restarts. Editing LinuxServer-KFGame.ini directly was more reliable in this guide.