joedwards32/CS2 packages the Counter-Strike 2 dedicated server as a Docker image
CS2 Dedicated Server Docker Image
At a glance
- What is it?
- The joedwards32/CS2 image runs the Counter-Strike 2 dedicated server in a container with configuration through environment variables, published to Docker Hub and GitHub Container Registry. It needs 60GB of disk and 2GiB of RAM, it updates the game on every start, and the Steam Workshop support is described as experimental.
- Who is it for?
- Adopt the joedwards32/CS2 image if you want to run a Counter-Strike 2 dedicated server on a machine you control, since the environment variable surface covers server config, game modes, bots, SourceTV and logging without editing files inside the container. Do not adopt it if you need Steam Workshop maps in production, because the README marks that support as experimental, and expect the game files to be re-downloaded on every start.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 29 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the image actually contains
The repository is a Docker image for the Counter-Strike 2 dedicated server. The README's opening section explains what CS2 is, describing Counter-Strike as having offered an elite competitive experience for over two decades, and then says plainly that this Docker image contains the dedicated server of the game.
That is the whole product. There is no web panel, no plugin system, no match scheduling, and no source code for a server application, because the server is Valve's. What the project contributes is the packaging: the base image with the right runtime libraries, the steamcmd installation of the dedicated server, the entrypoint that applies configuration and starts the server, and the volume layout that keeps the game files in a known place.
The repository metadata describes it as a CS2 Dedicated Server Docker Image, with the primary language Shell and topics for counter-strike, counter-strike-2, cs2, cs2-server, dedicated-server and game. The homepage points at the Docker Hub repository at hub.docker.com/r/joedwards32/cs2.
Two container registries are published, which is worth knowing before you pin anything: Docker Hub at joedwards32/cs2, and GitHub Container Registry at ghcr.io/joedwards32/cs2. The README's badge row shows two separate workflows, one for the Docker image CI and one for build and publish, so the two registries are built by separate pipelines rather than one pushing to both.
The top level entries are few: a .github/ directory, .gitignore, LICENSE, README.md, an examples/ directory and a steamrt4/ directory. The steamrt4 directory is the Steam Runtime 4 layer the image builds on, and the examples directory holds a compose file, a compose file that adds a Lancache service, and a packaged server configuration.
The quick start, and the two things that will bite you
The README gives a simple server first, then the same server with persistence. The simple form is:
$ SRCDS_TOKEN="..." # check https://steamcommunity.com/dev/managegameservers
$ docker run -d --name=cs2 -e SRCDS_TOKEN="$SRCDS_TOKEN" -p 27015:27015/tcp -p 27015:27015/udp -p 27020:27020/udp joedwards32/cs2The token is the game server token from the Steam community manage game servers page, and it is passed as an environment variable rather than baked into the image.
The persistent form adds a bind mount and a chown:
$ mkdir -p $(pwd)/cs2-data
$ chown 1000:1000 $(pwd)/cs2-data # Makes sure the directory is writeable by the unprivileged container user with uid 1000, known as steam
$ SRCDS_TOKEN="..." # check https://steamcommunity.com/dev/managegameservers
$ docker run -d --name=cs2 -e SRCDS_TOKEN="$SRCDS_TOKEN" -v $(pwd)/cs2-data:/home/steam/cs2-dedicated/ -p 27015:27015/tcp -p 27015:27015/udp -p 27020:27020/udp joedwards32/cs2Two details in that are easy to get wrong. The container runs as an unprivileged user with uid 1000, known as steam, so a bind-mounted host directory has to be owned by that uid or the server cannot write to it. And the mount target is /home/steam/cs2-dedicated/, which is where the game files live, so the volume holds the game install rather than just the configuration.
The third thing to know before you start is on the next line of the README: you must have at least 60GB of free disk space. The system requirements list two CPUs, 2GiB of RAM, and 60GB of disk for the container or mounted as a persistent volume on /home/steam/cs2-dedicated/, with a note that more space may be required if you plan to install mods.
There is also a behavioural detail that changes how you operate it: the container will automatically update the game on startup, so if there is a game update just restart the container. The image does not pin a game build and wait for you to update deliberately.
For compose users the README points at the examples directory, and the command is docker compose --file examples/docker-compose.yml up -d cs2-server, with a reminder to update passwords and SRCDS_TOKEN in your compose file.
Configuration is a long environment variable list, and escaping matters
The configuration surface is entirely environment variables, set with -e (--env), and the README groups them by subject.
The server configuration block is the core one:
SRCDS_TOKEN="" (Game Server Token from https://steamcommunity.com/dev/managegameservers)
CS2_SERVERNAME="changeme" (Set the visible name for your private server.)
CS2_CHEATS=0 (0 - disable cheats, 1 - enable cheats)
CS2_SERVER_HIBERNATE=0 (Put server in a low CPU state when there are no players.
0 - hibernation disabled, 1 - hibernation enabled
n.b. hibernation has been observed to trigger server crashes)
CS2_SERVER_DELTATICKS_ENFORCE=2 (By default, player must ack delta ticks in order. How to enforce it: 2 = kick all clients, 1 = kick only TV clients, 0 = do not kick.)
CS2_IP="" (CS2 server listening IP address, 0.0.0.0 - all IP addresses on the local machine, empty - IP identified automatically)CS2_PORT=27015 (CS2 server listen port tcp_udp)
CS2_RCON_PORT="" (Optional, use a simple TCP proxy to have RCON listen on an alternative port.
Useful for services like AWS Fargate which do not support mixed protocol ports.)
CS2_LAN="0" (0 - LAN mode disabled, 1 - LAN Mode enabled)
CS2_RCONPW="changeme" (RCON password)
CS2_PW="" (Optional, CS2 server password)
CS2_MAXPLAYERS=10 (Max players)
CS2_ADDITIONAL_ARGS="" (Optional additional arguments to pass into cs2)
The hibernation note is worth flagging because it is a warning from the maintainer: hibernation has been observed to trigger server crashes. It is off by default, which is the right setting.
The RCON port comment gives a deployment reason rather than a technical one: mixed protocol ports are a problem for services like AWS Fargate, so RCON can be moved to a plain TCP port and reached through a simple TCP proxy. The README repeats this as a note, telling you to map the chosen port with the TCP protocol on docker run or add it to the compose file.
There is one escaping rule that catches people out, and it is stated before the configuration list: / characters in Counter-Strike-related environment variables must be escaped as \/, so CS2_SERVERNAME="My Server 1\/3" results in My Server 1/3 in game. Otherwise this may cause unexpected behavior during configuration processing.
The other groups cover game modes, bots, SourceTV and logs. Game modes use CS2_GAMEALIAS, or CS2_GAMETYPE and CS2_GAMEMODE when the alias is not defined, with CS2_MAPGROUP and CS2_STARTMAP. Bots use CS2_BOT_DIFFICULTY, CS2_BOT_QUOTA and CS2_BOT_QUOTA_MODE. SourceTV covers TV_ENABLE, TV_PORT, TV_AUTORECORD, the two passwords, TV_MAXRATE, TV_DELAY and TV_RELAYVOICE. Logging covers the CS2_LOG family plus CS2_DISCONNECT_KILLS and CS2_LOG_HTTP_URL, which sets a URI for a listener to receive logs via HTTP POST and must be wrapped in double quotes.
SourceTV and the workshop caveat
Two features deserve their own reading because they change what the container is for.
SourceTV, called CSTV in the variable names, is Valve's spectating and demo system, and the image exposes it fully. TV_ENABLE turns it on, TV_PORT sets the port to bind to at 27020, and TV_AUTORECORD can record all games as CSTV demos. There are two separate passwords, TV_PW for clients and TV_RELAY_PW for relay proxies, so a spectator audience and a relay network can be authorised independently.
There is also bandwidth and delay control. TV_MAXRATE sets the maximum CSTV spectator bandwidth rate allowed with 0 meaning unlimited, and TV_DELAY sets the broadcast delay in seconds, which is the setting a broadcaster uses to hide the outcome of a round from the audience. TV_RELAYVOICE controls whether voice chat data is relayed to CSTV spectators and recorded in demos.
The Steam Workshop section is the one with a caveat attached to the heading itself: support for Steam Workshop is experimental. The environment variable for it is CS2_HOST_WORKSHOP_MAP, and the README's variable list is cut off at that point in the documentation available here.
That caveat interacts with the map pool settings. CS2_MAPGROUP and CS2_STARTMAP are both documented as ignored if workshop maps are defined, so the two ways of choosing what a server plays are mutually exclusive, and the one that is called experimental takes precedence. Anyone who wants a fixed map rotation should not define a workshop map, and anyone who wants workshop content is relying on the experimental path.
This is also where the 60GB disk requirement starts to bite. The README notes that more space may be required if you plan to install mods, and workshop content is downloaded content on top of the base game install that already consumes 60GB.
Where this image is the wrong choice
The first limitation is the update behaviour combined with the size. The container updates the game on every startup, and the game is 60GB. On a host where the game install is on a persistent volume, a restart after a Valve release means downloading tens of gigabytes again, and if the update breaks something you are the one who finds out. There is no documented way to pin a game build.
The second limitation is the operational surface of Docker itself. A dedicated server that consumes 60GB and expects both TCP and UDP on the game port is not something you put on a platform with mixed protocol port support, which is exactly the limitation the RCON_PORT note describes. The workaround the README offers is a simple TCP proxy in front of RCON, and that is the sort of piece of infrastructure you now own.
The third limitation is that the image gives you a server and nothing to manage it with. There is no web panel, no query interface, no player moderation tooling and no match scheduling, so the operational side of running a community server is entirely on you, with the only remote control being RCON over a TCP port.
The alternative to weigh is the other way of running the same thing. The examples directory itself contains a compose file for adding a Lancache service, which is the standard approach for a dedicated server that serves the same game files to many clients: you host one copy of the game content on your own network and let the clients pull from it. The difference in approach is that a hosting provider runs the Steam content for you and hands you a ready machine with a control panel and a game server token already attached, which removes the download and the disk requirement entirely, at a monthly price.
That is the trade to weigh. The image is free, self-hosted and gives you the exact server Valve ships with nothing between you and it. A hosting provider gives you the same binary with the content distribution problem solved and a panel to manage it, at a cost that varies with the configuration you pick.
Release cadence, licence and the registry question
The maintenance record is current. The last push was on 2026-09-24 and the repository is not archived, and the release history shows v5.0.0 on 2026-09-20, v4.0.1 on 2026-03-19 and v4.0.0 on 2025-10-08. The v5 release is a major version, so the configuration surface or the image layout changed in a way that could break an existing deployment.
The licence is MIT, with a LICENSE file at the repository root. That is a permissive grant with no copyleft obligation, so you can fork the image and modify it without the obligation to publish your changes. That is a licensing note rather than legal advice, and it covers the packaging rather than the game content, which is Valve's.
Two practical points about shipping images come out of the repository layout. The workflows are split into a Docker image CI workflow and a separate Docker build and publish workflow, which is a common pattern to keep a pull request check separate from a push to a registry. And because two registries are published, the practical question for a deployment is which one you pin, since the same tag in two registries is not automatically the same content.
The examples directory is the best source for a configuration you can copy rather than write from scratch. It holds examples/cs2.cfg.tgz, a packaged server configuration, examples/docker-compose.yml for the basic server, and examples/docker-compose-lancache.yml which adds the caching service.
The last thing to note is the Steam Runtime 4 directory. Steam Runtime is Valve's container base for the dedicated server, and it exists because the server needs a specific userspace with the right libraries, and because running it as an unprivileged user inside a container is what Valve supports for the dedicated server. That is why uid 1000 matters when you bind mount, and it is the reason the chown step is in the quick start at all.
Editorial conclusion
Adopt the joedwards32/CS2 image if you want to run a Counter-Strike 2 dedicated server on a machine you control, since the environment variable surface covers server config, game modes, bots, SourceTV and logging without editing files inside the container. Do not adopt it if you need Steam Workshop maps in production, because the README marks that support as experimental, and expect the game files to be re-downloaded on every start. Verify first that you have 60GB of disk free and that the host allows both TCP and UDP on 27015, since the container needs both protocols published for the game port.
Frequently asked questions
How do I run a CS2 dedicated server with the joedwards32/CS2 image?
Set SRCDS_TOKEN from the Steam community manage game servers page and run the container with the game port published for both TCP and UDP and the SourceTV port for UDP, for example docker run -d --name=cs2 -e SRCDS_TOKEN="$SRCDS_TOKEN" -p 27015:27015/tcp -p 27015:27015/udp -p 27020:27020/udp joedwards32/cs2. The image is also published at ghcr.io/joedwards32/cs2.
What are the system requirements for the CS2 Docker image?
The README lists a minimum of 2 CPUs, 2GiB of RAM, and 60GB of disk space for the container or mounted as a persistent volume on /home/steam/cs2-dedicated/. It warns that more space may be required if you plan to install mods.
How do I keep the CS2 game files when the container is recreated?
Bind mount a host directory to /home/steam/cs2-dedicated/ with -v, and chown it to 1000:1000 first, because the container runs as the unprivileged user with uid 1000, known as steam, and needs to be able to write to that directory.
How is the CS2 server configured in this image?
Through environment variables passed with -e, grouped into server configuration, game modes, bots, SourceTV and logging. Note that / characters in Counter-Strike-related variables must be escaped as \/, so a name like My Server 1\/3 appears in game as My Server 1/3, otherwise configuration processing may behave unexpectedly.
Is Steam Workshop support available in the CS2 Docker image?
The README states that support for Steam Workshop is experimental, and the relevant variable is CS2_HOST_WORKSHOP_MAP. The map pool and start map settings CS2_MAPGROUP and CS2_STARTMAP are ignored if workshop maps are defined.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/joedwards32-cs2)Was this useful?