Compare commits

...

No commits in common. "032fd2aa2d744a71bffa62eaa2cb8833562c8550" and "4cfa6d653be7aaf2ed5bca6ef45c4761f121472f" have entirely different histories.

16 changed files with 516 additions and 165 deletions

19
.github/workflows/docker-image.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Docker Image CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
working-directory: ./bookworm
run: docker build . --file Dockerfile --tag joedwards32/cs2:latest

69
.github/workflows/docker-publish.yml vendored Normal file
View file

@ -0,0 +1,69 @@
name: Docker Build and Publish
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: '21 5 * * 0'
push:
branches: [ "main" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: docker.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v4
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log in to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=semver,pattern={{version}}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: ./bookworm
file: ./bookworm/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

105
README.md
View file

@ -50,18 +50,25 @@ STEAMGUARD="" (Optional, Steam Guard key if enabled. Use your most
### Server Configuration
```dockerfile
SRCDS_TOKEN="" (Game Server Token from https://steamcommunity.com/dev/managegameservers)
CS2_SERVERNAME="changeme" (Set the visible name for your private server)
CS2_IP=0.0.0.0 (CS2 server listening IP address, 0.0.0.0 - all IP addresses on the local machine, empty - IP identified automatically)
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_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="changeme" (CS2 server password)
CS2_PW="changeme" (Optional, CS2 server password)
CS2_MAXPLAYERS=10 (Max players)
CS2_ADDITIONAL_ARGS="" (Optional additional arguments to pass into cs2)
```
**Note:** When using `CS2_RCON_PORT` don't forget to map the port chosen with TCP protocol (e.g., add `-p 27050:27050/tcp` on the `docker run` command or add the port to the `docker-compose.yml` file).
### Game Modes
```dockerfile
@ -69,8 +76,8 @@ CS2_GAMEALIAS="" (Game type, e.g. casual, competitive, deathmatch.
See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
CS2_GAMETYPE=0 (Used if CS2_GAMEALIAS not defined. See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
CS2_GAMEMODE=1 (Used if CS2_GAMEALIAS not defined. See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
CS2_MAPGROUP="mg_active" (Map pool)
CS2_STARTMAP="de_inferno" (Start map)
CS2_MAPGROUP="mg_active" (Map pool. Ignored if workshop maps are defined.)
CS2_STARTMAP="de_inferno" (Start map. Ignored if workshop maps are defined.)
```
### Bots
@ -81,6 +88,96 @@ CS2_BOT_QUOTA="" (Number of bots)
CS2_BOT_QUOTA_MODE="" (fill, competitive)
```
### CSTV/SourceTV
```dockerfile
TV_ENABLE=0 (0 - disable, 1 - enable)
TV_PORT=27020 (SourceTV/CSTV port to bind to)
TV_AUTORECORD=0 (Automatically record all games as CSTV demos: 0=off, 1=on)
TV_PW="changeme" (CSTV password for clients)
TV_RELAY_PW="changeme" (CSTV password for relay proxies)
TV_MAXRATE=0 (Max CSTV spectator bandwidth rate allowed, 0 == unlimited)
TV_DELAY=0 (CSTV broadcast delay in seconds)
```
### Logs
```dockerfile
CS2_LOG="on" ('on'/'off')
CS2_LOG_MONEY=0 (Turns money logging on/off: 0=off, 1=on)
CS2_LOG_DETAIL=0 (Combat damage logging: 0=disabled, 1=enemy, 2=friendly, 3=all)
CS2_LOG_ITEMS=0 (Turns item logging on/off: 0=off, 1=on)
```
### Steam Workshop
Support for Steam Workshop is experimental!
```dockerfile
CS2_HOST_WORKSHOP_MAP="" (Steam Workshop Map ID to load on server start)
CS2_HOST_WORKSHOP_COLLECTION="" (Steam Workshop Collection ID to download)
```
If a Workshop Collection is set, maps can be selected via rcon. E.g:
```
ds_workshop_listmaps
ds_workshop_changelevel $map_name
```
# Customizing this Container
## Debug Logging
If you want to increase the verbosity of log output set the `DEBUG` environment variable:
```dockerfile
DEBUG=0 (0=none, 1=steamcmd, 2=cs2, 3=all)
```
## Validating Game Files
If you break the game through your customisations and want steamcmd to validate and redownload then set the `STEAMAPPVALIDATE` environment variable to `1`:
```dockerfile
STEAMAPPVALIDATE=0 (0=skip validation, 1=validate game files)
```
## Pre and Post Hooks
The container includes two scripts for executing custom actions:
* `/home/steam/cs2-dedicated/pre.sh` is executed before the CS2 server starts
* `/home/steam/cs2-dedicated/post.sh` is executed after the CS2 server stops
When using a persient volume mounted at `/home/steam/cs2-dedicated/` you may edit these scripts to perform custom actions, such as enabling metamod.
Alternatively, you may have docker mount files from outside the container to override these files. E.g.:
```
-v /path/to/pre.sh:/home/steam/cs2-dedicated/pre.sh
```
## Overriding Game Mode Defaults
The default configurations for each game mode are stored in `/home/steam/cs2-dedicated/game/csgo/cfg/`. For example, the Competitive mode defaults are set by `gamemode_competitive.cfg`.
When using a persistent volume mounted at `/home/steam/cs2-dedicated/`, these defaults can be overridden by adding your own settings to `gamemode_competitive_server.cfg`.
```
// Game Mode Competitive Server Overrides
mp_maxrounds 16 // Shorter games
```
## Customisation Bundle
The container can be instructed to download a extract a Tar Gzip bundle, Tar or Zip archive of configuration files and other customisations from a given URL.
```dockerfile
CS2_CFG_URL="" (HTTP/HTTPS URL to fetch a Tar Gzip bundle, Tar or Zip archive of configuration files/mods)
```
# Credits
This container leans heavily on the work of [CM2Walki](https://github.com/CM2Walki/), especially his [SteamCMD](https://github.com/CM2Walki/steamcmd) container image. GG!

View file

@ -4,7 +4,7 @@
# BUILD STAGE
FROM cm2network/steamcmd:root as build_stage
FROM cm2network/steamcmd:root-bookworm as build_stage
LABEL maintainer="astra@zio.sh"
@ -20,39 +20,39 @@ COPY etc/post.sh "/etc/post.sh"
RUN set -x \
# Install, update & upgrade packages
&& dpkg --add-architecture i386 \
&& dpkg --add-architecture i386 \
&& apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
libcurl4:i386 \
libcurl4:i386 \
wget \
ca-certificates \
lib32z1 \
simpleproxy \
libicu-dev \
unzip \
patch \
simpleproxy \
libicu-dev \
unzip \
jq \
patch \
&& mkdir -p "${STEAMAPPDIR}" \
# Add entry script
&& chmod +x "${HOMEDIR}/entry.sh" \
&& chown -R "${USER}:${USER}" "${HOMEDIR}/entry.sh" "${STEAMAPPDIR}" \
&& chmod +x /etc/post.sh /etc/pre.sh \
&& chmod +x /etc/post.sh /etc/pre.sh \
# Clean up
&& apt-get clean \
&& find /var/lib/apt/lists/ -type f -delete
&& apt-get clean \
&& find /var/lib/apt/lists/ -type f -delete
# BASE
FROM build_stage AS bullseye-base
FROM build_stage AS bookworm-base
ENV CS2_SERVERNAME="cs2 private server" \
CS2_CHEATS=0 \
CS2_IP=0.0.0.0 \
CS2_PORT=27015 \
CS2_SERVER_HIBERNATE=0 \
CS2_PORT=27015 \
CS2_RCON_PORT="" \
CS2_MAXPLAYERS=10 \
CS2_CHEATS=0 \
CS2_RCONPW="changeme" \
CS2_PW="changeme" \
CS2_MAPGROUP="mg_active" \
CS2_STARTMAP="de_inferno" \
CS2_GAMEALIAS="" \
@ -61,12 +61,17 @@ ENV CS2_SERVERNAME="cs2 private server" \
CS2_LAN=0 \
TV_AUTORECORD=0 \
TV_ENABLE=0 \
TV_PW="changeme" \
TV_PORT=27020 \
TV_PW="changeme" \
TV_RELAY_PW="changeme" \
TV_MAXRATE=0 \
TV_DELAY=0 \
SRCDS_TOKEN="" \
CS2_CFG_URL="" \
CS2_LOG="on" \
CS2_LOG_MONEY=0 \
CS2_LOG_DETAIL=0 \
CS2_LOG_ITEMS=0 \
CS2_ADDITIONAL_ARGS=""
# Set permissions on STEAMAPPDIR

202
bookworm/etc/entry.sh Normal file
View file

@ -0,0 +1,202 @@
#!/bin/bash
# Debug
## Steamcmd debugging
if [[ $DEBUG -eq 1 ]] || [[ $DEBUG -eq 3 ]]; then
STEAMCMD_SPEW="+set_spew_level 4 4"
fi
## CS2 server debugging
if [[ $DEBUG -eq 2 ]] || [[ $DEBUG -eq 3 ]]; then
CS2_LOG="on"
CS2_LOG_MONEY=1
CS2_LOG_DETAIL=3
CS2_LOG_ITEMS=1
fi
# Create App Dir
mkdir -p "${STEAMAPPDIR}" || true
# Download Updates
if [[ "$STEAMAPPVALIDATE" -eq 1 ]]; then
VALIDATE="validate"
else
VALIDATE=""
fi
## SteamCMD can fail to download
## Retry logic
MAX_ATTEMPTS=3
attempt=0
while [[ $steamcmd_rc != 0 ]] && [[ $attempt -lt $MAX_ATTEMPTS ]]; do
((attempt+=1))
if [[ $attempt -gt 1 ]]; then
echo "Retrying SteamCMD, attempt ${attempt}"
# Stale appmanifest data can lead for HTTP 401 errors when requesting old
# files from SteamPipe CDN
echo "Removing steamapps (appmanifest data)..."
rm -rf "${STEAMAPPDIR}/steamapps"
fi
eval bash "${STEAMCMDDIR}/steamcmd.sh" "${STEAMCMD_SPEW}"\
+force_install_dir "${STEAMAPPDIR}" \
+@bClientTryRequestManifestWithoutCode 1 \
+login anonymous \
+app_update "${STEAMAPPID}" "${VALIDATE}"\
+quit
steamcmd_rc=$?
done
## Exit if steamcmd fails
if [[ $steamcmd_rc != 0 ]]; then
exit $steamcmd_rc
fi
# steamclient.so fix
mkdir -p ~/.steam/sdk64
ln -sfT ${STEAMCMDDIR}/linux64/steamclient.so ~/.steam/sdk64/steamclient.so
# Install server.cfg
mkdir -p $STEAMAPPDIR/game/csgo/cfg
cp /etc/server.cfg "${STEAMAPPDIR}"/game/csgo/cfg/server.cfg
# Install hooks if they don't already exist
if [[ ! -f "${STEAMAPPDIR}/pre.sh" ]] ; then
cp /etc/pre.sh "${STEAMAPPDIR}/pre.sh"
fi
if [[ ! -f "${STEAMAPPDIR}/post.sh" ]] ; then
cp /etc/post.sh "${STEAMAPPDIR}/post.sh"
fi
# Download and extract custom config bundle
if [[ ! -z $CS2_CFG_URL ]]; then
echo "Downloading config pack from ${CS2_CFG_URL}"
TEMP_DIR=$(mktemp -d)
TEMP_FILE="${TEMP_DIR}/$(basename ${CS2_CFG_URL})"
wget -qO "${TEMP_FILE}" "${CS2_CFG_URL}"
case "${TEMP_FILE}" in
*.zip)
echo "Extracting ZIP file..."
unzip -q "${TEMP_FILE}" -d "${STEAMAPPDIR}"
;;
*.tar.gz | *.tgz)
echo "Extracting TAR.GZ or TGZ file..."
tar xvzf "${TEMP_FILE}" -C "${STEAMAPPDIR}"
;;
*.tar)
echo "Extracting TAR file..."
tar xvf "${TEMP_FILE}" -C "${STEAMAPPDIR}"
;;
*)
echo "Unsupported file type"
rm -rf "${TEMP_DIR}"
exit 1
;;
esac
rm -rf "${TEMP_DIR}"
fi
# Rewrite Config Files
sed -r -i -e "s/^(hostname) .*/\1 ${CS2_SERVERNAME}/g" \
-e "s/^(sv_cheats) .*/\1 ${CS2_CHEATS}/g" \
-e "s/^(sv_hibernate_when_empty) .*/\1 ${CS2_SERVER_HIBERNATE}/g" \
-e "s/^(sv_password) .*/\1 ${CS2_PW}/g" \
-e "s/^(rcon_password) .*/\1 ${CS2_RCONPW}/g" \
-e "s/^(tv_enable) .*/\1 ${TV_ENABLE}/g" \
-e "s/^(tv_port) .*/\1 ${TV_PORT}/g" \
-e "s/^(tv_autorecord) .*/\1 ${TV_AUTORECORD}/g" \
-e "s/^(tv_password) .*/\1 ${TV_PW}/g" \
-e "s/^(tv_relaypassword) .*/\1 ${TV_RELAY_PW}/g" \
-e "s/^(tv_maxrate) .*/\1 ${TV_MAXRATE}/g" \
-e "s/^(tv_delay) .*/\1 ${TV_DELAY}/g" \
-e "s/^(tv_name) .*/\1 ${CS2_SERVERNAME} CSTV/g" \
-e "s/^(tv_title) .*/\1${CS2_SERVERNAME} CSTV/g" \
"${STEAMAPPDIR}"/game/csgo/cfg/server.cfg
if [[ ! -z $CS2_BOT_DIFFICULTY ]] ; then
sed -r -i "s/^(bot_difficulty) .*/\1 ${CS2_BOT_DIFFICULTY}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
if [[ ! -z $CS2_BOT_QUOTA ]] ; then
sed -r -i "s/^(bot_quota) .*/\1 ${CS2_BOT_QUOTA}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
if [[ ! -z $CS2_BOT_QUOTA_MODE ]] ; then
sed -r -i "s/^(bot_quota_mode) .*/\1 ${CS2_BOT_QUOTA_MODE}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
# Switch to server directory
cd "${STEAMAPPDIR}/game/bin/linuxsteamrt64"
# Pre Hook
source "${STEAMAPPDIR}/pre.sh"
# Construct server arguments
if [[ -z $CS2_GAMEALIAS ]]; then
# If CS2_GAMEALIAS is undefined then default to CS2_GAMETYPE and CS2_GAMEMODE
CS2_GAME_MODE_ARGS="+game_type ${CS2_GAMETYPE} +game_mode ${CS2_GAMEMODE}"
else
# Else, use alias to determine game mode
CS2_GAME_MODE_ARGS="+game_alias ${CS2_GAMEALIAS}"
fi
if [[ -z $CS2_IP ]]; then
CS2_IP_ARGS=""
else
CS2_IP_ARGS="-ip ${CS2_IP}"
fi
if [[ ! -z $SRCDS_TOKEN ]]; then
SV_SETSTEAMACCOUNT_ARGS="+sv_setsteamaccount ${SRCDS_TOKEN}"
fi
if [[ ! -z $CS2_HOST_WORKSHOP_COLLECTION ]] || [[ ! -z $CS2_HOST_WORKSHOP_MAP ]]; then
CS2_MP_MATCH_END_CHANGELEVEL="+mp_match_end_changelevel true" # https://github.com/joedwards32/CS2/issues/57#issuecomment-2245595368
CS2_STARTMAP="\<empty\>" # https://github.com/joedwards32/CS2/issues/57#issuecomment-2245595368
CS2_MAPGROUP_ARGS=
else
CS2_MAPGROUP_ARGS="+mapgroup ${CS2_MAPGROUP}"
fi
if [[ ! -z $CS2_HOST_WORKSHOP_COLLECTION ]]; then
CS2_HOST_WORKSHOP_COLLECTION_ARGS="+host_workshop_collection ${CS2_HOST_WORKSHOP_COLLECTION}"
fi
if [[ ! -z $CS2_HOST_WORKSHOP_MAP ]]; then
CS2_HOST_WORKSHOP_MAP_ARGS="+host_workshop_map ${CS2_HOST_WORKSHOP_MAP}"
fi
if [[ ! -z $CS2_PW ]]; then
CS2_PW_ARGS="+sv_password ${CS2_PW}"
fi
# Start Server
if [[ ! -z $CS2_RCON_PORT ]]; then
echo "Establishing Simpleproxy for ${CS2_RCON_PORT} to 127.0.0.1:${CS2_PORT}"
simpleproxy -L "${CS2_RCON_PORT}" -R 127.0.0.1:"${CS2_PORT}" &
fi
echo "Starting CS2 Dedicated Server"
eval "./cs2" -dedicated \
"${CS2_IP_ARGS}" -port "${CS2_PORT}" \
-console \
-usercon \
-maxplayers "${CS2_MAXPLAYERS}" \
"${CS2_GAME_MODE_ARGS}" \
"${CS2_MAPGROUP_ARGS}" \
+map "${CS2_STARTMAP}" \
"${CS2_HOST_WORKSHOP_COLLECTION_ARGS}" \
"${CS2_HOST_WORKSHOP_MAP_ARGS}" \
"${CS2_MP_MATCH_END_CHANGELEVEL}" \
+rcon_password "${CS2_RCONPW}" \
"${SV_SETSTEAMACCOUNT_ARGS}" \
"${CS2_PW_ARGS}" \
+sv_lan "${CS2_LAN}" \
+tv_port "${TV_PORT}" \
"${CS2_ADDITIONAL_ARGS}"
# Post Hook
source "${STEAMAPPDIR}/post.sh"

0
bullseye/etc/post.sh → bookworm/etc/post.sh Normal file → Executable file
View file

0
bullseye/etc/pre.sh → bookworm/etc/pre.sh Normal file → Executable file
View file

44
bookworm/etc/server.cfg Normal file
View file

@ -0,0 +1,44 @@
// Server Defaults
hostname "{{SERVER_HOSTNAME}}" // Set server hostname
sv_cheats {{SERVER_CHEATS}} // Enable or disable cheats
sv_hibernate_when_empty {{SERVER_HIBERNATE}} // Disable server hibernation
// Passwords
rcon_password "{{SERVER_RCON_PW}}" // Set rcon password
sv_password "{{SERVER_PW}}" // Set server password
// CSTV
sv_hibernate_postgame_delay 30 // Delay server hibernation after all clients disconnect
tv_allow_camera_man 1 // Auto director allows spectators to become camera man
tv_allow_static_shots 1 // Auto director uses fixed level cameras for shots
tv_autorecord {{TV_AUTORECORD}} // Automatically records all games as CSTV demos: 0=off, 1=on.
tv_chatgroupsize 0 // Set the default chat group size
tv_chattimelimit 8 // Limits spectators to chat only every n seconds
tv_debug 0 // CSTV debug info.
tv_delay {{TV_DELAY}} // CSTV broadcast delay in seconds
tv_delaymapchange 1 // Delays map change until broadcast is complete
tv_deltacache 2 // Enable delta entity bit stream cache
tv_dispatchmode 1 // Dispatch clients to relay proxies: 0=never, 1=if appropriate, 2=always
tv_enable {{TV_ENABLE}} // Activates CSTV on server: 0=off, 1=on.
tv_maxclients 10 // Maximum client number on CSTV server.
tv_maxrate {{TV_MAXRATE}} // Max CSTV spectator bandwidth rate allowed, 0 == unlimited
tv_name "{{SERVER_HOSTNAME}} CSTV" // CSTV host name
tv_overridemaster 0 // Overrides the CSTV master root address.
tv_port {{TV_PORT}} // Host SourceTV port
tv_password "{{TV_PW}}" // CSTV password for clients
tv_relaypassword "{{TV_RELAY_PW}}" // CSTV password for relay proxies
tv_relayvoice 1 // Relay voice data: 0=off, 1=on
tv_timeout 60 // CSTV connection timeout in seconds.
tv_title "{{SERVER_HOSTNAME}} CSTV" // Set title for CSTV spectator UI
tv_transmitall 1 // Transmit all entities (not only director view)
// Logs
log {{SERVER_LOG}} // Turns logging 'on' or 'off', defaults to 'on'
mp_logmoney {{SERVER_LOG_MONEY}} // Turns money logging on/off: 0=off, 1=on
mp_logdetail {{SERVER_LOG_DETAIL}} // Combat damage logging: 0=disabled, 1=enemy, 2=friendly, 3=all
mp_logdetail_items {{SERVER_LOG_ITEMS}} // Turns item logging on/off: 0=off, 1=on

View file

@ -2,4 +2,4 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
docker build --target=bullseye-base -t $DOCKER_REPO:latest -t $DOCKER_REPO:base ${SCRIPT_DIR}/..
docker build --target=bookworm-base -t $DOCKER_REPO:latest -t $DOCKER_REPO:base ${SCRIPT_DIR}/..

2
bookworm/hooks/push Normal file
View file

@ -0,0 +1,2 @@
#!/bin/bash
docker push --all-tags ${DOCKER_REPO}

View file

@ -1,104 +0,0 @@
#!/bin/bash
mkdir -p "${STEAMAPPDIR}" || true
if [[ "$STEAMAPPVALIDATE" -eq 1 ]]; then
VALIDATE="validate"
else
VALIDATE=""
fi
# Download Updates
bash "${STEAMCMDDIR}/steamcmd.sh" +force_install_dir "${STEAMAPPDIR}" \
+login anonymous \
+app_update "${STEAMAPPID}" "${VALIDATE}" \
+quit
# steamclient.so fix
mkdir -p ~/.steam/sdk64
ln -sfT ${STEAMCMDDIR}/linux64/steamclient.so ~/.steam/sdk64/steamclient.so
# Install server.cfg
cp /etc/server.cfg "${STEAMAPPDIR}"/game/csgo/cfg/server.cfg
sed -r -i -e "s/^(hostname) .*/\1 ${CS2_SERVERNAME}/g" \
-e "s/^(sv_cheats) .*/\1 ${CS2_CHEATS}/g" \
-e "s/^(sv_hibernate_when_empty) .*/\1 ${CS2_SERVER_HIBERNATE}/g" \
-e "s/^(sv_password) .*/\1 ${CS2_PW}/g" \
-e "s/^(rcon_password) .*/\1 ${CS2_RCONPW}/g" \
-e "s/^(tv_enable) .*/\1 ${TV_ENABLE}/g" \
-e "s/^(tv_port) .*/\1 ${TV_PORT}/g" \
-e "s/^(tv_autorecord) .*/\1 ${TV_AUTORECORD}/g" \
-e "s/^(tv_password) .*/\1 ${TV_PW}/g" \
-e "s/^(tv_relaypassword) .*/\1 ${TV_RELAY_PW}/g" \
-e "s/^(tv_maxrate) .*/\1 ${TV_MAXRATE}/g" \
-e "s/^(tv_delay) .*/\1 ${TV_DELAY}/g" \
-e "s/^(tv_name) .*/\1 ${CS2_SERVERNAME} CSTV/g" \
-e "s/^(tv_title) .*/\1${CS2_SERVERNAME} CSTV/g" \
"${STEAMAPPDIR}"/game/csgo/cfg/server.cfg
# Install hooks
if [[ ! -f "${STEAMAPPDIR}/pre.sh" ]] ; then
cp /etc/pre.sh "${STEAMAPPDIR}/pre.sh"
fi
if [[ ! -f "${STEAMAPPDIR}/post.sh" ]] ; then
cp /etc/post.sh "${STEAMAPPDIR}/post.sh"
fi
# Rewrite Config Files
if [[ ! -z $CS2_BOT_DIFFICULTY ]] ; then
sed -r -i "s/^(bot_difficulty) .*/\1 ${CS2_BOT_DIFFICULTY}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
if [[ ! -z $CS2_BOT_QUOTA ]] ; then
sed -r -i "s/^(bot_quota) .*/\1 ${CS2_BOT_QUOTA}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
if [[ ! -z $CS2_BOT_QUOTA_MODE ]] ; then
sed -r -i "s/^(bot_quota_mode) .*/\1 ${CS2_BOT_QUOTA_MODE}/" "${STEAMAPPDIR}"/game/csgo/cfg/*
fi
# Switch to server directory
cd "${STEAMAPPDIR}/game/bin/linuxsteamrt64"
# Pre Hook
bash "${STEAMAPPDIR}/pre.sh"
# Construct server arguments
if [[ -z $CS2_GAMEALIAS ]]; then
# If CS2_GAMEALIAS is undefined then default to CS2_GAMETYPE and CS2_GAMEMODE
CS2_GAME_MODE_ARGS="+game_type ${CS2_GAMETYPE} +game_mode ${CS2_GAMEMODE}"
else
# Else, use alias to determine game mode
CS2_GAME_MODE_ARGS="+game_alias ${CS2_GAMEALIAS}"
fi
if [[ -z $CS2_IP ]]; then
CS2_IP_ARGS=""
else
CS2_IP_ARGS="-ip ${CS2_IP}"
fi
if [[ ! -z $SRCDS_TOKEN ]]; then
SV_SETSTEAMACCOUNT_ARGS="+sv_setsteamaccount ${SRCDS_TOKEN}"
fi
# Start Server
if [[ ! -z $CS2_RCON_PORT ]]; then
echo "Establishing Simpleproxy for ${CS2_RCON_PORT} to 127.0.0.1:${CS2_PORT}"
simpleproxy -L "${CS2_RCON_PORT}" -R 127.0.0.1:"${CS2_PORT}" &
fi
eval "./cs2" -dedicated \
"${CS2_IP_ARGS}" -port "${CS2_PORT}" \
-console \
-usercon \
-maxplayers "${CS2_MAXPLAYERS}" \
"${CS2_GAME_MODE_ARGS}" \
+mapgroup "${CS2_MAPGROUP}" \
+map "${CS2_STARTMAP}" \
+rcon_password "${CS2_RCONPW}" \
"${SV_SETSTEAMACCOUNT_ARGS}" \
+sv_password "${CS2_PW}" \
+sv_lan "${CS2_LAN}" \
"${CS2_ADDITIONAL_ARGS}"
# Post Hook
bash "${STEAMAPPDIR}/post.sh"

View file

@ -1,37 +0,0 @@
// Server Defaults
hostname "changeme" // Set server hostname
sv_cheats 0 // Enable or disable cheats
sv_hibernate_when_empty 0 // Disable server hibernation
// Passwords
rcon_password "changeme" // Set rcon password
sv_password "changeme" // Set server password
// CSTV
sv_hibernate_postgame_delay 30 // Delay server hibernation after all clients disconnect
tv_allow_camera_man 1 // Auto director allows spectators to become camera man
tv_allow_static_shots 1 // Auto director uses fixed level cameras for shots
tv_autorecord 0 // Automatically records all games as CSTV demos: 0=off, 1=on.
tv_chatgroupsize 0 // Set the default chat group size
tv_chattimelimit 8 // Limits spectators to chat only every n seconds
tv_debug 0 // CSTV debug info.
tv_delay 30 // CSTV broadcast delay in seconds
tv_delaymapchange 1 // Delays map change until broadcast is complete
tv_deltacache 2 // Enable delta entity bit stream cache
tv_dispatchmode 1 // Dispatch clients to relay proxies: 0=never, 1=if appropriate, 2=always
tv_enable 0 // Activates CSTV on server: 0=off, 1=on.
tv_maxclients 10 // Maximum client number on CSTV server.
tv_maxrate 20000 // Max CSTV spectator bandwidth rate allowed, 0 == unlimited
tv_name "changeme" // CSTV host name
tv_overridemaster 0 // Overrides the CSTV master root address.
tv_port 0 // Host SourceTV port
tv_password "changeme" // CSTV password for clients
tv_relaypassword "changeme" // CSTV password for relay proxies
tv_relayvoice 1 // Relay voice data: 0=off, 1=on
tv_timeout 60 // CSTV connection timeout in seconds.
tv_title "changeme" // Set title for CSTV spectator UI
tv_transmitall 1 // Transmit all entities (not only director view)

View file

@ -1,2 +0,0 @@
#!/bin/bash
docker push --all-tags ${DOCKER_REPO}

BIN
examples/cs2.cfg.tgz Normal file

Binary file not shown.

View file

@ -0,0 +1,56 @@
services:
cs2-server:
image: joedwards32/cs2
container_name: cs2-dedicated
environment:
# Server configuration
- SRCDS_TOKEN # Game Server Token from https://steamcommunity.com/dev/managegameservers
- DEBUG=0 # (0 - off, 1 - steamcmd, 2 - cs2, 3 - all)
- STEAMAPPVALIDATE=0 # (0 - no validation, 1 - enable validation)
- CS2_SERVERNAME=changeme # (Set the visible name for your private server)
- CS2_CHEATS=0 # (0 - disable cheats, 1 - enable cheats)
- CS2_PORT=27015 # (CS2 server listen port tcp_udp)
- CS2_SERVER_HIBERNATE=0 # (Put server in a low CPU state when there are no players. 0 - hibernation disabled, 1 - hibernation enabled)
- 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)
- CS2_CFG_URL # HTTP/HTTPS URL to fetch a Tar Gzip bundle, Tar or Zip archive of configuration files/mods
# Game modes
- CS2_GAMEALIAS # (Game type, e.g. casual, competitive, deathmatch. See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
- CS2_GAMETYPE=0 # (Used if CS2_GAMEALIAS not defined. See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
- CS2_GAMEMODE=1 # (Used if CS2_GAMEALIAS not defined. See https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers)
- CS2_MAPGROUP=mg_active # (Map pool. Ignored if Workshop maps are defined.)
- CS2_STARTMAP=de_inferno # (Start map. Ignored if Workshop maps are defined.)
# Workshop Maps
- CS2_HOST_WORKSHOP_COLLECTION # The workshop collection to use
- CS2_HOST_WORKSHOP_MAP # The workshop map to use. If collection is also defined, this is the starting map.
# Bots
- CS2_BOT_DIFFICULTY # (0 - easy, 1 - normal, 2 - hard, 3 - expert)
- CS2_BOT_QUOTA # (Number of bots)
- CS2_BOT_QUOTA_MODE # (fill, competitive)
# TV
- TV_AUTORECORD=0 # Automatically records all games as CSTV demos: 0=off, 1=on.
- TV_ENABLE=0 # Activates CSTV on server: 0=off, 1=on.
- TV_PORT=27020 # Host SourceTV port
- TV_PW=changeme # CSTV password for clients
- TV_RELAY_PW=changeme # CSTV password for relay proxies
- TV_MAXRATE=0 # World snapshots to broadcast per second. Affects camera tickrate.
- TV_DELAY=0 # CSTV broadcast delay in seconds
# Logs
- CS2_LOG=on # 'on'/'off'
- CS2_LOG_MONEY=0 # Turns money logging on/off: (0=off, 1=on)
- CS2_LOG_DETAIL=0 # Combat damage logging: (0=disabled, 1=enemy, 2=friendly, 3=all)
- CS2_LOG_ITEMS=0 # Turns item logging on/off: (0=off, 1=on)
volumes:
- cs2:/home/steam/cs2-dedicated/ # Persistent data volume mount point inside container
ports:
- "27015:27015/tcp" # TCP
- "27015:27015/udp" # UDP
- "27020:27020/udp" # UDP
stdin_open: true # Add local console for docker attach, docker attach --sig-proxy=false cs2-dedicated
tty: true # Add local console for docker attach, docker attach --sig-proxy=false cs2-dedicated
volumes:
cs2: