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