Merge: zmap: 4.2.0 -> 4.3.1 (#364578)
[NixPkgs.git] / nixos / modules / services / networking / ncdns.nix
blob115726381eb78caf3b19daf75f34227ccc65caa1
1 { config, lib, pkgs, ... }:
2 let
3   cfgs = config.services;
4   cfg  = cfgs.ncdns;
6   dataDir  = "/var/lib/ncdns";
7   username = "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))
13     // { description = ''
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.
18          '';
19        };
21   configFile = pkgs.runCommand "ncdns.conf"
22     { json = builtins.toJSON cfg.settings;
23       passAsFile = [ "json" ];
24     }
25     "${pkgs.remarshal}/bin/json2toml < $jsonPath > $out";
27   defaultFiles = {
28     public  = "${dataDir}/bit.key";
29     private = "${dataDir}/bit.private";
30     zonePublic  = "${dataDir}/bit-zone.key";
31     zonePrivate = "${dataDir}/bit-zone.private";
32   };
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);
44   ###### interface
46   options = {
48     services.ncdns = {
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
54       '';
56       address = lib.mkOption {
57         type = lib.types.str;
58         default = "[::1]";
59         description = ''
60           The IP address the ncdns resolver will bind to.  Leave this unchanged
61           if you do not wish to directly expose the resolver.
62         '';
63       };
65       port = lib.mkOption {
66         type = lib.types.port;
67         default = 5333;
68         description = ''
69           The port the ncdns resolver will bind to.
70         '';
71       };
73       identity.hostname = lib.mkOption {
74         type = lib.types.str;
75         default = config.networking.hostName;
76         defaultText = lib.literalExpression "config.networking.hostName";
77         example = "example.com";
78         description = ''
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
81           the zone apex:
82           ```
83           bit. IN NS ns1.example.com.
84           ```
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.
89         '';
90       };
92       identity.hostmaster = lib.mkOption {
93         type = lib.types.str;
94         default = "";
95         example = "root@example.com";
96         description = ''
97           An email address for the SOA record at the bit zone.
98           If you are only using ncdns locally you can ignore this.
99         '';
100       };
102       identity.address = lib.mkOption {
103         type = lib.types.str;
104         default = "127.127.127.127";
105         description = ''
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.
109         '';
110       };
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
118       '';
120       dnssec.keys.public = lib.mkOption {
121         type = lib.types.path;
122         default = defaultFiles.public;
123         description = ''
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:
127           ```
128           $ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
129           ```
130         '';
131       };
133       dnssec.keys.private = lib.mkOption {
134         type = lib.types.path;
135         default = defaultFiles.private;
136         description = ''
137           Path to the file containing the KSK private key.
138         '';
139       };
141       dnssec.keys.zonePublic = lib.mkOption {
142         type = lib.types.path;
143         default = defaultFiles.zonePublic;
144         description = ''
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:
148           ```
149           $ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
150           ```
151         '';
152       };
154       dnssec.keys.zonePrivate = lib.mkOption {
155         type = lib.types.path;
156         default = defaultFiles.zonePrivate;
157         description = ''
158           Path to the file containing the ZSK private key.
159         '';
160       };
162       settings = lib.mkOption {
163         type = configType;
164         default = { };
165         example = lib.literalExpression ''
166           { # enable webserver
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";
174           }
175         '';
176         description = ''
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.
181         '';
182       };
184     };
186     services.pdns-recursor.resolveNamecoin = lib.mkOption {
187       type = lib.types.bool;
188       default = false;
189       description = ''
190         Resolve `.bit` top-level domains using ncdns and namecoin.
191       '';
192     };
194   };
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}";
203       luaConfig =
204         if cfg.dnssec.enable
205           then ''readTrustAnchorsFromFile("${cfg.dnssec.keys.public}")''
206           else ''addNTA("bit", "namecoin DNSSEC disabled")'';
207     };
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" ];
213     };
215     services.ncdns.settings = mkDefaultAttrs {
216       ncdns =
217         { # Namecoin RPC
218           namecoinrpcaddress =
219             "${cfgs.namecoind.rpc.address}:${toString cfgs.namecoind.rpc.port}";
220           namecoinrpcusername = cfgs.namecoind.rpc.user;
221           namecoinrpcpassword = cfgs.namecoind.rpc.password;
223           # Identity
224           selfname = cfg.identity.hostname;
225           hostmaster = cfg.identity.hostmaster;
226           selfip = cfg.identity.address;
228           # Other
229           bind = "${cfg.address}:${toString cfg.port}";
230         }
231         // lib.optionalAttrs cfg.dnssec.enable
232         { # DNSSEC
233           publickey  = "../.." + cfg.dnssec.keys.public;
234           privatekey = "../.." + cfg.dnssec.keys.private;
235           zonepublickey  = "../.." + cfg.dnssec.keys.zonePublic;
236           zoneprivatekey = "../.." + cfg.dnssec.keys.zonePrivate;
237         };
239         # Daemon
240         service.daemon = true;
241         xlog.journal = true;
242     };
244     users.users.ncdns = {
245       isSystemUser = true;
246       group = "ncdns";
247       description = "ncdns daemon user";
248     };
249     users.groups.ncdns = {};
251     systemd.services.ncdns = {
252       description = "ncdns daemon";
253       after    = [ "namecoind.service" ];
254       wantedBy = [ "multi-user.target" ];
256       serviceConfig = {
257         User = "ncdns";
258         StateDirectory = "ncdns";
259         Restart = "on-failure";
260         ExecStart = "${pkgs.ncdns}/bin/ncdns -conf=${configFile}";
261       };
263       preStart = lib.optionalString (cfg.dnssec.enable && needsKeygen) ''
264         cd ${dataDir}
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
272         fi
273       '';
274     };
276   };
278   meta.maintainers = with lib.maintainers; [ rnhmjoj ];