1# /etc files related to networking, such as /etc/services.
2{
3 config,
4 lib,
5 pkgs,
6 ...
7}:
8let
9
10 cfg = config.networking.resolvconf;
11
12 resolvconfOptions =
13 cfg.extraOptions
14 ++ lib.optional cfg.dnsSingleRequest "single-request"
15 ++ lib.optional cfg.dnsExtensionMechanism "edns0"
16 ++ lib.optional cfg.useLocalResolver "trust-ad";
17
18 configText =
19 ''
20 # This is the default, but we must set it here to prevent
21 # a collision with an apparently unrelated environment
22 # variable with the same name exported by dhcpcd.
23 interface_order='lo lo[0-9]*'
24 ''
25 + lib.optionalString config.services.nscd.enable ''
26 # Invalidate the nscd cache whenever resolv.conf is
27 # regenerated.
28 libc_restart='/run/current-system/systemd/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
29 ''
30 + lib.optionalString (lib.length resolvconfOptions > 0) ''
31 # Options as described in resolv.conf(5)
32 resolv_conf_options='${lib.concatStringsSep " " resolvconfOptions}'
33 ''
34 + lib.optionalString cfg.useLocalResolver ''
35 # This hosts runs a full-blown DNS resolver.
36 name_servers='127.0.0.1${lib.optionalString config.networking.enableIPv6 " ::1"}'
37 ''
38 + cfg.extraConfig;
39
40in
41
42{
43 imports = [
44 (lib.mkRenamedOptionModule
45 [ "networking" "dnsSingleRequest" ]
46 [ "networking" "resolvconf" "dnsSingleRequest" ]
47 )
48 (lib.mkRenamedOptionModule
49 [ "networking" "dnsExtensionMechanism" ]
50 [ "networking" "resolvconf" "dnsExtensionMechanism" ]
51 )
52 (lib.mkRenamedOptionModule
53 [ "networking" "extraResolvconfConf" ]
54 [ "networking" "resolvconf" "extraConfig" ]
55 )
56 (lib.mkRenamedOptionModule
57 [ "networking" "resolvconfOptions" ]
58 [ "networking" "resolvconf" "extraOptions" ]
59 )
60 (lib.mkRemovedOptionModule [
61 "networking"
62 "resolvconf"
63 "useHostResolvConf"
64 ] "This option was never used for anything anyways")
65 ];
66
67 options = {
68
69 networking.resolvconf = {
70
71 enable = lib.mkOption {
72 type = lib.types.bool;
73 default = !(config.environment.etc ? "resolv.conf");
74 defaultText = lib.literalExpression ''!(config.environment.etc ? "resolv.conf")'';
75 description = ''
76 Whether DNS configuration is managed by resolvconf.
77 '';
78 };
79
80 package = lib.mkOption {
81 type = lib.types.package;
82 default = pkgs.openresolv;
83 defaultText = lib.literalExpression "pkgs.openresolv";
84 description = ''
85 The package that provides the system-wide resolvconf command. Defaults to `openresolv`
86 if this module is enabled. Otherwise, can be used by other modules (for example {option}`services.resolved`) to
87 provide a compatibility layer.
88
89 This option generally shouldn't be set by the user.
90 '';
91 };
92
93 dnsSingleRequest = lib.mkOption {
94 type = lib.types.bool;
95 default = false;
96 description = ''
97 Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
98 address queries at the same time, from the same port. Sometimes upstream
99 routers will systemically drop the ipv4 queries. The symptom of this problem is
100 that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
101 workaround for this is to specify the option 'single-request' in
102 /etc/resolv.conf. This option enables that.
103 '';
104 };
105
106 dnsExtensionMechanism = lib.mkOption {
107 type = lib.types.bool;
108 default = true;
109 description = ''
110 Enable the `edns0` option in {file}`resolv.conf`. With
111 that option set, `glibc` supports use of the extension mechanisms for
112 DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
113 which does not work without it.
114 '';
115 };
116
117 extraConfig = lib.mkOption {
118 type = lib.types.lines;
119 default = "";
120 example = "libc=NO";
121 description = ''
122 Extra configuration to append to {file}`resolvconf.conf`.
123 '';
124 };
125
126 extraOptions = lib.mkOption {
127 type = lib.types.listOf lib.types.str;
128 default = [ ];
129 example = [
130 "ndots:1"
131 "rotate"
132 ];
133 description = ''
134 Set the options in {file}`/etc/resolv.conf`.
135 '';
136 };
137
138 useLocalResolver = lib.mkOption {
139 type = lib.types.bool;
140 default = false;
141 description = ''
142 Use local DNS server for resolving.
143 '';
144 };
145
146 subscriberFiles = lib.mkOption {
147 type = lib.types.listOf lib.types.path;
148 default = [ ];
149 description = ''
150 Files written by resolvconf updates
151 '';
152 internal = true;
153 };
154
155 };
156
157 };
158
159 config = lib.mkMerge [
160 {
161 environment.etc."resolvconf.conf".text =
162 if !cfg.enable then
163 # Force-stop any attempts to use resolvconf
164 ''
165 echo "resolvconf is disabled on this system but was used anyway:" >&2
166 echo "$0 $*" >&2
167 exit 1
168 ''
169 else
170 configText;
171 }
172
173 (lib.mkIf cfg.enable {
174 users.groups.resolvconf = { };
175
176 networking.resolvconf.subscriberFiles = [ "/etc/resolv.conf" ];
177
178 networking.resolvconf.package = pkgs.openresolv;
179
180 environment.systemPackages = [ cfg.package ];
181
182 systemd.services.resolvconf = {
183 description = "resolvconf update";
184
185 before = [ "network-pre.target" ];
186 wants = [ "network-pre.target" ];
187 wantedBy = [ "multi-user.target" ];
188 restartTriggers = [ config.environment.etc."resolvconf.conf".source ];
189 serviceConfig.Type = "oneshot";
190 serviceConfig.RemainAfterExit = true;
191
192 script = ''
193 ${lib.getExe cfg.package} -u
194 chgrp resolvconf ${lib.escapeShellArgs cfg.subscriberFiles}
195 chmod g=u ${lib.escapeShellArgs cfg.subscriberFiles}
196 ${lib.getExe' pkgs.acl "setfacl"} -R \
197 -m group:resolvconf:rwx \
198 -m default:group:resolvconf:rwx \
199 /run/resolvconf
200 '';
201 };
202
203 })
204 ];
205
206}