at 23.11-pre 4.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 ts3 = pkgs.teamspeak_server; 7 cfg = config.services.teamspeak3; 8 user = "teamspeak"; 9 group = "teamspeak"; 10in 11 12{ 13 14 ###### interface 15 16 options = { 17 18 services.teamspeak3 = { 19 enable = mkOption { 20 type = types.bool; 21 default = false; 22 description = lib.mdDoc '' 23 Whether to run the Teamspeak3 voice communication server daemon. 24 ''; 25 }; 26 27 dataDir = mkOption { 28 type = types.path; 29 default = "/var/lib/teamspeak3-server"; 30 description = lib.mdDoc '' 31 Directory to store TS3 database and other state/data files. 32 ''; 33 }; 34 35 logPath = mkOption { 36 type = types.path; 37 default = "/var/log/teamspeak3-server/"; 38 description = lib.mdDoc '' 39 Directory to store log files in. 40 ''; 41 }; 42 43 voiceIP = mkOption { 44 type = types.nullOr types.str; 45 default = null; 46 example = "[::]"; 47 description = lib.mdDoc '' 48 IP on which the server instance will listen for incoming voice connections. Defaults to any IP. 49 ''; 50 }; 51 52 defaultVoicePort = mkOption { 53 type = types.int; 54 default = 9987; 55 description = lib.mdDoc '' 56 Default UDP port for clients to connect to virtual servers - used for first virtual server, subsequent ones will open on incrementing port numbers by default. 57 ''; 58 }; 59 60 fileTransferIP = mkOption { 61 type = types.nullOr types.str; 62 default = null; 63 example = "[::]"; 64 description = lib.mdDoc '' 65 IP on which the server instance will listen for incoming file transfer connections. Defaults to any IP. 66 ''; 67 }; 68 69 fileTransferPort = mkOption { 70 type = types.int; 71 default = 30033; 72 description = lib.mdDoc '' 73 TCP port opened for file transfers. 74 ''; 75 }; 76 77 queryIP = mkOption { 78 type = types.nullOr types.str; 79 default = null; 80 example = "0.0.0.0"; 81 description = lib.mdDoc '' 82 IP on which the server instance will listen for incoming ServerQuery connections. Defaults to any IP. 83 ''; 84 }; 85 86 queryPort = mkOption { 87 type = types.int; 88 default = 10011; 89 description = lib.mdDoc '' 90 TCP port opened for ServerQuery connections. 91 ''; 92 }; 93 94 openFirewall = mkOption { 95 type = types.bool; 96 default = false; 97 description = lib.mdDoc "Open ports in the firewall for the TeamSpeak3 server."; 98 }; 99 100 openFirewallServerQuery = mkOption { 101 type = types.bool; 102 default = false; 103 description = lib.mdDoc "Open ports in the firewall for the TeamSpeak3 serverquery (administration) system. Requires openFirewall."; 104 }; 105 106 }; 107 108 }; 109 110 111 ###### implementation 112 113 config = mkIf cfg.enable { 114 users.users.teamspeak = { 115 description = "Teamspeak3 voice communication server daemon"; 116 group = group; 117 uid = config.ids.uids.teamspeak; 118 home = cfg.dataDir; 119 createHome = true; 120 }; 121 122 users.groups.teamspeak = { 123 gid = config.ids.gids.teamspeak; 124 }; 125 126 systemd.tmpfiles.rules = [ 127 "d '${cfg.logPath}' - ${user} ${group} - -" 128 ]; 129 130 networking.firewall = mkIf cfg.openFirewall { 131 allowedTCPPorts = [ cfg.fileTransferPort ] ++ optionals (cfg.openFirewallServerQuery) [ cfg.queryPort (cfg.queryPort + 11) ]; 132 # subsequent vServers will use the incremented voice port, let's just open the next 10 133 allowedUDPPortRanges = [ { from = cfg.defaultVoicePort; to = cfg.defaultVoicePort + 10; } ]; 134 }; 135 136 systemd.services.teamspeak3-server = { 137 description = "Teamspeak3 voice communication server daemon"; 138 after = [ "network.target" ]; 139 wantedBy = [ "multi-user.target" ]; 140 141 serviceConfig = { 142 ExecStart = '' 143 ${ts3}/bin/ts3server \ 144 dbsqlpath=${ts3}/lib/teamspeak/sql/ logpath=${cfg.logPath} \ 145 ${optionalString (cfg.voiceIP != null) "voice_ip=${cfg.voiceIP}"} \ 146 default_voice_port=${toString cfg.defaultVoicePort} \ 147 ${optionalString (cfg.fileTransferIP != null) "filetransfer_ip=${cfg.fileTransferIP}"} \ 148 filetransfer_port=${toString cfg.fileTransferPort} \ 149 ${optionalString (cfg.queryIP != null) "query_ip=${cfg.queryIP}"} \ 150 query_port=${toString cfg.queryPort} license_accepted=1 151 ''; 152 WorkingDirectory = cfg.dataDir; 153 User = user; 154 Group = group; 155 Restart = "on-failure"; 156 }; 157 }; 158 }; 159 160 meta.maintainers = with lib.maintainers; [ arobyn ]; 161}