at master 6.3 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 12 inherit (pkgs) nntp-proxy; 13 14 cfg = config.services.nntp-proxy; 15 16 configBool = b: if b then "TRUE" else "FALSE"; 17 18 confFile = pkgs.writeText "nntp-proxy.conf" '' 19 nntp_server: 20 { 21 # NNTP Server host and port address 22 server = "${cfg.upstreamServer}"; 23 port = ${toString cfg.upstreamPort}; 24 # NNTP username 25 username = "${cfg.upstreamUser}"; 26 # NNTP password in clear text 27 password = "${cfg.upstreamPassword}"; 28 # Maximum number of connections allowed by the NNTP 29 max_connections = ${toString cfg.upstreamMaxConnections}; 30 }; 31 32 proxy: 33 { 34 # Local address and port to bind to 35 bind_ip = "${cfg.listenAddress}"; 36 bind_port = ${toString cfg.port}; 37 38 # SSL key and cert file 39 ssl_key = "${cfg.sslKey}"; 40 ssl_cert = "${cfg.sslCert}"; 41 42 # prohibit users from posting 43 prohibit_posting = ${configBool cfg.prohibitPosting}; 44 # Verbose levels: ERROR, WARNING, NOTICE, INFO, DEBUG 45 verbose = "${toUpper cfg.verbosity}"; 46 # Password is made with: 'mkpasswd -m sha-512 <password>' 47 users = (${ 48 concatStringsSep ",\n" ( 49 mapAttrsToList (username: userConfig: '' 50 { 51 username = "${username}"; 52 password = "${userConfig.passwordHash}"; 53 max_connections = ${toString userConfig.maxConnections}; 54 } 55 '') cfg.users 56 ) 57 }); 58 }; 59 ''; 60 61in 62 63{ 64 65 ###### interface 66 67 options = { 68 69 services.nntp-proxy = { 70 enable = mkEnableOption "NNTP-Proxy"; 71 72 upstreamServer = mkOption { 73 type = types.str; 74 default = ""; 75 example = "ssl-eu.astraweb.com"; 76 description = '' 77 Upstream server address 78 ''; 79 }; 80 81 upstreamPort = mkOption { 82 type = types.port; 83 default = 563; 84 description = '' 85 Upstream server port 86 ''; 87 }; 88 89 upstreamMaxConnections = mkOption { 90 type = types.int; 91 default = 20; 92 description = '' 93 Upstream server maximum allowed concurrent connections 94 ''; 95 }; 96 97 upstreamUser = mkOption { 98 type = types.str; 99 default = ""; 100 description = '' 101 Upstream server username 102 ''; 103 }; 104 105 upstreamPassword = mkOption { 106 type = types.str; 107 default = ""; 108 description = '' 109 Upstream server password 110 ''; 111 }; 112 113 listenAddress = mkOption { 114 type = types.str; 115 default = "127.0.0.1"; 116 example = "[::]"; 117 description = '' 118 Proxy listen address (IPv6 literal addresses need to be enclosed in "[" and "]" characters) 119 ''; 120 }; 121 122 port = mkOption { 123 type = types.port; 124 default = 5555; 125 description = '' 126 Proxy listen port 127 ''; 128 }; 129 130 sslKey = mkOption { 131 type = types.str; 132 default = "key.pem"; 133 example = "/path/to/your/key.file"; 134 description = '' 135 Proxy ssl key path 136 ''; 137 }; 138 139 sslCert = mkOption { 140 type = types.str; 141 default = "cert.pem"; 142 example = "/path/to/your/cert.file"; 143 description = '' 144 Proxy ssl certificate path 145 ''; 146 }; 147 148 prohibitPosting = mkOption { 149 type = types.bool; 150 default = true; 151 description = '' 152 Whether to prohibit posting to the upstream server 153 ''; 154 }; 155 156 verbosity = mkOption { 157 type = types.enum [ 158 "error" 159 "warning" 160 "notice" 161 "info" 162 "debug" 163 ]; 164 default = "info"; 165 example = "error"; 166 description = '' 167 Verbosity level 168 ''; 169 }; 170 171 users = mkOption { 172 type = types.attrsOf ( 173 types.submodule { 174 options = { 175 username = mkOption { 176 type = types.str; 177 description = '' 178 Username 179 ''; 180 }; 181 182 passwordHash = mkOption { 183 type = types.str; 184 example = "$6$GtzE7FrpE$wwuVgFYU.TZH4Rz.Snjxk9XGua89IeVwPQ/fEUD8eujr40q5Y021yhn0aNcsQ2Ifw.BLclyzvzgegopgKcneL0"; 185 description = '' 186 SHA-512 password hash (can be generated by 187 `mkpasswd -m sha-512 <password>`) 188 ''; 189 }; 190 191 maxConnections = mkOption { 192 type = types.int; 193 default = 1; 194 description = '' 195 Maximum number of concurrent connections to the proxy for this user 196 ''; 197 }; 198 }; 199 } 200 ); 201 description = '' 202 NNTP-Proxy user configuration 203 ''; 204 205 default = { }; 206 example = literalExpression '' 207 { 208 "user1" = { 209 passwordHash = "$6$1l0t5Kn2Dk$appzivc./9l/kjq57eg5UCsBKlcfyCr0zNWYNerKoPsI1d7eAwiT0SVsOVx/CTgaBNT/u4fi2vN.iGlPfv1ek0"; 210 maxConnections = 5; 211 }; 212 "anotheruser" = { 213 passwordHash = "$6$6lwEsWB.TmsS$W7m1riUx4QrA8pKJz8hvff0dnF1NwtZXgdjmGqA1Dx2MDPj07tI9GNcb0SWlMglE.2/hBgynDdAd/XqqtRqVQ0"; 214 maxConnections = 7; 215 }; 216 } 217 ''; 218 }; 219 }; 220 221 }; 222 223 ###### implementation 224 225 config = mkIf cfg.enable { 226 227 users.users.nntp-proxy = { 228 isSystemUser = true; 229 group = "nntp-proxy"; 230 description = "NNTP-Proxy daemon user"; 231 }; 232 users.groups.nntp-proxy = { }; 233 234 systemd.services.nntp-proxy = { 235 description = "NNTP proxy"; 236 after = [ 237 "network.target" 238 "nss-lookup.target" 239 ]; 240 wantedBy = [ "multi-user.target" ]; 241 serviceConfig = { 242 User = "nntp-proxy"; 243 }; 244 serviceConfig.ExecStart = "${nntp-proxy}/bin/nntp-proxy ${confFile}"; 245 preStart = '' 246 if [ ! \( -f ${cfg.sslCert} -a -f ${cfg.sslKey} \) ]; then 247 ${pkgs.openssl.bin}/bin/openssl req -subj '/CN=AutoGeneratedCert/O=NixOS Service/C=US' \ 248 -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout ${cfg.sslKey} -out ${cfg.sslCert}; 249 fi 250 ''; 251 }; 252 253 }; 254 255}