1 { config, lib, pkgs, ... }:
3 cfgs = config.services;
6 dataDir = "/var/lib/ncdns";
9 valueType = with lib.types; oneOf [ int str bool path ]
10 // { description = "setting type (integer, string, bool or path)"; };
12 configType = with lib.types; attrsOf (nullOr (either valueType configType))
14 ncdns.conf configuration type. The format consists of an
15 attribute set of settings. Each setting can be either `null`,
16 a value or an attribute set. The allowed values are integers,
17 strings, booleans or paths.
21 configFile = pkgs.runCommand "ncdns.conf"
22 { json = builtins.toJSON cfg.settings;
23 passAsFile = [ "json" ];
25 "${pkgs.remarshal}/bin/json2toml < $jsonPath > $out";
28 public = "${dataDir}/bit.key";
29 private = "${dataDir}/bit.private";
30 zonePublic = "${dataDir}/bit-zone.key";
31 zonePrivate = "${dataDir}/bit-zone.private";
34 # if all keys are the default value
35 needsKeygen = lib.all lib.id (lib.flip lib.mapAttrsToList cfg.dnssec.keys
36 (n: v: v == lib.getAttr n defaultFiles));
38 mkDefaultAttrs = lib.mapAttrs (n: v: lib.mkDefault v);
50 enable = lib.mkEnableOption ''
51 ncdns, a Go daemon to bridge Namecoin to DNS.
52 To resolve .bit domains set `services.namecoind.enable = true;`
53 and an RPC username/password
56 address = lib.mkOption {
60 The IP address the ncdns resolver will bind to. Leave this unchanged
61 if you do not wish to directly expose the resolver.
66 type = lib.types.port;
69 The port the ncdns resolver will bind to.
73 identity.hostname = lib.mkOption {
75 default = config.networking.hostName;
76 defaultText = lib.literalExpression "config.networking.hostName";
77 example = "example.com";
79 The hostname of this ncdns instance, which defaults to the machine
80 hostname. If specified, ncdns lists the hostname as an NS record at
83 bit. IN NS ns1.example.com.
85 If unset ncdns will generate an internal pseudo-hostname under the
86 zone, which will resolve to the value of
87 {option}`services.ncdns.identity.address`.
88 If you are only using ncdns locally you can ignore this.
92 identity.hostmaster = lib.mkOption {
95 example = "root@example.com";
97 An email address for the SOA record at the bit zone.
98 If you are only using ncdns locally you can ignore this.
102 identity.address = lib.mkOption {
103 type = lib.types.str;
104 default = "127.127.127.127";
106 The IP address the hostname specified in
107 {option}`services.ncdns.identity.hostname` should resolve to.
108 If you are only using ncdns locally you can ignore this.
112 dnssec.enable = lib.mkEnableOption ''
113 DNSSEC support in ncdns. This will generate KSK and ZSK keypairs
114 (unless provided via the options
115 {option}`services.ncdns.dnssec.publicKey`,
116 {option}`services.ncdns.dnssec.privateKey` etc.) and add a trust
117 anchor to recursive resolvers
120 dnssec.keys.public = lib.mkOption {
121 type = lib.types.path;
122 default = defaultFiles.public;
124 Path to the file containing the KSK public key.
125 The key can be generated using the `dnssec-keygen`
126 command, provided by the package `bind` as follows:
128 $ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
133 dnssec.keys.private = lib.mkOption {
134 type = lib.types.path;
135 default = defaultFiles.private;
137 Path to the file containing the KSK private key.
141 dnssec.keys.zonePublic = lib.mkOption {
142 type = lib.types.path;
143 default = defaultFiles.zonePublic;
145 Path to the file containing the ZSK public key.
146 The key can be generated using the `dnssec-keygen`
147 command, provided by the package `bind` as follows:
149 $ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
154 dnssec.keys.zonePrivate = lib.mkOption {
155 type = lib.types.path;
156 default = defaultFiles.zonePrivate;
158 Path to the file containing the ZSK private key.
162 settings = lib.mkOption {
165 example = lib.literalExpression ''
167 ncdns.httplistenaddr = ":8202";
169 # synchronize TLS certs
170 certstore.nss = true;
171 # note: all paths are relative to the config file
172 certstore.nsscertdir = "../../var/lib/ncdns";
173 certstore.nssdbdir = "../../home/alice/.pki/nssdb";
177 ncdns settings. Use this option to configure ncds
178 settings not exposed in a NixOS option or to bypass one.
179 See the example ncdns.conf file at <https://github.com/namecoin/ncdns/blob/master/_doc/ncdns.conf.example>
180 for the available options.
186 services.pdns-recursor.resolveNamecoin = lib.mkOption {
187 type = lib.types.bool;
190 Resolve `.bit` top-level domains using ncdns and namecoin.
197 ###### implementation
199 config = lib.mkIf cfg.enable {
201 services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin {
202 forwardZonesRecurse.bit = "${cfg.address}:${toString cfg.port}";
205 then ''readTrustAnchorsFromFile("${cfg.dnssec.keys.public}")''
206 else ''addNTA("bit", "namecoin DNSSEC disabled")'';
209 # Avoid pdns-recursor not finding the DNSSEC keys
210 systemd.services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin {
211 after = [ "ncdns.service" ];
212 wants = [ "ncdns.service" ];
215 services.ncdns.settings = mkDefaultAttrs {
219 "${cfgs.namecoind.rpc.address}:${toString cfgs.namecoind.rpc.port}";
220 namecoinrpcusername = cfgs.namecoind.rpc.user;
221 namecoinrpcpassword = cfgs.namecoind.rpc.password;
224 selfname = cfg.identity.hostname;
225 hostmaster = cfg.identity.hostmaster;
226 selfip = cfg.identity.address;
229 bind = "${cfg.address}:${toString cfg.port}";
231 // lib.optionalAttrs cfg.dnssec.enable
233 publickey = "../.." + cfg.dnssec.keys.public;
234 privatekey = "../.." + cfg.dnssec.keys.private;
235 zonepublickey = "../.." + cfg.dnssec.keys.zonePublic;
236 zoneprivatekey = "../.." + cfg.dnssec.keys.zonePrivate;
240 service.daemon = true;
244 users.users.ncdns = {
247 description = "ncdns daemon user";
249 users.groups.ncdns = {};
251 systemd.services.ncdns = {
252 description = "ncdns daemon";
253 after = [ "namecoind.service" ];
254 wantedBy = [ "multi-user.target" ];
258 StateDirectory = "ncdns";
259 Restart = "on-failure";
260 ExecStart = "${pkgs.ncdns}/bin/ncdns -conf=${configFile}";
263 preStart = lib.optionalString (cfg.dnssec.enable && needsKeygen) ''
265 if [ ! -e bit.key ]; then
266 ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 bit
267 mv Kbit.*.key bit-zone.key
268 mv Kbit.*.private bit-zone.private
269 ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
270 mv Kbit.*.key bit.key
271 mv Kbit.*.private bit.private
278 meta.maintainers = with lib.maintainers; [ rnhmjoj ];