├── Dockerfile ├── LICENSE ├── README.md ├── cfg ├── knife.cfg ├── live.cfg └── warmup.cfg ├── docker-compose.yaml └── entrypoint.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.gitlab.steamos.cloud/steamrt/sniper/platform 2 | 3 | ENV STEAMCMD_DIR /mnt/server/steamcmd 4 | ENV CS2_DIR /mnt/server/cs2 5 | ENV STEAM_DIR /mnt/server 6 | 7 | RUN adduser --disabled-password --gecos "" steam && \ 8 | mkdir -p ${STEAMCMD_DIR} && \ 9 | mkdir -p ${CS2_DIR}/steamapps && \ 10 | mkdir -p /mnt/cfg && \ 11 | curl -sSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar -zx -C /mnt/server/steamcmd && \ 12 | chown -R steam:steam /mnt/server 13 | ENV DEBIAN_FRONTEND=noninteractive 14 | USER steam 15 | ENV USER=steam HOME=/mnt/server 16 | WORKDIR /mnt/server 17 | 18 | COPY entrypoint.sh /entrypoint.sh 19 | COPY cfg/* /mnt/cfg 20 | CMD [ "/bin/bash", "/entrypoint.sh" ] 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Soren90 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CS2 dockerized 2 | 3 | This project is still in early development. But with this docker image you should be able to run a cs2 server in a pretty simple manner. Pull requests are open and I'll be happy to implement improvements to the project 4 | 5 | ## How to use 6 | 7 | Install docker: 8 | ```bash 9 | curl -fsSL https://get.docker.com/ -o install-docker.sh && sh install-docker.sh 10 | ``` 11 | 12 | > [!IMPORTANT] 13 | > You need to add your GSLT-token to the docker-compose file. You can generate your Game Server Login Token [here](https://steamcommunity.com/dev/managegameservers). Use AppID 730 for CS2. 14 | 15 | start the server: 16 | ```bash 17 | docker compose up -d 18 | ``` 19 | 20 | If you need to modify the server files, you will find the server files here: /var/lib/docker/volumes/cs2-data/_data/ 21 | 22 | ## TODO 23 | 24 | - Fix RCON (Bugged for now. You can only use rcon_address outside of the server for now.) 25 | - Add sourcemod/metamod when ready 26 | - Improve this document 27 | 28 | ## RCON workaround 29 | My workaround for now is to use [shobhit-pathak/cs2-rcon-panel](https://github.com/shobhit-pathak/cs2-rcon-panel) 30 | 31 | Docker image for the panel might not be up to date, as I'm not the maintainer, but here is a POC: 32 | ```yaml 33 | version: "3.7" 34 | 35 | volumes: 36 | cs2-data: 37 | name: cs2-data 38 | 39 | services: 40 | csgo: 41 | image: soren90/cs2 42 | container_name: cs2-ds 43 | 44 | environment: 45 | SERVER_HOSTNAME: "Counter-strike 2 Dedicated server" 46 | SERVER_PASSWORD: "" 47 | RCON_PASSWORD: "" 48 | IP: 0.0.0.0 49 | PORT: 27015 50 | GAME_TYPE: 0 51 | GAME_MODE: 1 52 | MAP: de_inferno 53 | MAXPLAYERS: 12 54 | MAPGROUP: mg_active 55 | GSLT: 56 | EXTRAARG: "" 57 | 58 | volumes: 59 | - type: volume 60 | source: cs2-data 61 | target: /mnt/server 62 | 63 | network_mode: "host" 64 | 65 | restart: unless-stopped 66 | stdin_open: true 67 | tty: true 68 | rconpanel: 69 | image: soren90/rcon-panel 70 | ports: 71 | - "3000:3000" 72 | restart: unless-stopped 73 | 74 | ``` 75 | 76 | ## Credits 77 | 78 | This is heavily inspired by [kaimallea/csgo](https://github.com/kaimallea/csgo) 79 | Great webpanel for RCON: [shobhit-pathak/cs2-rcon-panel](https://github.com/shobhit-pathak/cs2-rcon-panel) 80 | -------------------------------------------------------------------------------- /cfg/knife.cfg: -------------------------------------------------------------------------------- 1 | mp_ct_default_secondary "" 2 | mp_free_armor 1 3 | mp_freezetime 10 4 | mp_give_player_c4 0 5 | mp_maxmoney 0 6 | mp_respawn_immunitytime 0 7 | mp_respawn_on_death_ct 0 8 | mp_respawn_on_death_t 0 9 | mp_roundtime 1.92 10 | mp_roundtime_defuse 1.92 11 | mp_roundtime_hostage 1.92 12 | mp_t_default_secondary "" 13 | mp_round_restart_delay 3 14 | mp_warmup_end 15 | mp_restartgame 1 16 | 17 | 18 | say Knife! 19 | say Knife! 20 | say Knife! 21 | -------------------------------------------------------------------------------- /cfg/live.cfg: -------------------------------------------------------------------------------- 1 | ammo_grenade_limit_default 1 2 | ammo_grenade_limit_flashbang 2 3 | ammo_grenade_limit_total 4 4 | bot_quota 0 5 | cash_player_bomb_defused 300 6 | cash_player_bomb_planted 300 7 | cash_player_damage_hostage -30 8 | cash_player_interact_with_hostage 300 9 | cash_player_killed_enemy_default 300 10 | cash_player_killed_enemy_factor 1 11 | cash_player_killed_hostage -1000 12 | cash_player_killed_teammate -300 13 | cash_player_rescued_hostage 1000 14 | cash_team_bonus_shorthanded 1000 15 | cash_team_elimination_bomb_map 3250 16 | cash_team_elimination_hostage_map_ct 3000 17 | cash_team_elimination_hostage_map_t 3000 18 | cash_team_hostage_alive 0 19 | cash_team_hostage_interaction 600 20 | cash_team_loser_bonus 1400 21 | cash_team_loser_bonus_consecutive_rounds 500 22 | cash_team_planted_bomb_but_defused 800 23 | cash_team_rescued_hostage 600 24 | cash_team_terrorist_win_bomb 3500 25 | cash_team_win_by_defusing_bomb 3500 26 | cash_team_win_by_hostage_rescue 2900 27 | cash_team_win_by_time_running_out_bomb 3250 28 | cash_team_win_by_time_running_out_hostage 3250 29 | ff_damage_reduction_bullets 0.33 30 | ff_damage_reduction_grenade 0.85 31 | ff_damage_reduction_grenade_self 1 32 | ff_damage_reduction_other 0.4 33 | mp_afterroundmoney 0 34 | mp_autokick 0 35 | mp_autoteambalance 0 36 | mp_backup_restore_load_autopause 1 37 | mp_backup_round_auto 1 38 | mp_buy_anywhere 0 39 | mp_buy_during_immunity 0 40 | mp_buytime 20 41 | mp_c4timer 40 42 | mp_ct_default_melee weapon_knife 43 | mp_ct_default_primary "" 44 | mp_ct_default_secondary weapon_hkp2000 45 | mp_death_drop_defuser 1 46 | mp_death_drop_grenade 2 47 | mp_death_drop_gun 1 48 | mp_defuser_allocation 0 49 | mp_display_kill_assists 1 50 | mp_endmatch_votenextmap 0 51 | mp_forcecamera 1 52 | mp_free_armor 0 53 | mp_freezetime 15 54 | mp_friendlyfire 1 55 | mp_give_player_c4 1 56 | mp_halftime 1 57 | mp_halftime_duration 15 58 | mp_halftime_pausetimer 0 59 | mp_ignore_round_win_conditions 0 60 | mp_limitteams 0 61 | mp_match_can_clinch 1 62 | mp_match_end_restart 1 63 | mp_maxmoney 16000 64 | mp_maxrounds 24 65 | mp_molotovusedelay 0 66 | mp_overtime_enable 1 67 | mp_overtime_halftime_pausetimer 0 68 | mp_overtime_maxrounds 6 69 | mp_overtime_startmoney 10000 70 | mp_playercashawards 1 71 | mp_randomspawn 0 72 | mp_respawn_immunitytime 0 73 | mp_respawn_on_death_ct 0 74 | mp_respawn_on_death_t 0 75 | mp_round_restart_delay 7 76 | mp_roundtime 1.92 77 | mp_roundtime_defuse 1.92 78 | mp_roundtime_hostage 1.92 79 | mp_solid_teammates 1 80 | mp_starting_losses 1 81 | mp_startmoney 800 82 | mp_t_default_melee weapon_knife 83 | mp_t_default_primary "" 84 | mp_t_default_secondary weapon_glock 85 | mp_teamcashawards 1 86 | mp_timelimit 0 87 | mp_weapons_allow_map_placed 1 88 | mp_weapons_allow_zeus 1 89 | mp_weapons_glow_on_ground 0 90 | mp_win_panel_display_time 3 91 | occlusion_test_async 0 92 | spec_freeze_deathanim_time 0 93 | spec_freeze_panel_extended_time 0 94 | spec_freeze_time 2 95 | spec_freeze_time_lock 2 96 | spec_replay_enable 0 97 | sv_allow_votes 0 98 | sv_auto_full_alltalk_during_warmup_half_end 0 99 | sv_coaching_enabled 1 100 | sv_competitive_official_5v5 1 101 | sv_damage_print_enable 0 102 | sv_deadtalk 1 103 | sv_hibernate_postgame_delay 300 104 | sv_holiday_mode 0 105 | sv_ignoregrenaderadio 0 106 | sv_infinite_ammo 0 107 | sv_occlude_players 1 108 | sv_talk_enemy_dead 0 109 | sv_talk_enemy_living 0 110 | sv_voiceenable 1 111 | tv_relayvoice 0 112 | mp_warmup_end 113 | mp_restartgame 1 114 | say Match is live! 115 | say Match is live! 116 | say Match is live! 117 | -------------------------------------------------------------------------------- /cfg/warmup.cfg: -------------------------------------------------------------------------------- 1 | bot_kick 2 | bot_quota 0 3 | mp_autokick 0 4 | mp_autoteambalance 0 5 | mp_buy_anywhere 0 6 | mp_buytime 15 7 | mp_death_drop_gun 0 8 | mp_free_armor 0 9 | mp_ignore_round_win_conditions 0 10 | mp_limitteams 0 11 | mp_radar_showall 0 12 | mp_respawn_on_death_ct 0 13 | mp_respawn_on_death_t 0 14 | mp_solid_teammates 0 15 | mp_spectators_max 20 16 | mp_maxmoney 16000 17 | mp_startmoney 16000 18 | mp_timelimit 0 19 | sv_alltalk 1 20 | sv_auto_full_alltalk_during_warmup_half_end 0 21 | sv_coaching_enabled 1 22 | sv_competitive_official_5v5 1 23 | sv_deadtalk 1 24 | sv_full_alltalk 1 25 | sv_grenade_trajectory 0 26 | sv_hibernate_when_empty 0 27 | mp_weapons_allow_typecount -1 28 | sv_infinite_ammo 0 29 | sv_showimpacts 0 30 | sv_voiceenable 1 31 | sm_cvar sv_mute_players_with_social_penalties 0 32 | sv_mute_players_with_social_penalties 0 33 | tv_relayvoice 1 34 | sv_cheats 0 35 | mp_ct_default_melee weapon_knife 36 | mp_ct_default_secondary weapon_hkp2000 37 | mp_ct_default_primary "" 38 | mp_t_default_melee weapon_knife 39 | mp_t_default_secondary weapon_glock 40 | mp_t_default_primary 41 | mp_warmup_start 42 | mp_warmup_pausetimer 1 43 | mp_warmuptime 9999 44 | mp_restartgame 1 45 | say Warmup! 46 | say Warmup! 47 | say Warmup! 48 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | volumes: 4 | cs2-data: 5 | name: cs2-data 6 | 7 | services: 8 | cs2: 9 | image: soren90/cs2:latest 10 | container_name: cs2-ds 11 | 12 | environment: 13 | SERVER_HOSTNAME: "Counter-strike 2 Dedicated server" 14 | SERVER_PASSWORD: "" 15 | RCON_PASSWORD: "" 16 | IP: 0.0.0.0 17 | PORT: 27015 18 | GAME_TYPE: 0 19 | GAME_MODE: 1 20 | MAP: de_inferno 21 | MAXPLAYERS: 12 22 | MAPGROUP: mg_active 23 | GSLT: #Mandatory 24 | EXTRAARG: #Extra Launch options 25 | 26 | volumes: 27 | - type: volume 28 | source: cs2-data 29 | target: /mnt/server 30 | #- ./cfg:/mnt/cfg # Custom cfg files to be mounted to the `/cfg` folder on each container start 31 | 32 | network_mode: "host" 33 | 34 | restart: unless-stopped 35 | stdin_open: true 36 | tty: true 37 | 38 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | sleep 1 2 | # Mandatory variables check 3 | : "${STEAM_DIR:?'ERROR: STEAM_DIR IS NOT SET!'}" 4 | : "${STEAMCMD_DIR:?'ERROR: STEAMCMD_DIR IS NOT SET!'}" 5 | : "${CS2_DIR:?'ERROR: CSGO_DIR IS NOT SET!'}" 6 | : "${GSLT:?'ERROR: GSLT IS NOT SET!'}" 7 | 8 | # Set defaults 9 | export SERVER_HOSTNAME="${SERVER_HOSTNAME:-cs2server}" 10 | export PORT="${PORT:-27015}" 11 | export GAME_TYPE="${GAME_TYPE:-0}" 12 | export GAME_MODE="${GAME_MODE:-1}" 13 | export MAP="${MAP:-de_dust2}" 14 | export MAPGROUP="${MAPGROUP:-mg_active}" 15 | export MAXPLAYERS="${MAXPLAYERS:-12}" 16 | export IP="${IP:-0.0.0.0}" 17 | 18 | # Copy competitive configs 19 | mkdir -p ${CS2_DIR}/game/csgo/cfg 20 | cp /mnt/cfg/* ${CS2_DIR}/game/csgo/cfg 21 | 22 | if [ ! -s "$CS2_DIR/game/csgo/cfg/autoexec.cfg" ]; then 23 | cat << AUTOEXECCFG > "$CS2_DIR/game/csgo/cfg/autoexec.cfg" 24 | log on 25 | hostname "$SERVER_HOSTNAME" 26 | rcon_password "$RCON_PASSWORD" 27 | sv_password "$SERVER_PASSWORD" 28 | sv_cheats 0 29 | tv_delaymapchange 1 30 | tv_delay 30 31 | tv_deltacache 2 32 | tv_dispatchmode 1 33 | tv_maxclients 10 34 | tv_maxrate 0 35 | tv_overridemaster 0 36 | tv_relayvoice 1 37 | tv_snapshotrate 64 38 | tv_timeout 60 39 | tv_transmitall 1 40 | writeid 41 | writeip 42 | exec banned_user.cfg 43 | exec banned_ip.cfg 44 | exec warmup.cfg 45 | AUTOEXECCFG 46 | 47 | else 48 | sed -i "s/^hostname.*/hostname \"$SERVER_HOSTNAME\"/" $CS2_DIR/game/csgo/cfg/autoexec.cfg 49 | sed -i "s/^rcon_password.*/rcon_password \"$RCON_PASSWORD\"/" $CS2_DIR/game/csgo/cfg/autoexec.cfg 50 | sed -i "s/^sv_password.*/sv_password \"$SERVER_PASSWORD\"/" $CS2_DIR/game/csgo/cfg/autoexec.cfg 51 | 52 | fi 53 | 54 | # Install/update game 55 | ${STEAMCMD_DIR}/steamcmd.sh +login anonymous +force_install_dir ${CS2_DIR} +app_update 730 +quit 56 | 57 | # hacky error fix 58 | mkdir -p ${STEAM_DIR}/.steam/sdk32 59 | mkdir -p ${STEAM_DIR}/.steam/sdk64 60 | 61 | cp ${STEAMCMD_DIR}/linux32/steamclient.so ${STEAM_DIR}/.steam/sdk32/steamclient.so 62 | cp ${STEAMCMD_DIR}/linux64/steamclient.so ${STEAM_DIR}/.steam/sdk64/steamclient.so 63 | 64 | # Start gameserver 65 | ${CS2_DIR}/game/cs2.sh +ip ${IP} -port ${PORT} -maxplayers ${MAXPLAYERS} -dedicated -game csgo -console -usercon +map ${MAP} +mapgroup ${MAPGROUP} +game_type ${GAME_TYPE} +game_mode ${GAME_MODE} +exec autoexec.cfg +sv_setsteamaccount "${GSLT}" ${EXTRAARG} 66 | --------------------------------------------------------------------------------