Compare commits

...
6 Commits
Author SHA1 Message Date
blake 1c5c21612a enable dns and update ip address 2026-06-12 23:54:04 -05:00
blake 01e420aa8d enable dns and update ip address 2026-06-12 23:54:04 -05:00
blake a422358acd source dedicated server shenangans 2026-06-12 23:54:04 -05:00
blake d5f619ce4d add srcds 2026-06-12 23:54:04 -05:00
blake 981a7b0c4a add cs2 server 2026-06-12 23:54:04 -05:00
blake 6509775612 add cs2 server 2026-06-12 23:54:04 -05:00
8 changed files with 363 additions and 27 deletions
Generated
+58 -1
View File
@@ -257,7 +257,7 @@
}, },
"fenix": { "fenix": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_4",
"rust-analyzer-src": "rust-analyzer-src" "rust-analyzer-src": "rust-analyzer-src"
}, },
"locked": { "locked": {
@@ -907,6 +907,22 @@
} }
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": {
"lastModified": 1739419412,
"narHash": "sha256-NCWZQg4DbYVFWg+MOFrxWRaVsLA7yvRWAf6o0xPR1hI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2d55b4c1531187926c2a423f6940b3b1301399b5",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1677063315, "lastModified": 1677063315,
"narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=", "narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=",
@@ -1137,6 +1153,7 @@
"nvf": "nvf", "nvf": "nvf",
"slippi": "slippi", "slippi": "slippi",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"srcds-nix": "srcds-nix",
"stylix": "stylix", "stylix": "stylix",
"vpn-confinement": "vpn-confinement", "vpn-confinement": "vpn-confinement",
"watershot": "watershot" "watershot": "watershot"
@@ -1253,6 +1270,25 @@
"type": "github" "type": "github"
} }
}, },
"srcds-nix": {
"inputs": {
"nixpkgs": "nixpkgs_3",
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1739576881,
"narHash": "sha256-zudD0ycB1cOwvqFBlAwSKwjO9cZir2qzA4f43ixNYCQ=",
"owner": "ihaveamac",
"repo": "srcds-nix",
"rev": "ad8a719fa97b26dfc0b3b6f0ba0f468036c549e1",
"type": "github"
},
"original": {
"owner": "ihaveamac",
"repo": "srcds-nix",
"type": "github"
}
},
"std": { "std": {
"inputs": { "inputs": {
"arion": [ "arion": [
@@ -1427,6 +1463,27 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"srcds-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1738953846,
"narHash": "sha256-yrK3Hjcr8F7qS/j2F+r7C7o010eVWWlm4T1PrbKBOxQ=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "4f09b473c936d41582dd744e19f34ec27592c5fd",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"vpn-confinement": { "vpn-confinement": {
"locked": { "locked": {
"lastModified": 1778182451, "lastModified": 1778182451,
+1
View File
@@ -61,6 +61,7 @@
url = "github:lytedev/slippi-nix"; url = "github:lytedev/slippi-nix";
inputs.nixpkgs.follows = "nixpkgs-unstable"; inputs.nixpkgs.follows = "nixpkgs-unstable";
}; };
srcds-nix.url = "github:ihaveamac/srcds-nix";
}; };
outputs = { outputs = {
self, self,
+5 -5
View File
@@ -17,7 +17,7 @@
../../../modules/system ../../../modules/system
../../../modules/fileshares/holocron_new ../../../modules/fileshares/holocron_new
../../../modules/homelab ../../../modules/homelab
../../../modules/gameservers/cs2 #../../../modules/gameservers/srcds
#../../../modules/gameservers/minecraft_recpro #../../../modules/gameservers/minecraft_recpro
#../../../modules/gameservers/minecraft_modded #../../../modules/gameservers/minecraft_modded
]; ];
@@ -59,7 +59,7 @@
# network # network
tailscale.enable = true; tailscale.enable = true;
caddy.enable = true; caddy.enable = true;
dnsmasq.enable = false; dnsmasq.enable = true;
# mediastack # mediastack
mediastack.enable = true; mediastack.enable = true;
qbittorrent.vpn_inf = "enp34s0.69"; qbittorrent.vpn_inf = "enp34s0.69";
@@ -83,9 +83,9 @@
nfs.enable = true; nfs.enable = true;
}; };
gameservers = { # gameservers = {
cs2.enable = true; # srcds.enable = true;
}; # };
# boot (systemd is going on me) # boot (systemd is going on me)
boot.loader.systemd-boot.enable = true; # systemd your pretty cool ya know boot.loader.systemd-boot.enable = true; # systemd your pretty cool ya know
@@ -34,7 +34,7 @@ in {
autodetect = true; autodetect = true;
defaults.monitored = "-a -o on -s (S/../.././05|L/../01/./05)"; defaults.monitored = "-a -o on -s (S/../.././05|L/../01/./05)";
notifications = { notifications = {
test = true; test = false;
mail = { mail = {
enable = true; enable = true;
recipient = "blake"; recipient = "blake";
+21 -19
View File
@@ -17,6 +17,10 @@ in {
type = lib.types.int; type = lib.types.int;
default = 27015; default = 27015;
}; };
tv_port = lib.mkOption {
type = lib.types.int;
default = 27016;
};
hostname = lib.mkOption { hostname = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "recoil.pro CS2"; default = "recoil.pro CS2";
@@ -25,7 +29,7 @@ in {
type = lib.types.str; type = lib.types.str;
default = "de_dust2"; default = "de_dust2";
}; };
maxPlayers = lib.mkOption { max_players = lib.mkOption {
type = lib.types.int; type = lib.types.int;
default = 10; default = 10;
}; };
@@ -51,6 +55,8 @@ in {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
steamcmd steamcmd
steam-run
rcon
]; ];
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
@@ -61,8 +67,7 @@ in {
environment.etc."cs2/server.cfg".text = '' environment.etc."cs2/server.cfg".text = ''
hostname "${cfg.hostname}" hostname "${cfg.hostname}"
sv_lan 0 sv_lan 0
sv_visiblemaxplayers ${toString cfg.maxPlayers} rcon_password "$(<${config.sops.secrets."cs2/rcon".path})"
rcon_password "$(<${config.sops.secrets.cs2-rcon.path})"
mp_autoteambalance 1 mp_autoteambalance 1
mp_limitteams 2 mp_limitteams 2
''; '';
@@ -95,22 +100,30 @@ in {
serviceConfig = { serviceConfig = {
User = "cs2"; User = "cs2";
Group = "cs2"; Group = "cs2";
WorkingDirectory = "${cfg.data_dir}/server/game/bin/linuxsteamrt64"; WorkingDirectory = "${cfg.data_dir}";
Restart = "always"; Restart = "always";
ExecStart = pkgs.writeShellScript "cs2-start" '' ExecStart = pkgs.writeShellScript "cs2-start" ''
export GSLT=$(cat ${config.sops.secrets."cs2/gslt".path}) export GSLT=$(cat ${config.sops.secrets."cs2/gslt".path})
exec ./cs2.sh \ exec ${pkgs.steam-run}/bin/steam-run -- \
${cfg.data_dir}/server/game/bin/linuxsteamrt64/cs2 \
-dedicated \ -dedicated \
-usercon \ -usercon \
-console \
-port ${toString cfg.port} \
-tv_port ${toString cfg.tv_port} \
-maxplayers_override ${toString cfg.max_players} \
+game_type 0 \
+game_mode 1 \
+mapgroup mg_active \
+map ${cfg.map} \ +map ${cfg.map} \
+sv_setsteamaccount "$GSLT" \ +sv_setsteamaccount "$GSLT" \
+exec server.cfg +exec /etc/gameserver/cs2/server.cfg
''; '';
}; };
}; };
networking.firewall.allowedTCPPorts = [cfg.port]; networking.firewall.allowedTCPPorts = [cfg.port cfg.tv_port];
networking.firewall.allowedUDPPorts = [cfg.port]; networking.firewall.allowedUDPPorts = [cfg.port cfg.tv_port];
# backups cs2 server with borg! # backups cs2 server with borg!
services.borgbackup.jobs.${service} = { services.borgbackup.jobs.${service} = {
@@ -134,17 +147,6 @@ in {
}; };
}; };
sops.secrets = {
cs2-gslt = {
owner = "cs2";
group = "cs2";
};
cs2-rcon = {
owner = "cs2";
group = "cs2";
};
};
# manage secrets with sops # manage secrets with sops
sops.secrets = { sops.secrets = {
"${service}/gslt" = { "${service}/gslt" = {
+162
View File
@@ -0,0 +1,162 @@
{
pkgs,
config,
lib,
...
}: let
service = "cs2";
cfg = config.gameservers.${service};
in {
options.gameservers.${service} = {
enable = lib.mkEnableOption "Counter Strike 2 server";
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/gameservers/cs2";
};
port = lib.mkOption {
type = lib.types.int;
default = 27015;
};
tv_port = lib.mkOption {
type = lib.types.int;
default = 27016;
};
hostname = lib.mkOption {
type = lib.types.str;
default = "recoil.pro CS2";
};
map = lib.mkOption {
type = lib.types.str;
default = "de_dust2";
};
max_players = lib.mkOption {
type = lib.types.int;
default = 10;
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
};
backup_repo = lib.mkOption {
type = lib.types.path;
default = "/holocron/archives/gameservers/cs2";
};
};
config = lib.mkIf cfg.enable {
users.users.cs2 = {
isSystemUser = true;
group = "cs2";
home = cfg.data_dir;
createHome = true;
};
users.groups.cs2 = {};
environment.systemPackages = with pkgs; [
steamcmd
steam-run
rcon
];
systemd.tmpfiles.rules = [
"d ${cfg.data_dir} 0770 cs2 cs2 -"
"d ${cfg.data_dir}/server 0770 cs2 cs2 -"
];
environment.etc."cs2/server.cfg".text = ''
hostname "${cfg.hostname}"
sv_lan 0
rcon_password "$(<${config.sops.secrets."cs2/rcon".path})"
mp_autoteambalance 1
mp_limitteams 2
'';
systemd.services.cs2-update = {
description = "Update CS2 server";
serviceConfig = {
Type = "oneshot";
User = "cs2";
};
script = ''
${pkgs.steamcmd}/bin/steamcmd \
+force_install_dir ${cfg.data_dir}/server \
+login anonymous \
+app_update 730 validate \
+quit
'';
};
systemd.services.cs2-server = {
description = "Counter Strike 2 Dedicated Server";
after = [
"network.target"
"cs2-update.service"
];
requires = [
"cs2-update.service"
];
wantedBy = ["multi-user.target"];
serviceConfig = {
User = "cs2";
Group = "cs2";
WorkingDirectory = "${cfg.data_dir}/server";
Restart = "always";
ExecStart = pkgs.writeShellScript "cs2-start" ''
export GSLT=$(cat ${config.sops.secrets."cs2/gslt".path})
exec ${pkgs.steam-run}/bin/steam-run -- \
${cfg.data_dir}/server/game/cs2.sh \
-dedicated \
-usercon \
-console \
-port ${toString cfg.port} \
-tv_port ${toString cfg.tv_port} \
-maxplayers_override ${toString cfg.max_players} \
+game_type 0 \
+game_mode 1 \
+mapgroup mg_active \
+map ${cfg.map} \
+sv_setsteamaccount "$GSLT" \
+exec /etc/gameserver/cs2/server.cfg
'';
};
};
networking.firewall.allowedTCPPorts = [cfg.port cfg.tv_port];
networking.firewall.allowedUDPPorts = [cfg.port cfg.tv_port];
# backups cs2 server with borg!
services.borgbackup.jobs.${service} = {
archiveBaseName = service;
repo = cfg.backup_repo;
paths = cfg.data_dir;
compression = "auto,zstd";
#preHook = "systemctl start mysql-backup.service";
startAt = "*-*-* *:00:00";
group = "archives";
encryption.mode = "repokey-blake2";
encryption.passCommand = "cat ${config.sops.secrets."borg_passwd".path}";
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
prune.keep = {
within = "1d"; # Keep all archives from the last day
hourly = 24;
daily = 7;
weekly = 12;
monthly = -1; # Keep at least one archive for each month
};
};
# manage secrets with sops
sops.secrets = {
"${service}/gslt" = {
owner = service;
group = service;
};
"${service}/rcon" = {
owner = service;
group = service;
};
};
};
}
+114
View File
@@ -0,0 +1,114 @@
{
pkgs,
config,
lib,
inputs,
...
}: let
service = "srcds";
cfg = config.gameservers.${service};
in {
imports = [inputs.srcds-nix.nixosModules.default];
options.gameservers.${service} = {
enable = lib.mkEnableOption "Counter Strike 2 server";
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/gameservers/cs2";
};
port = lib.mkOption {
type = lib.types.int;
default = 27015;
};
tv_port = lib.mkOption {
type = lib.types.int;
default = 27016;
};
hostname = lib.mkOption {
type = lib.types.str;
default = "recoil.pro CS2";
};
map = lib.mkOption {
type = lib.types.str;
default = "de_dust2";
};
max_players = lib.mkOption {
type = lib.types.int;
default = 10;
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
};
backup_repo = lib.mkOption {
type = lib.types.path;
default = "/holocron/archives/gameservers/cs2";
};
};
config = lib.mkIf cfg.enable {
users.users.cs2 = {
isSystemUser = true;
group = "cs2";
home = cfg.data_dir;
createHome = true;
};
users.groups.cs2 = {};
services.srcds = {
enable = true;
openFirewall = true;
games = {
cs2-server = {
appId = 730;
gamePort = cfg.port;
rcon = {
enable = true;
password = "secretpass";
};
extraArgs = [];
startingMap = cfg.map;
};
};
};
environment.systemPackages = with pkgs; [
rcon
];
# backups cs2 server with borg!
services.borgbackup.jobs.${service} = {
archiveBaseName = service;
repo = cfg.backup_repo;
paths = cfg.data_dir;
compression = "auto,zstd";
#preHook = "systemctl start mysql-backup.service";
startAt = "*-*-* *:00:00";
group = "archives";
encryption.mode = "repokey-blake2";
encryption.passCommand = "cat ${config.sops.secrets."borg_passwd".path}";
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
prune.keep = {
within = "1d"; # Keep all archives from the last day
hourly = 24;
daily = 7;
weekly = 12;
monthly = -1; # Keep at least one archive for each month
};
};
# manage secrets with sops
sops.secrets = {
"${service}/gslt" = {
owner = service;
group = service;
};
"${service}/rcon" = {
owner = service;
group = service;
};
};
};
}
+1 -1
View File
@@ -25,7 +25,7 @@ in {
alwaysKeepRunning = true; alwaysKeepRunning = true;
settings = { settings = {
no-resolv = true; no-resolv = true;
listen-address = "10.10.0.10"; # your LAN IP listen-address = "10.10.0.11"; # your LAN IP
#interface = "enp89s0"; #interface = "enp89s0";
bind-interfaces = true; bind-interfaces = true;
# address = [ # address = [