1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.bind;
8
9 bindUser = "named";
10
11 confFile = pkgs.writeText "named.conf"
12 ''
13 include "/etc/bind/rndc.key";
14 controls {
15 inet 127.0.0.1 allow {localhost;} keys {"rndc-key";};
16 };
17
18 acl cachenetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} };
19 acl badnetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} };
20
21 options {
22 listen-on { ${concatMapStrings (entry: " ${entry}; ") cfg.listenOn} };
23 listen-on-v6 { ${concatMapStrings (entry: " ${entry}; ") cfg.listenOnIpv6} };
24 allow-query { cachenetworks; };
25 blackhole { badnetworks; };
26 forward first;
27 forwarders { ${concatMapStrings (entry: " ${entry}; ") cfg.forwarders} };
28 directory "/var/run/named";
29 pid-file "/var/run/named/named.pid";
30 ${cfg.extraOptions}
31 };
32
33 ${cfg.extraConfig}
34
35 ${ concatMapStrings
36 ({ name, file, master ? true, slaves ? [], masters ? [] }:
37 ''
38 zone "${name}" {
39 type ${if master then "master" else "slave"};
40 file "${file}";
41 ${ if master then
42 ''
43 allow-transfer {
44 ${concatMapStrings (ip: "${ip};\n") slaves}
45 };
46 ''
47 else
48 ''
49 masters {
50 ${concatMapStrings (ip: "${ip};\n") masters}
51 };
52 ''
53 }
54 allow-query { any; };
55 };
56 '')
57 cfg.zones }
58 '';
59
60in
61
62{
63
64 ###### interface
65
66 options = {
67
68 services.bind = {
69
70 enable = mkOption {
71 default = false;
72 description = "
73 Whether to enable BIND domain name server.
74 ";
75 };
76
77 cacheNetworks = mkOption {
78 default = ["127.0.0.0/24"];
79 description = "
80 What networks are allowed to use us as a resolver.
81 ";
82 };
83
84 blockedNetworks = mkOption {
85 default = [];
86 description = "
87 What networks are just blocked.
88 ";
89 };
90
91 ipv4Only = mkOption {
92 default = false;
93 description = "
94 Only use ipv4, even if the host supports ipv6.
95 ";
96 };
97
98 forwarders = mkOption {
99 default = config.networking.nameservers;
100 description = "
101 List of servers we should forward requests to.
102 ";
103 };
104
105 listenOn = mkOption {
106 default = ["any"];
107 type = types.listOf types.str;
108 description = "
109 Interfaces to listen on.
110 ";
111 };
112
113 listenOnIpv6 = mkOption {
114 default = ["any"];
115 type = types.listOf types.str;
116 description = "
117 Ipv6 interfaces to listen on.
118 ";
119 };
120
121 zones = mkOption {
122 default = [];
123 description = "
124 List of zones we claim authority over.
125 master=false means slave server; slaves means addresses
126 who may request zone transfer.
127 ";
128 example = [{
129 name = "example.com";
130 master = false;
131 file = "/var/dns/example.com";
132 masters = ["192.168.0.1"];
133 slaves = [];
134 }];
135 };
136
137 extraConfig = mkOption {
138 type = types.lines;
139 default = "";
140 description = "
141 Extra lines to be added verbatim to the generated named configuration file.
142 ";
143 };
144
145 extraOptions = mkOption {
146 type = types.lines;
147 default = "";
148 description = ''
149 Extra lines to be added verbatim to the options section of the
150 generated named configuration file.
151 '';
152 };
153
154 configFile = mkOption {
155 type = types.path;
156 default = confFile;
157 defaultText = "confFile";
158 description = "
159 Overridable config file to use for named. By default, that
160 generated by nixos.
161 ";
162 };
163
164 };
165
166 };
167
168
169 ###### implementation
170
171 config = mkIf config.services.bind.enable {
172
173 users.users = singleton
174 { name = bindUser;
175 uid = config.ids.uids.bind;
176 description = "BIND daemon user";
177 };
178
179 systemd.services.bind = {
180 description = "BIND Domain Name Server";
181 after = [ "network.target" ];
182 wantedBy = [ "multi-user.target" ];
183
184 preStart = ''
185 mkdir -m 0755 -p /etc/bind
186 if ! [ -f "/etc/bind/rndc.key" ]; then
187 ${pkgs.bind.out}/sbin/rndc-confgen -r /dev/urandom -c /etc/bind/rndc.key -u ${bindUser} -a -A hmac-sha256 2>/dev/null
188 fi
189
190 ${pkgs.coreutils}/bin/mkdir -p /var/run/named
191 chown ${bindUser} /var/run/named
192 '';
193
194 serviceConfig = {
195 ExecStart = "${pkgs.bind.out}/sbin/named -u ${bindUser} ${optionalString cfg.ipv4Only "-4"} -c ${cfg.configFile} -f";
196 ExecReload = "${pkgs.bind.out}/sbin/rndc -k '/etc/bind/rndc.key' reload";
197 ExecStop = "${pkgs.bind.out}/sbin/rndc -k '/etc/bind/rndc.key' stop";
198 };
199
200 unitConfig.Documentation = "man:named(8)";
201 };
202 };
203}