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