at 25.11-pre 8.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfgs = config.services; 9 cfg = cfgs.ncdns; 10 11 dataDir = "/var/lib/ncdns"; 12 13 format = pkgs.formats.toml { }; 14 15 defaultFiles = { 16 public = "${dataDir}/bit.key"; 17 private = "${dataDir}/bit.private"; 18 zonePublic = "${dataDir}/bit-zone.key"; 19 zonePrivate = "${dataDir}/bit-zone.private"; 20 }; 21 22 # if all keys are the default value 23 needsKeygen = lib.all lib.id ( 24 lib.flip lib.mapAttrsToList cfg.dnssec.keys (n: v: v == lib.getAttr n defaultFiles) 25 ); 26 27 mkDefaultAttrs = lib.mapAttrs (_n: v: lib.mkDefault v); 28 29in 30 31{ 32 33 ###### interface 34 35 options = { 36 37 services.ncdns = { 38 39 enable = lib.mkEnableOption '' 40 ncdns, a Go daemon to bridge Namecoin to DNS. 41 To resolve .bit domains set `services.namecoind.enable = true;` 42 and an RPC username/password 43 ''; 44 45 address = lib.mkOption { 46 type = lib.types.str; 47 default = "[::1]"; 48 description = '' 49 The IP address the ncdns resolver will bind to. Leave this unchanged 50 if you do not wish to directly expose the resolver. 51 ''; 52 }; 53 54 port = lib.mkOption { 55 type = lib.types.port; 56 default = 5333; 57 description = '' 58 The port the ncdns resolver will bind to. 59 ''; 60 }; 61 62 identity.hostname = lib.mkOption { 63 type = lib.types.str; 64 default = config.networking.hostName; 65 defaultText = lib.literalExpression "config.networking.hostName"; 66 example = "example.com"; 67 description = '' 68 The hostname of this ncdns instance, which defaults to the machine 69 hostname. If specified, ncdns lists the hostname as an NS record at 70 the zone apex: 71 ``` 72 bit. IN NS ns1.example.com. 73 ``` 74 If unset ncdns will generate an internal pseudo-hostname under the 75 zone, which will resolve to the value of 76 {option}`services.ncdns.identity.address`. 77 If you are only using ncdns locally you can ignore this. 78 ''; 79 }; 80 81 identity.hostmaster = lib.mkOption { 82 type = lib.types.str; 83 default = ""; 84 example = "root@example.com"; 85 description = '' 86 An email address for the SOA record at the bit zone. 87 If you are only using ncdns locally you can ignore this. 88 ''; 89 }; 90 91 identity.address = lib.mkOption { 92 type = lib.types.str; 93 default = "127.127.127.127"; 94 description = '' 95 The IP address the hostname specified in 96 {option}`services.ncdns.identity.hostname` should resolve to. 97 If you are only using ncdns locally you can ignore this. 98 ''; 99 }; 100 101 dnssec.enable = lib.mkEnableOption '' 102 DNSSEC support in ncdns. This will generate KSK and ZSK keypairs 103 (unless provided via the options 104 {option}`services.ncdns.dnssec.publicKey`, 105 {option}`services.ncdns.dnssec.privateKey` etc.) and add a trust 106 anchor to recursive resolvers 107 ''; 108 109 dnssec.keys.public = lib.mkOption { 110 type = lib.types.path; 111 default = defaultFiles.public; 112 description = '' 113 Path to the file containing the KSK public key. 114 The key can be generated using the `dnssec-keygen` 115 command, provided by the package `bind` as follows: 116 ``` 117 $ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit 118 ``` 119 ''; 120 }; 121 122 dnssec.keys.private = lib.mkOption { 123 type = lib.types.path; 124 default = defaultFiles.private; 125 description = '' 126 Path to the file containing the KSK private key. 127 ''; 128 }; 129 130 dnssec.keys.zonePublic = lib.mkOption { 131 type = lib.types.path; 132 default = defaultFiles.zonePublic; 133 description = '' 134 Path to the file containing the ZSK public key. 135 The key can be generated using the `dnssec-keygen` 136 command, provided by the package `bind` as follows: 137 ``` 138 $ dnssec-keygen -a RSASHA256 -3 -b 2048 bit 139 ``` 140 ''; 141 }; 142 143 dnssec.keys.zonePrivate = lib.mkOption { 144 type = lib.types.path; 145 default = defaultFiles.zonePrivate; 146 description = '' 147 Path to the file containing the ZSK private key. 148 ''; 149 }; 150 151 settings = lib.mkOption { 152 type = format.type; 153 default = { }; 154 example = lib.literalExpression '' 155 { # enable webserver 156 ncdns.httplistenaddr = ":8202"; 157 158 # synchronize TLS certs 159 certstore.nss = true; 160 # note: all paths are relative to the config file 161 certstore.nsscertdir = "../../var/lib/ncdns"; 162 certstore.nssdbdir = "../../home/alice/.pki/nssdb"; 163 } 164 ''; 165 description = '' 166 ncdns settings. Use this option to configure ncds 167 settings not exposed in a NixOS option or to bypass one. 168 See the example ncdns.conf file at <https://github.com/namecoin/ncdns/blob/master/_doc/ncdns.conf.example> 169 for the available options. 170 ''; 171 }; 172 173 }; 174 175 services.pdns-recursor.resolveNamecoin = lib.mkOption { 176 type = lib.types.bool; 177 default = false; 178 description = '' 179 Resolve `.bit` top-level domains using ncdns and namecoin. 180 ''; 181 }; 182 183 }; 184 185 ###### implementation 186 187 config = lib.mkIf cfg.enable { 188 189 services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin { 190 forwardZonesRecurse.bit = "${cfg.address}:${toString cfg.port}"; 191 luaConfig = 192 if cfg.dnssec.enable then 193 ''readTrustAnchorsFromFile("${cfg.dnssec.keys.public}")'' 194 else 195 ''addNTA("bit", "namecoin DNSSEC disabled")''; 196 }; 197 198 # Avoid pdns-recursor not finding the DNSSEC keys 199 systemd.services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin { 200 after = [ "ncdns.service" ]; 201 wants = [ "ncdns.service" ]; 202 }; 203 204 services.ncdns.settings = mkDefaultAttrs { 205 ncdns = 206 { 207 # Namecoin RPC 208 namecoinrpcaddress = "${cfgs.namecoind.rpc.address}:${toString cfgs.namecoind.rpc.port}"; 209 namecoinrpcusername = cfgs.namecoind.rpc.user; 210 namecoinrpcpassword = cfgs.namecoind.rpc.password; 211 212 # Identity 213 selfname = cfg.identity.hostname; 214 hostmaster = cfg.identity.hostmaster; 215 selfip = cfg.identity.address; 216 217 # Other 218 bind = "${cfg.address}:${toString cfg.port}"; 219 } 220 // lib.optionalAttrs cfg.dnssec.enable { 221 # DNSSEC 222 publickey = "../.." + cfg.dnssec.keys.public; 223 privatekey = "../.." + cfg.dnssec.keys.private; 224 zonepublickey = "../.." + cfg.dnssec.keys.zonePublic; 225 zoneprivatekey = "../.." + cfg.dnssec.keys.zonePrivate; 226 }; 227 228 # Daemon 229 service.daemon = true; 230 xlog.journal = true; 231 }; 232 233 users.users.ncdns = { 234 isSystemUser = true; 235 group = "ncdns"; 236 description = "ncdns daemon user"; 237 }; 238 users.groups.ncdns = { }; 239 240 systemd.services.ncdns = { 241 description = "ncdns daemon"; 242 after = [ "namecoind.service" ]; 243 wantedBy = [ "multi-user.target" ]; 244 245 serviceConfig = { 246 User = "ncdns"; 247 StateDirectory = "ncdns"; 248 Restart = "on-failure"; 249 ExecStart = "${pkgs.ncdns}/bin/ncdns -conf=${format.generate "ncdns.conf" cfg.settings}"; 250 }; 251 252 preStart = lib.optionalString (cfg.dnssec.enable && needsKeygen) '' 253 cd ${dataDir} 254 if [ ! -e bit.key ]; then 255 ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 bit 256 mv Kbit.*.key bit-zone.key 257 mv Kbit.*.private bit-zone.private 258 ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit 259 mv Kbit.*.key bit.key 260 mv Kbit.*.private bit.private 261 fi 262 ''; 263 }; 264 265 }; 266 267 meta.maintainers = with lib.maintainers; [ rnhmjoj ]; 268 269}