Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Docker Implementation #61

Merged
merged 12 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TICKRATE=128
MAXPLAYERS=24
API_KEY="" # Only needed if workshop maps are needed
STEAM_ACCOUNT="" # Only needed for online play
18 changes: 18 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Docker Image CI

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:

build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag cs2-modded-server:$(date +%s)
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/tools/
/server/
/steamcmd/
.env copy
/custom_files/*
52 changes: 52 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
FROM debian:bullseye-20240211-slim

USER root

RUN apt-get update --fix-missing \
&& apt-get install -y --no-install-recommends \
sudo \
dnsutils \
curl \
git-all \
ca-certificates=20210119 \
lib32z1=1:1.2.11.dfsg-2+deb11u2 \
wget=1.21-1+deb11u1 \
locales \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
&& dpkg-reconfigure --frontend=noninteractive locales \
&& rm -rf /var/lib/apt/lists/*


RUN addgroup steam \
&& useradd -g steam steam \
&& usermod -aG sudo steam

ENV TICKRATE=""
ENV MAXPLAYERS=""
ENV API_KEY=""
ENV STEAM_ACCOUNT=""

RUN echo "steam ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/steam \
&& chmod 0440 /etc/sudoers.d/steam

RUN mkdir -p /home/cs2-modded-server

RUN mkdir -p /home/steam/cs2

WORKDIR /home/cs2-modded-server/

RUN chown -R steam:steam /home/steam/cs2

RUN git clone https://github.com/DanielDKnudsen/cs2-modded-server

RUN echo cloned repository

RUN mv /home/cs2-modded-server/cs2-modded-server/* /home/cs2-modded-server

RUN rm -rf /home/cs2-modded-server/cs2-modded-server

WORKDIR /home/cs2-modded-server/

USER steam

CMD [ "sudo", "-E", "bash", "/home/cs2-modded-server/install_docker.sh" ]
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Getting up and running:

- [Running on Google Cloud](#running-on-google-cloud)
- [Running on Linux](#running-on-linux)
- [Running in Docker](#running-in-docker)
- [Running on Windows](#running-on-windows)

## Mods installed
Expand Down Expand Up @@ -324,6 +325,29 @@ If you see content in both; everything is working.

When you join the server you can [change game modes](#changing-game-modes).

## Running in Docker

*Only tested on Windows 11 with WSL2 integration as backend*

Make sure Docker is installed and about 40 GB disk space is free.

You can either Download this repo and extract it to where you want your server (i.e. C:\Server\cs2-modded-server) or use git and clone the repo git clone [email protected]:kus/cs2-modded-server.git and run your server from inside of it. This way you can simply git pull updates.

- **If setting up for internet server:**

Set 'STEAM_ACCOUNT' variable in '.env'-file in the root if the repository.
For workshop maps set 'API_KEY' in '.env'-file.

- **Build docker image:**

`docker build -t cs2-modded-server .`

- **Run the server**

`docker compose up`



## Running on Windows

Make sure you have **60GB free space**.
Expand Down
25 changes: 25 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
services:
cs2_modded_server:
image: cs2-modded-server
container_name: cs2-modded-server
env_file:
- .env
volumes:
- cs2-volume:/home/steam/
- type: bind
source: ./custom_files
target: /home/custom_files/
- type: bind
source: ./game
target: /home/game/
ports:
- "27015:27015/tcp"
- "27015:27015/udp"
- "27020:27020/tcp"
- "27020:27020/udp"
cpu_count: 2
mem_limit: 3500m
# command: tail -F anything

volumes:
cs2-volume:
207 changes: 207 additions & 0 deletions install_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#!/usr/bin/env bash

# As root (sudo su)
# cd / && curl -s -H "Cache-Control: no-cache" -o "install.sh" "https://raw.githubusercontent.com/kus/cs2-modded-server/master/install.sh" && chmod +x install.sh && bash install.sh

# Variables
user="steam"
BRANCH="master"

# Check if MOD_BRANCH is set and not empty
if [ -n "$MOD_BRANCH" ]; then
BRANCH="$MOD_BRANCH"
fi

CUSTOM_FILES="${CUSTOM_FOLDER:-custom_files}"

# 32 or 64 bit Operating System
# If BITS environment variable is not set, try determine it
if [ -z "$BITS" ]; then
# Determine the operating system architecture
architecture=$(uname -m)

# Set OS_BITS based on the architecture
if [[ $architecture == *"64"* ]]; then
export BITS=64
elif [[ $architecture == *"i386"* ]] || [[ $architecture == *"i686"* ]]; then
export BITS=32
else
echo "Unknown architecture: $architecture"
exit 1
fi
fi

if [[ -z $IP ]]; then
IP_ARGS=""
else
IP_ARGS="-ip ${IP}"
fi

if [ -f /etc/os-release ]; then
# freedesktop.org and systemd
. /etc/os-release
DISTRO_OS=$NAME
DISTRO_VERSION=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
# linuxbase.org
DISTRO_OS=$(lsb_release -si)
DISTRO_VERSION=$(lsb_release -sr)
elif [ -f /etc/lsb-release ]; then
# For some versions of Debian/Ubuntu without lsb_release command
. /etc/lsb-release
DISTRO_OS=$DISTRIB_ID
DISTRO_VERSION=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
# Older Debian/Ubuntu/etc.
DISTRO_OS=Debian
DISTRO_VERSION=$(cat /etc/debian_version)
else
# Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
DISTRO_OS=$(uname -s)
DISTRO_VERSION=$(uname -r)
fi

echo "Starting on $DISTRO_OS: $DISTRO_VERSION..."

# Get the free space on the root filesystem in GB
FREE_SPACE=$(df / --output=avail -BG | tail -n 1 | tr -d 'G')

echo "With $FREE_SPACE Gb free space..."

# Check root
if [ "$EUID" -ne 0 ]; then
echo "ERROR: Please run this script as root..."
exit 1
fi

PUBLIC_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)

if [ -z "$PUBLIC_IP" ]; then
echo "ERROR: Cannot retrieve your public IP address..."
exit 1
fi

# Update DuckDNS with our current IP
if [ ! -z "$DUCK_TOKEN" ]; then
echo url="http://www.duckdns.org/update?domains=$DUCK_DOMAIN&token=$DUCK_TOKEN&ip=$PUBLIC_IP" | curl -k -o /duck.log -K -
fi

echo "Checking $user user exists..."
getent passwd ${user} >/dev/null 2&>1
if [ "$?" -ne "0" ]; then
echo "Adding $user user..."
addgroup ${user} && \
adduser --system --home /home/${user} --shell /bin/false --ingroup ${user} ${user} && \
usermod -a -G tty ${user} && \
mkdir -m 777 /home/${user}/cs2 && \
chown -R ${user}:${user} /home/${user}/cs2
if [ "$?" -ne "0" ]; then
echo "ERROR: Cannot add user $user..."
exit 1
fi
fi

echo "Checking steamcmd exists..."
if [ ! -d "/steamcmd" ]; then
mkdir /steamcmd && cd /steamcmd
wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz
tar -xvzf steamcmd_linux.tar.gz
mkdir -p /root/.steam/sdk32/
ln -s /steamcmd/linux32/steamclient.so /root/.steam/sdk32/
mkdir -p /root/.steam/sdk64/
ln -s /steamcmd/linux64/steamclient.so /root/.steam/sdk64/
fi

chown -R ${user}:${user} /steamcmd

echo "Downloading any updates for CS2..."
# https://developer.valvesoftware.com/wiki/Command_line_options
sudo -u $user /steamcmd/steamcmd.sh \
+api_logging 1 1 \
+@sSteamCmdForcePlatformType linux \
+@sSteamCmdForcePlatformBitness $BITS \
+force_install_dir /home/${user}/cs2 \
+login anonymous \
+app_update 730 \
+quit

cd /home/${user}
echo "/home/user !!!!!!!"

# mkdir -p /root/.steam/sdk32/
# ln -sf /steamcmd/linux32/steamclient.so /root/.steam/sdk32/
# mkdir -p /root/.steam/sdk64/
# ln -sf /steamcmd/linux64/steamclient.so /root/.steam/sdk64/

# mkdir -p /home/${user}/.steam/sdk32/
# ln -sf /steamcmd/linux32/steamclient.so /home/${user}/.steam/sdk32/
# mkdir -p /home/${user}/.steam/sdk64/
# ln -sf /steamcmd/linux64/steamclient.so /home/${user}/.steam/sdk64/

echo "Installing mods"
cp -R /home/game/csgo/ /home/${user}/cs2/game/

echo "Merging in custom files"
cp -RT /home/custom_files/ /home/${user}/cs2/game/csgo/

chown -R ${user}:${user} /home/${user}/cs2

cd /home/${user}/cs2

# Define the file name
FILE="game/csgo/gameinfo.gi"

# Define the pattern to search for and the line to add
PATTERN="Game_LowViolence[[:space:]]*csgo_lv // Perfect World content override"
LINE_TO_ADD="\t\t\tGame\tcsgo/addons/metamod"

# Use a regular expression to ignore spaces when checking if the line exists
REGEX_TO_CHECK="^[[:space:]]*Game[[:space:]]*csgo/addons/metamod"

# Check if the line already exists in the file, ignoring spaces
if grep -qE "$REGEX_TO_CHECK" "$FILE"; then
echo "$FILE already patched for Metamod."
else
# If the line isn't there, use awk to add it after the pattern
awk -v pattern="$PATTERN" -v lineToAdd="$LINE_TO_ADD" '{
print $0;
if ($0 ~ pattern) {
print lineToAdd;
}
}' "$FILE" > tmp_file && mv tmp_file "$FILE"
echo "$FILE successfully patched for Metamod."
fi

echo "Starting server on $PUBLIC_IP:$PORT"
# https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers#Command-Line_Parameters
echo ./game/bin/linuxsteamrt64/cs2 \
-dedicated \
-console \
-usercon \
-autoupdate \
-tickrate $TICKRATE \
$IP_ARGS \
-port $PORT \
+map de_dust2 \
-maxplayers $MAXPLAYERS \
-authkey $API_KEY \
+sv_setsteamaccount $STEAM_ACCOUNT \
+game_type 0 \
+game_mode 0 \
+mapgroup mg_active

sudo -u $user /home/steam/cs2/game/bin/linuxsteamrt64/cs2 \
-dedicated \
-console \
-usercon \
-autoupdate \
-tickrate $TICKRATE \
$IP_ARGS \
-port $PORT \
+map de_dust2 \
-maxplayers $MAXPLAYERS \
-authkey $API_KEY \
+sv_setsteamaccount $STEAM_ACCOUNT \
+game_type 0 \
+game_mode 0 \
+mapgroup mg_active