1# /etc files related to networking, such as /etc/services.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8
9 cfg = config.networking;
10 dnsmasqResolve = config.services.dnsmasq.enable &&
11 config.services.dnsmasq.resolveLocalQueries;
12 hasLocalResolver = config.services.bind.enable ||
13 config.services.unbound.enable ||
14 dnsmasqResolve;
15
16 resolvconfOptions = cfg.resolvconfOptions
17 ++ optional cfg.dnsSingleRequest "single-request"
18 ++ optional cfg.dnsExtensionMechanism "edns0";
19in
20
21{
22
23 options = {
24
25 networking.hosts = lib.mkOption {
26 type = types.attrsOf ( types.listOf types.str );
27 default = {};
28 example = literalExample ''
29 {
30 "127.0.0.1" = [ "foo.bar.baz" ];
31 "192.168.0.2" = [ "fileserver.local" "nameserver.local" ];
32 };
33 '';
34 description = ''
35 Locally defined maps of hostnames to IP addresses.
36 '';
37 };
38
39 networking.extraHosts = lib.mkOption {
40 type = types.lines;
41 default = "";
42 example = "192.168.0.1 lanlocalhost";
43 description = ''
44 Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
45 '';
46 };
47
48 networking.hostConf = lib.mkOption {
49 type = types.lines;
50 default = "multi on";
51 example = ''
52 multi on
53 reorder on
54 trim lan
55 '';
56 description = ''
57 The contents of <filename>/etc/host.conf</filename>. See also <citerefentry><refentrytitle>host.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
58 '';
59 };
60
61 networking.dnsSingleRequest = lib.mkOption {
62 type = types.bool;
63 default = false;
64 description = ''
65 Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
66 address queries at the same time, from the same port. Sometimes upstream
67 routers will systemically drop the ipv4 queries. The symptom of this problem is
68 that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
69 workaround for this is to specify the option 'single-request' in
70 /etc/resolv.conf. This option enables that.
71 '';
72 };
73
74 networking.dnsExtensionMechanism = lib.mkOption {
75 type = types.bool;
76 default = true;
77 description = ''
78 Enable the <code>edns0</code> option in <filename>resolv.conf</filename>. With
79 that option set, <code>glibc</code> supports use of the extension mechanisms for
80 DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
81 which does not work without it.
82 '';
83 };
84
85 networking.extraResolvconfConf = lib.mkOption {
86 type = types.lines;
87 default = "";
88 example = "libc=NO";
89 description = ''
90 Extra configuration to append to <filename>resolvconf.conf</filename>.
91 '';
92 };
93
94 networking.resolvconfOptions = lib.mkOption {
95 type = types.listOf types.str;
96 default = [];
97 example = [ "ndots:1" "rotate" ];
98 description = ''
99 Set the options in <filename>/etc/resolv.conf</filename>.
100 '';
101 };
102
103 networking.timeServers = mkOption {
104 default = [
105 "0.nixos.pool.ntp.org"
106 "1.nixos.pool.ntp.org"
107 "2.nixos.pool.ntp.org"
108 "3.nixos.pool.ntp.org"
109 ];
110 description = ''
111 The set of NTP servers from which to synchronise.
112 '';
113 };
114
115 networking.proxy = {
116
117 default = lib.mkOption {
118 type = types.nullOr types.str;
119 default = null;
120 description = ''
121 This option specifies the default value for httpProxy, httpsProxy, ftpProxy and rsyncProxy.
122 '';
123 example = "http://127.0.0.1:3128";
124 };
125
126 httpProxy = lib.mkOption {
127 type = types.nullOr types.str;
128 default = cfg.proxy.default;
129 description = ''
130 This option specifies the http_proxy environment variable.
131 '';
132 example = "http://127.0.0.1:3128";
133 };
134
135 httpsProxy = lib.mkOption {
136 type = types.nullOr types.str;
137 default = cfg.proxy.default;
138 description = ''
139 This option specifies the https_proxy environment variable.
140 '';
141 example = "http://127.0.0.1:3128";
142 };
143
144 ftpProxy = lib.mkOption {
145 type = types.nullOr types.str;
146 default = cfg.proxy.default;
147 description = ''
148 This option specifies the ftp_proxy environment variable.
149 '';
150 example = "http://127.0.0.1:3128";
151 };
152
153 rsyncProxy = lib.mkOption {
154 type = types.nullOr types.str;
155 default = cfg.proxy.default;
156 description = ''
157 This option specifies the rsync_proxy environment variable.
158 '';
159 example = "http://127.0.0.1:3128";
160 };
161
162 allProxy = lib.mkOption {
163 type = types.nullOr types.str;
164 default = cfg.proxy.default;
165 description = ''
166 This option specifies the all_proxy environment variable.
167 '';
168 example = "http://127.0.0.1:3128";
169 };
170
171 noProxy = lib.mkOption {
172 type = types.nullOr types.str;
173 default = null;
174 description = ''
175 This option specifies the no_proxy environment variable.
176 If a default proxy is used and noProxy is null,
177 then noProxy will be set to 127.0.0.1,localhost.
178 '';
179 example = "127.0.0.1,localhost,.localdomain";
180 };
181
182 envVars = lib.mkOption {
183 type = types.attrs;
184 internal = true;
185 default = {};
186 description = ''
187 Environment variables used for the network proxy.
188 '';
189 };
190 };
191 };
192
193 config = {
194
195 environment.etc =
196 { # /etc/services: TCP/UDP port assignments.
197 "services".source = pkgs.iana-etc + "/etc/services";
198
199 # /etc/protocols: IP protocol numbers.
200 "protocols".source = pkgs.iana-etc + "/etc/protocols";
201
202 # /etc/rpc: RPC program numbers.
203 "rpc".source = pkgs.glibc.out + "/etc/rpc";
204
205 # /etc/hosts: Hostname-to-IP mappings.
206 "hosts".text =
207 let oneToString = set : ip : ip + " " + concatStringsSep " " ( getAttr ip set );
208 allToString = set : concatMapStringsSep "\n" ( oneToString set ) ( attrNames set );
209 userLocalHosts = optionalString
210 ( builtins.hasAttr "127.0.0.1" cfg.hosts )
211 ( concatStringsSep " " ( remove "localhost" cfg.hosts."127.0.0.1" ));
212 userLocalHosts6 = optionalString
213 ( builtins.hasAttr "::1" cfg.hosts )
214 ( concatStringsSep " " ( remove "localhost" cfg.hosts."::1" ));
215 otherHosts = allToString ( removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]);
216 in
217 ''
218 127.0.0.1 ${userLocalHosts} localhost
219 ${optionalString cfg.enableIPv6 ''
220 ::1 ${userLocalHosts6} localhost
221 ''}
222 ${otherHosts}
223 ${cfg.extraHosts}
224 '';
225
226 # /etc/host.conf: resolver configuration file
227 "host.conf".text = cfg.hostConf;
228
229 # /etc/resolvconf.conf: Configuration for openresolv.
230 "resolvconf.conf".text =
231 ''
232 # This is the default, but we must set it here to prevent
233 # a collision with an apparently unrelated environment
234 # variable with the same name exported by dhcpcd.
235 interface_order='lo lo[0-9]*'
236 '' + optionalString (length resolvconfOptions > 0) ''
237 # Options as described in resolv.conf(5)
238 resolv_conf_options='${concatStringsSep " " resolvconfOptions}'
239 '' + optionalString hasLocalResolver ''
240 # This hosts runs a full-blown DNS resolver.
241 name_servers='127.0.0.1'
242 '' + optionalString dnsmasqResolve ''
243 dnsmasq_conf=/etc/dnsmasq-conf.conf
244 dnsmasq_resolv=/etc/dnsmasq-resolv.conf
245 '' + cfg.extraResolvconfConf + ''
246 '';
247
248 } // optionalAttrs config.services.resolved.enable {
249 # symlink the static version of resolv.conf as recommended by upstream:
250 # https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf
251 "resolv.conf".source = "${pkgs.systemd}/lib/systemd/resolv.conf";
252 } // optionalAttrs (config.services.resolved.enable && dnsmasqResolve) {
253 "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
254 };
255
256 networking.proxy.envVars =
257 optionalAttrs (cfg.proxy.default != null) {
258 # other options already fallback to proxy.default
259 no_proxy = "127.0.0.1,localhost";
260 } // optionalAttrs (cfg.proxy.httpProxy != null) {
261 http_proxy = cfg.proxy.httpProxy;
262 } // optionalAttrs (cfg.proxy.httpsProxy != null) {
263 https_proxy = cfg.proxy.httpsProxy;
264 } // optionalAttrs (cfg.proxy.rsyncProxy != null) {
265 rsync_proxy = cfg.proxy.rsyncProxy;
266 } // optionalAttrs (cfg.proxy.ftpProxy != null) {
267 ftp_proxy = cfg.proxy.ftpProxy;
268 } // optionalAttrs (cfg.proxy.allProxy != null) {
269 all_proxy = cfg.proxy.allProxy;
270 } // optionalAttrs (cfg.proxy.noProxy != null) {
271 no_proxy = cfg.proxy.noProxy;
272 };
273
274 # Install the proxy environment variables
275 environment.sessionVariables = cfg.proxy.envVars;
276
277 # This is needed when /etc/resolv.conf is being overriden by networkd
278 # and other configurations. If the file is destroyed by an environment
279 # activation then it must be rebuilt so that applications which interface
280 # with /etc/resolv.conf directly don't break.
281 system.activationScripts.resolvconf = stringAfter [ "etc" "specialfs" "var" ]
282 ''
283 # Systemd resolved controls its own resolv.conf
284 rm -f /run/resolvconf/interfaces/systemd
285 ${optionalString config.services.resolved.enable ''
286 rm -rf /run/resolvconf/interfaces
287 mkdir -p /run/resolvconf/interfaces
288 ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd
289 ''}
290
291 # Make sure resolv.conf is up to date if not managed manually or by systemd
292 ${optionalString (!config.environment.etc?"resolv.conf") ''
293 ${pkgs.openresolv}/bin/resolvconf -u
294 ''}
295 '';
296
297 };
298
299 }