1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.dnscache;
7
8 dnscache-root = pkgs.runCommand "dnscache-root" {} ''
9 mkdir -p $out/{servers,ip}
10
11 ${concatMapStrings (ip: ''
12 echo > "$out/ip/"${lib.escapeShellArg ip}
13 '') cfg.clientIps}
14
15 ${concatStrings (mapAttrsToList (host: ips: ''
16 ${concatMapStrings (ip: ''
17 echo ${lib.escapeShellArg ip} > "$out/servers/"${lib.escapeShellArg host}
18 '') ips}
19 '') cfg.domainServers)}
20
21 # if a list of root servers was not provided in config, copy it
22 # over. (this is also done by dnscache-conf, but we 'rm -rf
23 # /var/lib/dnscache/root' below & replace it wholesale with this,
24 # so we have to ensure servers/@ exists ourselves.)
25 if [ ! -e $out/servers/@ ]; then
26 # symlink does not work here, due chroot
27 cp ${pkgs.djbdns}/etc/dnsroots.global $out/servers/@;
28 fi
29 '';
30
31in {
32
33 ###### interface
34
35 options = {
36 services.dnscache = {
37 enable = mkOption {
38 default = false;
39 type = types.bool;
40 description = "Whether to run the dnscache caching dns server";
41 };
42
43 ip = mkOption {
44 default = "0.0.0.0";
45 type = types.str;
46 description = "IP address on which to listen for connections";
47 };
48
49 clientIps = mkOption {
50 default = [ "127.0.0.1" ];
51 type = types.listOf types.str;
52 description = "client IP addresses (or prefixes) from which to accept connections";
53 example = ["192.168" "172.23.75.82"];
54 };
55
56 domainServers = mkOption {
57 default = { };
58 type = types.attrsOf (types.listOf types.str);
59 description = "table of {hostname: server} pairs to use as authoritative servers for hosts (and subhosts)";
60 example = {
61 "example.com" = ["8.8.8.8" "8.8.4.4"];
62 };
63 };
64 };
65 };
66
67 ###### implementation
68
69 config = mkIf config.services.dnscache.enable {
70 environment.systemPackages = [ pkgs.djbdns ];
71 users.extraUsers.dnscache = {};
72
73 systemd.services.dnscache = {
74 description = "djbdns dnscache server";
75 wantedBy = [ "multi-user.target" ];
76 path = with pkgs; [ bash daemontools djbdns ];
77 preStart = ''
78 rm -rf /var/lib/dnscache
79 dnscache-conf dnscache dnscache /var/lib/dnscache ${config.services.dnscache.ip}
80 rm -rf /var/lib/dnscache/root
81 ln -sf ${dnscache-root} /var/lib/dnscache/root
82 '';
83 script = ''
84 cd /var/lib/dnscache/
85 exec ./run
86 '';
87 };
88 };
89}