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