Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / networking / dnscache.nix
blobf360aa86c7b8deda5a2577b23a4de5726c76ca7c
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.dnscache;
10   dnscache-root = pkgs.runCommand "dnscache-root" { preferLocalBuild = true; } ''
11     mkdir -p $out/{servers,ip}
13     ${lib.concatMapStrings (ip: ''
14       touch "$out/ip/"${lib.escapeShellArg ip}
15     '') cfg.clientIps}
17     ${lib.concatStrings (
18       lib.mapAttrsToList (host: ips: ''
19         ${lib.concatMapStrings (ip: ''
20           echo ${lib.escapeShellArg ip} >> "$out/servers/"${lib.escapeShellArg host}
21         '') ips}
22       '') cfg.domainServers
23     )}
25     # if a list of root servers was not provided in config, copy it
26     # over. (this is also done by dnscache-conf, but we 'rm -rf
27     # /var/lib/dnscache/root' below & replace it wholesale with this,
28     # so we have to ensure servers/@ exists ourselves.)
29     if [ ! -e $out/servers/@ ]; then
30       # symlink does not work here, due chroot
31       cp ${pkgs.djbdns}/etc/dnsroots.global $out/servers/@;
32     fi
33   '';
38   ###### interface
40   options = {
41     services.dnscache = {
43       enable = lib.mkOption {
44         default = false;
45         type = lib.types.bool;
46         description = "Whether to run the dnscache caching dns server.";
47       };
49       ip = lib.mkOption {
50         default = "0.0.0.0";
51         type = lib.types.str;
52         description = "IP address on which to listen for connections.";
53       };
55       clientIps = lib.mkOption {
56         default = [ "127.0.0.1" ];
57         type = lib.types.listOf lib.types.str;
58         description = "Client IP addresses (or prefixes) from which to accept connections.";
59         example = [
60           "192.168"
61           "172.23.75.82"
62         ];
63       };
65       domainServers = lib.mkOption {
66         default = { };
67         type = lib.types.attrsOf (lib.types.listOf lib.types.str);
68         description = ''
69           Table of {hostname: server} pairs to use as authoritative servers for hosts (and subhosts).
70           If entry for @ is not specified predefined list of root servers is used.
71         '';
72         example = lib.literalExpression ''
73           {
74             "@" = ["8.8.8.8" "8.8.4.4"];
75             "example.com" = ["192.168.100.100"];
76           }
77         '';
78       };
80       forwardOnly = lib.mkOption {
81         default = false;
82         type = lib.types.bool;
83         description = ''
84           Whether to treat root servers (for @) as caching
85           servers, requesting addresses the same way a client does. This is
86           needed if you want to use e.g. Google DNS as your upstream DNS.
87         '';
88       };
90     };
91   };
93   ###### implementation
95   config = lib.mkIf config.services.dnscache.enable {
96     environment.systemPackages = [ pkgs.djbdns ];
97     users.users.dnscache = {
98       isSystemUser = true;
99       group = "dnscache";
100     };
101     users.groups.dnscache = { };
103     systemd.services.dnscache = {
104       description = "djbdns dnscache server";
105       wantedBy = [ "multi-user.target" ];
106       path = with pkgs; [
107         bash
108         daemontools
109         djbdns
110       ];
111       preStart = ''
112         rm -rf /var/lib/dnscache
113         dnscache-conf dnscache dnscache /var/lib/dnscache ${config.services.dnscache.ip}
114         rm -rf /var/lib/dnscache/root
115         ln -sf ${dnscache-root} /var/lib/dnscache/root
116       '';
117       script = ''
118         cd /var/lib/dnscache/
119         ${lib.optionalString cfg.forwardOnly "export FORWARDONLY=1"}
120         exec ./run
121       '';
122     };
123   };