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