vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / ncdns.nix
blobd9aeb29e285fde28f9f045de427f6c94d163e1b1
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 ''
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 = ''
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 = ''
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 = ''
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 pseudo-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 = ''
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 = ''
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 ''
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 = ''
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 = ''
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 = ''
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 = ''
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 = ''
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 = ''
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 ];