Last active
February 9, 2025 07:17
-
-
Save JM1/350cd57ac9dfb1bf94de89e56df104ef to your computer and use it in GitHub Desktop.
Butane config for Fedora CoreOS 39 and later which will run a Counter Strike 2 dedicated server in a Podman container.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2024 Jakob Meng, <[email protected]> | |
# SPDX-License-Identifier: LGPL-2.1-or-later | |
# | |
# A Butane config [0] for Fedora CoreOS 39 and later [1] which will run a Counter Strike 2 dedicated server [2] in a | |
# Podman container. | |
# | |
# First, customize all configuration settings marked with a TODO below. Then use Butane to translate it into a Ignition | |
# config [3]. With CoreOS Installer, embed it into a ISO or PXE image for Fedora CoreOS and/or to install Fedora CoreOS | |
# to bare metal [4] or a libvirt [5] virtual machine or a QEMU virtual machine [6]. | |
# | |
# Ref.: | |
# [0] https://coreos.github.io/butane/specs/ | |
# [1] https://docs.fedoraproject.org/en-US/fedora-coreos/ | |
# [2] https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers | |
# [3] https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/ | |
# [4] https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/ | |
# [5] https://docs.fedoraproject.org/en-US/fedora-coreos/provisioning-libvirt/ | |
# [6] https://docs.fedoraproject.org/en-US/fedora-coreos/provisioning-qemu/ | |
variant: fcos | |
version: 1.4.0 | |
passwd: | |
users: | |
- name: gamemaster | |
# TODO: Replace with your SSH keys. | |
ssh_authorized_keys: | |
- ssh-rsa AAAAB3NzaC1yc2E... | |
# TODO: Uncomment to grant administrative privileges | |
#groups: | |
# - sudo | |
# - wheel | |
storage: | |
directories: | |
- path: /home/gamemaster/.config | |
mode: 0755 | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/.config/systemd | |
mode: 0755 | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/.config/systemd/user | |
mode: 0755 | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/.config/systemd/user/default.target.wants | |
mode: 0755 | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/steamcmd | |
mode: 0755 | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
files: | |
# TODO: Adapt network configuration. | |
- path: /etc/NetworkManager/system-connections/first.nmconnection | |
mode: 0600 | |
contents: | |
inline: | | |
# 2024 Jakob Meng, <[email protected]> | |
# | |
# Network configuration | |
# | |
# This example assigns a static ip address, similar to | |
# $> nmcli con add con-name "first" ifname enxdeadbeef1337 type ethernet ip4 192.168.0.66/16 gw4 192.168.0.1 | |
# $> nmcli con mod "first" ipv4.dns "192.168.0.1" | |
# $> nmcli con mod "first" ipv6.method "disabled" | |
# $> nmcli con up "first" | |
# | |
# Ref.: https://www.networkmanager.dev/docs/api/latest/nm-settings-nmcli.html | |
[connection] | |
id=first | |
type=ethernet | |
# NOTE: Kernel command line argument net.ifname-policy=mac has to be set when | |
# interface names should be based on the device's persistent MAC address. | |
interface-name=enxdeadbeef1337 | |
[ethernet] | |
[ipv4] | |
address1=192.168.0.66/16,192.168.0.1 | |
dns=192.168.0.1; | |
method=manual | |
[ipv6] | |
addr-gen-mode=default | |
method=disabled | |
- path: /etc/sudoers.d/sudoers | |
mode: 0440 | |
contents: | |
inline: | | |
# 2024 Jakob Meng, <[email protected]> | |
gamemaster ALL=(ALL) NOPASSWD: /usr/sbin/poweroff, /usr/sbin/reboot | |
- path: /etc/ssh/sshd_config.d/99-disable-password-authentication.conf | |
mode: 0644 | |
contents: | |
inline: | | |
# 2023 Jakob Meng, <[email protected]> | |
PasswordAuthentication no | |
- path: /var/lib/systemd/linger/gamemaster | |
mode: 0644 | |
- path: /home/gamemaster/.config/systemd/user/steamcmd.service | |
mode: 0644 | |
contents: | |
inline: | | |
# Copyright (c) 2024 Jakob Meng, <[email protected]> | |
# SPDX-License-Identifier: LGPL-2.1-or-later | |
# ~/.config/systemd/user/steamcmd.service | |
[Unit] | |
Description=Counter Strike 2 dedicated server | |
Wants=network-online.target | |
After=network-online.target | |
[Service] | |
Environment=PODMAN_SYSTEMD_UNIT=%n | |
Restart=always | |
RestartSec=1min | |
# Grant time to build image | |
TimeoutStartSec=900 | |
ExecStartPre=/usr/bin/podman build --pull=always -t steamcmd:rawhide "steamcmd/" | |
ExecStartPre=/usr/bin/podman volume create --ignore "steamcmd" | |
ExecStart=/usr/bin/bash -c ' \ | |
max_uid_count=$(grep -e "^$(id -n -u):" /etc/subuid | cut -d ':' -f 3); \ | |
[ -n "$max_uid_count" ] || exit 125; \ | |
exec /usr/bin/podman run \ | |
--cidfile=%t/%n.ctr-id \ | |
--cgroups=no-conmon \ | |
--sdnotify=conmon \ | |
--detach \ | |
--name "steamcmd" \ | |
--replace \ | |
--init \ | |
--tty \ | |
--interactive \ | |
--uidmap "$UID:0:1" \ | |
--uidmap "0:1:$UID" \ | |
--uidmap "$((UID+1)):$((UID+1)):$((max_uid_count-UID))" \ | |
--publish '27000-27100:27000-27100/tcp' \ | |
--publish '27000-27100:27000-27100/udp' \ | |
--tmpfs /run:exec \ | |
--tmpfs /run/lock \ | |
--tmpfs /tmp:size=50% \ | |
-v "steamcmd:/home/gamer/Steam/:z" \ | |
-v "$HOME/steamcmd/entrypoint.sh:/usr/local/bin/entrypoint.sh:ro,z" \ | |
-v "$HOME/steamcmd/:/home/gamer/steamcmd/:ro,z" \ | |
"steamcmd:rawhide" \ | |
' | |
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id | |
ExecStopPost=/usr/bin/podman rm --ignore --cidfile=%t/%n.ctr-id --force | |
Type=notify | |
NotifyAccess=all | |
[Install] | |
WantedBy=default.target | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/steamcmd/Dockerfile | |
mode: 0644 | |
contents: | |
inline: | | |
# Copyright (c) 2024 Jakob Meng, <[email protected]> | |
# SPDX-License-Identifier: LGPL-2.1-or-later | |
# ~/steamcmd/Dockerfile | |
FROM registry.fedoraproject.org/fedora:rawhide | |
RUN dnf -y upgrade && \ | |
dnf install -y curl iputils man-db psmisc shadow-utils vim tzdata && \ | |
dnf install -y glibc.i686 libstdc++.i686 && \ | |
dnf clean all | |
RUN useradd --create-home --shell /bin/bash gamer | |
USER gamer | |
RUN mkdir -p /home/gamer/Steam/ | |
USER ROOT | |
VOLUME /home/gamer/Steam/ | |
COPY entrypoint.sh /usr/local/bin/ | |
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] | |
CMD [] | |
USER gamer | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/steamcmd/entrypoint.sh | |
mode: 0755 | |
contents: | |
inline: | | |
#!/bin/bash | |
# vim:set tabstop=8 shiftwidth=4 expandtab: | |
# kate: space-indent on; indent-width 4; | |
# | |
# Copyright (c) 2022-2024 Jakob Meng, <[email protected]> | |
# SPDX-License-Identifier: LGPL-2.1-or-later | |
# ~/steamcmd/entrypoint.sh | |
# | |
# Ref.: | |
# https://developer.valvesoftware.com/wiki/SteamCMD | |
# https://developer.valvesoftware.com/wiki/Counter-Strike_2/Dedicated_Servers | |
# https://developer.valvesoftware.com/wiki/List_of_Counter-Strike_2_console_commands_and_variables | |
set -euxo pipefail | |
error() { | |
echo "ERROR: $*" 1>&2 | |
} | |
if [ "$(id -u)" -eq 0 ]; then | |
error "Please do not run as root" | |
exit 125 | |
fi | |
export STEAM_DIR="$HOME/Steam" | |
export STEAM_APP="cs2-ds" | |
export STEAM_APP_DIR="$STEAM_DIR/_games/$STEAM_APP" | |
export STEAM_APP_ID="730" | |
cd "$STEAM_DIR" | |
if [ ! -e "./steamcmd.sh" ]; then | |
curl --fail --silent --show-error --location \ | |
'https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz' | tar -xzf - | |
"./steamcmd.sh" +quit | |
fi | |
if [ ! -e "$STEAM_APP_DIR" ]; then | |
# Install | |
"./steamcmd.sh" +force_install_dir "$STEAM_APP_DIR" +login anonymous +app_update "$STEAM_APP_ID" validate +quit | |
else | |
# Update only | |
"./steamcmd.sh" +force_install_dir "$STEAM_APP_DIR" +login anonymous +app_update "$STEAM_APP_ID" +quit | |
fi | |
# Workaround for issue with SteamCMD | |
if [ ! -e "$HOME/.steam/sdk64/steamclient.so" ]; then | |
mkdir -p "$HOME/.steam/sdk64" | |
ln -sfT "$STEAM_DIR/linux64/steamclient.so" "$HOME/.steam/sdk64/steamclient.so" | |
fi | |
if [ ! -L "$STEAM_APP_DIR/game/csgo/cfg/server.cfg" ]; then | |
rm -f "$STEAM_APP_DIR/game/csgo/cfg/server.cfg" | |
ln -s "$HOME/steamcmd/server.cfg" "$STEAM_APP_DIR/game/csgo/cfg/server.cfg" | |
fi | |
app_args=() | |
# Steam Web API Key (e.g. for Workshop maps) | |
# Ref.: https://steamcommunity.com/dev/apikey | |
# TODO: Enter Steam Web API Key. | |
app_args+=(-authkey "01234567890ABCDEF01234567890ABCD") | |
# Steam Game Server Login Token | |
# Ref.: https://steamcommunity.com/dev/managegameservers | |
# TODO: Enter Steam Game Server Login Token. | |
app_args+=(+sv_setsteamaccount "01234567890ABCDEF01234567890ABCD") | |
# Set the configuration of game type and mode based on game alias like "deathmatch". | |
app_args+=(+game_alias competitive) | |
# or | |
#app_args+=(+game_mode 1 +game_type 0) | |
#app_args+=(+game_alias wingman) | |
# or | |
#app_args+=(+game_mode 2 +game_type 0) | |
#app_args+=(+game_alias casual) | |
# or | |
#app_args+=(+game_mode 0 +game_type 0) | |
#app_args+=(+game_alias deathmatch) | |
# or | |
#app_args+=(+game_mode 2 +game_type 1) | |
#app_args+=(+game_alias custom) | |
# or | |
#app_args+=(+game_mode 0 +game_type 3) | |
# Load a new map. | |
app_args+=(+map de_dust2) | |
# Specify a map group. | |
app_args+=(+mapgroup mg_active) | |
# Host a workshop map collection as a mapgroup | |
#app_args+=(+host_workshop_collection 2284573502) | |
# Get the latest version of the map and host it on this server. | |
#app_args+=(+host_workshop_map 125439851) | |
exec "$STEAM_APP_DIR/game/bin/linuxsteamrt64/cs2" \ | |
-dedicated \ | |
-console \ | |
-usercon \ | |
-maxplayers 32 \ | |
-port "27015" \ | |
+tv_port "27020" \ | |
+clientport "27005" \ | |
-ip "0" \ | |
"${app_args[@]}" \ | |
+exec "server.cfg" | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
- path: /home/gamemaster/steamcmd/server.cfg | |
mode: 0644 | |
contents: | |
# TODO: Adapt server.cfg. | |
inline: | | |
// Copyright (c) 2020-2024 Jakob Meng, <[email protected]> | |
// SPDX-License-Identifier: LGPL-2.1-or-later | |
// ~/steamcmd/server.cfg | |
// | |
// Counter-Strike 2 formerly known as Counter-Strike: Global Offensive | |
// | |
// Ref.: | |
// https://developer.valvesoftware.com/wiki/List_of_Counter-Strike_2_console_commands_and_variables | |
// https://totalcsgo.com/commands/server | |
// https://github.com/GameServerManagers/Game-Server-Configs/blob/master/CounterStrikeGlobalOffensive/server.cfg | |
// https://github.com/CM2Walki/CSGO/blob/master/etc/cfg.tar.gz | |
// https://github.com/bjerrecs/CSGO-Config-Templates/blob/master/csgo/cfg/server.cfg | |
// .................................. Basic ................................. // | |
// Name of the server. | |
// TODO: Define server name. | |
hostname "CS2 competitive de_dust2 mg_active" | |
// Remote console password. | |
// TODO: Define RCON password. | |
rcon_password "secret" | |
// Server password for entry into multiplayer games. | |
//sv_password "" | |
// Server is a lan server ( no heartbeat, no authentication, no non-class C addresses ) | |
sv_lan 0 | |
// Allow cheats on server. | |
sv_cheats 0 | |
// Server tags. Used to provide extra information to clients when they're browsing for servers. Separate tags with a comma. | |
sv_tags "" | |
// The region of the world to report this server in. | |
// 0 - US East, 1 - US West, 2 - South America, 3 - Europe, 4 - Asia, 5 - Australia, 6 - Middle East, 7 - Africa | |
sv_region 3 | |
// Puts the server into extremely low CPU usage mode when no clients connected | |
sv_hibernate_when_empty 1 | |
// ............................. Server Logging ............................. // | |
// Enables logging to file, console, and udp < on | off >. | |
log on | |
// Log server bans in the server logs. | |
sv_logbans 1 | |
// Display log information to the server console. | |
sv_logecho 1 | |
// Log server information in the log file. | |
sv_logfile 1 | |
// One file log - Log server information to only one file. | |
sv_log_onefile false | |
// ................................ Ban List ................................ // | |
// User ban - Server banlist based on user steam ID. | |
// Recommended: exec banned_user.cfg | |
exec banned_user.cfg | |
// IP ban - Server banlist based on user IP. | |
// Recommended: exec banned_ip.cfg | |
exec banned_ip.cfg | |
// Writes a list of permanently-banned user IDs to banned_user.cfg. | |
writeid | |
// Save the ban list to banned_ip.cfg. | |
writeip | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
links: | |
- path: /home/gamemaster/.config/systemd/user/default.target.wants/steamcmd.service | |
user: | |
name: gamemaster | |
group: | |
name: gamemaster | |
target: /home/gamemaster/.config/systemd/user/steamcmd.service | |
hard: false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment