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 || dnsmasqResolve;
13
14in
15
16{
17
18 options = {
19
20 networking.extraHosts = lib.mkOption {
21 type = types.lines;
22 default = "";
23 example = "192.168.0.1 lanlocalhost";
24 description = ''
25 Additional entries to be appended to <filename>/etc/hosts</filename>.
26 '';
27 };
28
29 networking.dnsSingleRequest = lib.mkOption {
30 type = types.bool;
31 default = false;
32 description = ''
33 Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
34 address queries at the same time, from the same port. Sometimes upstream
35 routers will systemically drop the ipv4 queries. The symptom of this problem is
36 that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
37 workaround for this is to specify the option 'single-request' in
38 /etc/resolv.conf. This option enables that.
39 '';
40 };
41
42 networking.dnsExtensionMechanism = lib.mkOption {
43 type = types.bool;
44 default = false;
45 description = ''
46 Enable the <code>edns0</code> option in <filename>resolv.conf</filename>. With
47 that option set, <code>glibc</code> supports use of the extension mechanisms for
48 DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
49 which does not work without it.
50 '';
51 };
52
53 networking.extraResolvconfConf = lib.mkOption {
54 type = types.lines;
55 default = "";
56 example = "libc=NO";
57 description = ''
58 Extra configuration to append to <filename>resolvconf.conf</filename>.
59 '';
60 };
61
62
63 networking.proxy = {
64
65 default = lib.mkOption {
66 type = types.nullOr types.str;
67 default = null;
68 description = ''
69 This option specifies the default value for httpProxy, httpsProxy, ftpProxy and rsyncProxy.
70 '';
71 example = "http://127.0.0.1:3128";
72 };
73
74 httpProxy = lib.mkOption {
75 type = types.nullOr types.str;
76 default = cfg.proxy.default;
77 description = ''
78 This option specifies the http_proxy environment variable.
79 '';
80 example = "http://127.0.0.1:3128";
81 };
82
83 httpsProxy = lib.mkOption {
84 type = types.nullOr types.str;
85 default = cfg.proxy.default;
86 description = ''
87 This option specifies the https_proxy environment variable.
88 '';
89 example = "http://127.0.0.1:3128";
90 };
91
92 ftpProxy = lib.mkOption {
93 type = types.nullOr types.str;
94 default = cfg.proxy.default;
95 description = ''
96 This option specifies the ftp_proxy environment variable.
97 '';
98 example = "http://127.0.0.1:3128";
99 };
100
101 rsyncProxy = lib.mkOption {
102 type = types.nullOr types.str;
103 default = cfg.proxy.default;
104 description = ''
105 This option specifies the rsync_proxy environment variable.
106 '';
107 example = "http://127.0.0.1:3128";
108 };
109
110 allProxy = lib.mkOption {
111 type = types.nullOr types.str;
112 default = cfg.proxy.default;
113 description = ''
114 This option specifies the all_proxy environment variable.
115 '';
116 example = "http://127.0.0.1:3128";
117 };
118
119 noProxy = lib.mkOption {
120 type = types.nullOr types.str;
121 default = null;
122 description = ''
123 This option specifies the no_proxy environment variable.
124 If a default proxy is used and noProxy is null,
125 then noProxy will be set to 127.0.0.1,localhost.
126 '';
127 example = "127.0.0.1,localhost,.localdomain";
128 };
129
130 envVars = lib.mkOption {
131 type = types.attrs;
132 internal = true;
133 default = {};
134 description = ''
135 Environment variables used for the network proxy.
136 '';
137 };
138 };
139 };
140
141 config = {
142
143 environment.etc =
144 { # /etc/services: TCP/UDP port assignments.
145 "services".source = pkgs.iana_etc + "/etc/services";
146
147 # /etc/protocols: IP protocol numbers.
148 "protocols".source = pkgs.iana_etc + "/etc/protocols";
149
150 # /etc/rpc: RPC program numbers.
151 "rpc".source = pkgs.glibc + "/etc/rpc";
152
153 # /etc/hosts: Hostname-to-IP mappings.
154 "hosts".text =
155 ''
156 127.0.0.1 localhost
157 ${optionalString cfg.enableIPv6 ''
158 ::1 localhost
159 ''}
160 ${cfg.extraHosts}
161 '';
162
163 # /etc/resolvconf.conf: Configuration for openresolv.
164 "resolvconf.conf".text =
165 ''
166 # This is the default, but we must set it here to prevent
167 # a collision with an apparently unrelated environment
168 # variable with the same name exported by dhcpcd.
169 interface_order='lo lo[0-9]*'
170 '' + optionalString config.services.nscd.enable ''
171 # Invalidate the nscd cache whenever resolv.conf is
172 # regenerated.
173 libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
174 '' + optionalString cfg.dnsSingleRequest ''
175 # only send one DNS request at a time
176 resolv_conf_options+=' single-request'
177 '' + optionalString cfg.dnsExtensionMechanism ''
178 # enable extension mechanisms for DNS
179 resolv_conf_options+=' edns0'
180 '' + optionalString hasLocalResolver ''
181 # This hosts runs a full-blown DNS resolver.
182 name_servers='127.0.0.1'
183 '' + optionalString dnsmasqResolve ''
184 dnsmasq_conf=/etc/dnsmasq-conf.conf
185 dnsmasq_resolv=/etc/dnsmasq-resolv.conf
186 '' + cfg.extraResolvconfConf + ''
187 '';
188
189 } // (optionalAttrs config.services.resolved.enable (
190 if dnsmasqResolve then {
191 "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
192 } else {
193 "resolv.conf".source = "/run/systemd/resolve/resolv.conf";
194 }
195 ));
196
197 networking.proxy.envVars =
198 optionalAttrs (cfg.proxy.default != null) {
199 # other options already fallback to proxy.default
200 no_proxy = "127.0.0.1,localhost";
201 } // optionalAttrs (cfg.proxy.httpProxy != null) {
202 http_proxy = cfg.proxy.httpProxy;
203 } // optionalAttrs (cfg.proxy.httpsProxy != null) {
204 https_proxy = cfg.proxy.httpsProxy;
205 } // optionalAttrs (cfg.proxy.rsyncProxy != null) {
206 rsync_proxy = cfg.proxy.rsyncProxy;
207 } // optionalAttrs (cfg.proxy.ftpProxy != null) {
208 ftp_proxy = cfg.proxy.ftpProxy;
209 } // optionalAttrs (cfg.proxy.allProxy != null) {
210 all_proxy = cfg.proxy.allProxy;
211 } // optionalAttrs (cfg.proxy.noProxy != null) {
212 no_proxy = cfg.proxy.noProxy;
213 };
214
215 # Install the proxy environment variables
216 environment.sessionVariables = cfg.proxy.envVars;
217
218 # The ‘ip-up’ target is started when we have IP connectivity. So
219 # services that depend on IP connectivity (like ntpd) should be
220 # pulled in by this target.
221 systemd.targets.ip-up.description = "Services Requiring IP Connectivity";
222
223 # This is needed when /etc/resolv.conf is being overriden by networkd
224 # and other configurations. If the file is destroyed by an environment
225 # activation then it must be rebuilt so that applications which interface
226 # with /etc/resolv.conf directly don't break.
227 system.activationScripts.resolvconf = stringAfter [ "etc" "tmpfs" "var" ]
228 ''
229 # Systemd resolved controls its own resolv.conf
230 rm -f /run/resolvconf/interfaces/systemd
231 ${optionalString config.services.resolved.enable ''
232 rm -rf /run/resolvconf/interfaces
233 mkdir -p /run/resolvconf/interfaces
234 ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd
235 ''}
236
237 # Make sure resolv.conf is up to date if not managed by systemd
238 ${optionalString (!config.services.resolved.enable) ''
239 ${pkgs.openresolv}/bin/resolvconf -u
240 ''}
241 '';
242
243 };
244
245 }