at 23.11-beta 3.8 kB view raw
1{ config, pkgs, lib, ... }: 2 3let 4 inherit (lib) literalMD mkEnableOption mkIf mkOption types; 5 cfg = config.services.quake3-server; 6 7 configFile = pkgs.writeText "q3ds-extra.cfg" '' 8 set net_port ${builtins.toString cfg.port} 9 10 ${cfg.extraConfig} 11 ''; 12 13 defaultBaseq3 = pkgs.requireFile rec { 14 name = "baseq3"; 15 hashMode = "recursive"; 16 sha256 = "5dd8ee09eabd45e80450f31d7a8b69b846f59738726929298d8a813ce5725ed3"; 17 message = '' 18 Unfortunately, we cannot download ${name} automatically. 19 Please purchase a legitimate copy of Quake 3 and change into the installation directory. 20 21 You can either add all relevant files to the nix-store like this: 22 mkdir /tmp/baseq3 23 cp baseq3/pak*.pk3 /tmp/baseq3 24 nix-store --add-fixed sha256 --recursive /tmp/baseq3 25 26 Alternatively you can set services.quake3-server.baseq3 to a path and copy the baseq3 directory into 27 $services.quake3-server.baseq3/.q3a/ 28 ''; 29 }; 30 31 home = pkgs.runCommand "quake3-home" {} '' 32 mkdir -p $out/.q3a/baseq3 33 34 for file in ${cfg.baseq3}/*; do 35 ln -s $file $out/.q3a/baseq3/$(basename $file) 36 done 37 38 ln -s ${configFile} $out/.q3a/baseq3/nix.cfg 39 ''; 40in { 41 options = { 42 services.quake3-server = { 43 enable = mkEnableOption (lib.mdDoc "Quake 3 dedicated server"); 44 package = lib.mkPackageOptionMD pkgs "ioquake3" { }; 45 46 port = mkOption { 47 type = types.port; 48 default = 27960; 49 description = lib.mdDoc '' 50 UDP Port the server should listen on. 51 ''; 52 }; 53 54 openFirewall = mkOption { 55 type = types.bool; 56 default = false; 57 description = lib.mdDoc '' 58 Open the firewall. 59 ''; 60 }; 61 62 extraConfig = mkOption { 63 type = types.lines; 64 default = ""; 65 example = '' 66 seta rconPassword "superSecret" // sets RCON password for remote console 67 seta sv_hostname "My Quake 3 server" // name that appears in server list 68 ''; 69 description = lib.mdDoc '' 70 Extra configuration options. Note that options changed via RCON will not be persisted. To list all possible 71 options, use "cvarlist 1" via RCON. 72 ''; 73 }; 74 75 baseq3 = mkOption { 76 type = types.either types.package types.path; 77 default = defaultBaseq3; 78 defaultText = literalMD "Manually downloaded Quake 3 installation directory."; 79 example = "/var/lib/q3ds"; 80 description = lib.mdDoc '' 81 Path to the baseq3 files (pak*.pk3). If this is on the nix store (type = package) all .pk3 files should be saved 82 in the top-level directory. If this is on another filesystem (e.g /var/lib/baseq3) the .pk3 files are searched in 83 $baseq3/.q3a/baseq3/ 84 ''; 85 }; 86 }; 87 }; 88 89 config = let 90 baseq3InStore = builtins.typeOf cfg.baseq3 == "set"; 91 in mkIf cfg.enable { 92 networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [ cfg.port ]; 93 94 systemd.services.q3ds = { 95 description = "Quake 3 dedicated server"; 96 wantedBy = [ "multi-user.target" ]; 97 after = [ "networking.target" ]; 98 99 environment.HOME = if baseq3InStore then home else cfg.baseq3; 100 101 serviceConfig = with lib; { 102 Restart = "always"; 103 DynamicUser = true; 104 WorkingDirectory = home; 105 106 # It is possible to alter configuration files via RCON. To ensure reproducibility we have to prevent this 107 ReadOnlyPaths = if baseq3InStore then home else cfg.baseq3; 108 ExecStartPre = optionalString (!baseq3InStore) "+${pkgs.coreutils}/bin/cp ${configFile} ${cfg.baseq3}/.q3a/baseq3/nix.cfg"; 109 110 ExecStart = "${cfg.package}/bin/ioq3ded +exec nix.cfg"; 111 }; 112 }; 113 }; 114 115 meta.maintainers = with lib.maintainers; [ f4814n ]; 116}