nixos/services.resolved: Move to systemd tooling (#416720)

This commit is contained in:
Sandro
2026-01-14 06:44:50 +00:00
committed by GitHub
5 changed files with 79 additions and 150 deletions
@@ -101,6 +101,8 @@ of pulling the upstream container image from Docker Hub. If you want the old beh
- `services.frp` now supports multiple instances through `services.frp.instances` to make it possible to run multiple frp clients or servers at the same time.
- [services.resolved](#opt-services.resolved.enable) module was converted to RFC42-style settings. The moved options have also been renamed to match the upstream names. Aliases mean current configs will continue to function, but users should move to the new options as convenient.
- `services.openssh` now supports generating host SSH keys by setting `services.openssh.generateHostKeys = true` while leaving `services.openssh.enable` disabled. This is particularly useful for systems that have no need of an SSH daemon but want SSH host keys for other purposes such as using agenix or sops-nix.
- `services.slurm` now supports slurmrestd usage through the `services.slurm.rest` NixOS options.
+74 -145
View File
@@ -2,160 +2,82 @@
config,
lib,
pkgs,
utils,
...
}:
with lib;
let
inherit (utils.systemdUtils.lib) settingsToSections;
inherit (utils.systemdUtils.unitOptions) unitOption;
inherit (lib)
literalExpression
mkIf
mkMerge
mkOption
mkOptionDefault
mkOrder
mkRenamedOptionModule
mkRemovedOptionModule
optionalAttrs
types
;
cfg = config.services.resolved;
dnsmasqResolve = config.services.dnsmasq.enable && config.services.dnsmasq.resolveLocalQueries;
resolvedConf = ''
[Resolve]
${optionalString (
config.networking.nameservers != [ ]
) "DNS=${concatStringsSep " " config.networking.nameservers}"}
${optionalString (cfg.fallbackDns != null) "FallbackDNS=${concatStringsSep " " cfg.fallbackDns}"}
${optionalString (cfg.domains != [ ]) "Domains=${concatStringsSep " " cfg.domains}"}
LLMNR=${cfg.llmnr}
DNSSEC=${cfg.dnssec}
DNSOverTLS=${cfg.dnsovertls}
${config.services.resolved.extraConfig}
'';
resolvedConf = settingsToSections cfg.settings;
in
{
imports = [
(mkRenamedOptionModule
[ "services" "resolved" "fallbackDns" ]
[ "services" "resolved" "settings" "Resolve" "FallbackDNS" ]
)
(mkRenamedOptionModule
[ "services" "resolved" "domains" ]
[ "services" "resolved" "settings" "Resolve" "Domains" ]
)
(mkRenamedOptionModule
[ "services" "resolved" "llmnr" ]
[ "services" "resolved" "settings" "Resolve" "LLMNR" ]
)
(mkRenamedOptionModule
[ "services" "resolved" "dnssec" ]
[ "services" "resolved" "settings" "Resolve" "DNSSEC" ]
)
(mkRenamedOptionModule
[ "services" "resolved" "dnsovertls" ]
[ "services" "resolved" "settings" "Resolve" "DNSOverTLS" ]
)
(mkRemovedOptionModule [
"services"
"resolved"
"extraConfig"
] "Use services.resolved.settings instead")
];
options = {
services.resolved = {
enable = lib.mkEnableOption "the Systemd DNS resolver daemon (systemd-resolved)";
settings.Resolve = mkOption {
description = ''
Settings option for systemd-resolved.
See {manpage}`resolved.conf(5)` for all available options.
'';
# Remember to keep this in sync to the actual settings at the bottom of the page.
defaultText = literalExpression ''
{
DNS = config.networking.nameservers;
DNSOverTLS = false;
DNSSEC = false;
Domains = config.networking.search;
LLMNR = true;
}
'';
type = types.attrsOf unitOption;
};
services.resolved.enable = mkOption {
default = false;
type = types.bool;
description = ''
Whether to enable the systemd DNS resolver daemon, `systemd-resolved`.
Search for `services.resolved` to see all options.
'';
};
services.resolved.fallbackDns = mkOption {
default = null;
example = [
"8.8.8.8"
"2001:4860:4860::8844"
];
type = types.nullOr (types.listOf types.str);
description = ''
A list of IPv4 and IPv6 addresses to use as the fallback DNS servers.
If this option is null, a compiled-in list of DNS servers is used instead.
Setting this option to an empty list will override the built-in list to an empty list, disabling fallback.
'';
};
services.resolved.domains = mkOption {
default = config.networking.search;
defaultText = literalExpression "config.networking.search";
example = [ "example.com" ];
type = types.listOf types.str;
description = ''
A list of domains. These domains are used as search suffixes
when resolving single-label host names (domain names which
contain no dot), in order to qualify them into fully-qualified
domain names (FQDNs).
For compatibility reasons, if this setting is not specified,
the search domains listed in
{file}`/etc/resolv.conf` are used instead, if
that file exists and any domains are configured in it.
'';
};
services.resolved.llmnr = mkOption {
default = "true";
example = "false";
type = types.enum [
"true"
"resolve"
"false"
];
description = ''
Controls Link-Local Multicast Name Resolution support
(RFC 4795) on the local host.
If set to
- `"true"`: Enables full LLMNR responder and resolver support.
- `"false"`: Disables both.
- `"resolve"`: Only resolution support is enabled, but responding is disabled.
'';
};
services.resolved.dnssec = mkOption {
default = "false";
example = "true";
type = types.enum [
"true"
"allow-downgrade"
"false"
];
description = ''
If set to
- `"true"`:
all DNS lookups are DNSSEC-validated locally (excluding
LLMNR and Multicast DNS). Note that this mode requires a
DNS server that supports DNSSEC. If the DNS server does
not properly support DNSSEC all validations will fail.
- `"allow-downgrade"`:
DNSSEC validation is attempted, but if the server does not
support DNSSEC properly, DNSSEC mode is automatically
disabled. Note that this mode makes DNSSEC validation
vulnerable to "downgrade" attacks, where an attacker might
be able to trigger a downgrade to non-DNSSEC mode by
synthesizing a DNS response that suggests DNSSEC was not
supported.
- `"false"`: DNS lookups are not DNSSEC validated.
At the time of September 2023, systemd upstream advise
to disable DNSSEC by default as the current code
is not robust enough to deal with "in the wild" non-compliant
servers, which will usually give you a broken bad experience
in addition of insecure.
'';
};
services.resolved.dnsovertls = mkOption {
default = "false";
example = "true";
type = types.enum [
"true"
"opportunistic"
"false"
];
description = ''
If set to
- `"true"`:
all DNS lookups will be encrypted. This requires
that the DNS server supports DNS-over-TLS and
has a valid certificate. If the hostname was specified
via the `address#hostname` format in {option}`services.resolved.domains`
then the specified hostname is used to validate its certificate.
- `"opportunistic"`:
all DNS lookups will attempt to be encrypted, but will fallback
to unecrypted requests if the server does not support DNS-over-TLS.
Note that this mode does allow for a malicious party to conduct a
downgrade attack by immitating the DNS server and pretending to not
support encryption.
- `"false"`:
all DNS lookups are done unencrypted.
'';
};
services.resolved.extraConfig = mkOption {
default = "";
type = types.lines;
description = ''
Extra config to append to resolved.conf.
'';
};
boot.initrd.services.resolved.enable = mkOption {
@@ -179,6 +101,15 @@ in
}
];
# If updating any of these attrs, also update the defaultText above.
services.resolved.settings.Resolve = {
DNS = config.networking.nameservers;
DNSOverTLS = mkOptionDefault false;
DNSSEC = mkOptionDefault false;
Domains = mkOptionDefault config.networking.search;
LLMNR = mkOptionDefault true;
};
users.users.systemd-resolve.group = "systemd-resolve";
# add resolve to nss hosts database if enabled and nscd enabled
@@ -186,9 +117,7 @@ in
# added with order 501 to allow modules to go before with mkBefore
system.nssDatabases.hosts = (mkOrder 501 [ "resolve [!UNAVAIL=return]" ]);
systemd.additionalUpstreamSystemUnits = [
"systemd-resolved.service"
];
systemd.additionalUpstreamSystemUnits = [ "systemd-resolved.service" ];
systemd.services.systemd-resolved = {
wantedBy = [ "sysinit.target" ];
+1 -3
View File
@@ -128,9 +128,7 @@
};
};
services.resolved.extraConfig = ''
DNSStubListener=no
'';
services.resolved.settings.Resolve.DNSStubListener = false;
networking.extraHosts = ''
192.0.0.171 ipv4only.arpa
+1 -1
View File
@@ -50,7 +50,7 @@
}
];
services.resolved.enable = true;
services.resolved.fallbackDns = [ ];
services.resolved.settings.Resolve.FallbackDNS = [ ];
networking.useNetworkd = true;
networking.useDHCP = false;
systemd.network.networks."40-eth0".enable = false;
@@ -44,7 +44,7 @@ in
# Enable systemd-resolved with DNSSEC and use the local DNS as a name server
services.resolved.enable = true;
services.resolved.dnssec = "true";
services.resolved.settings.Resolve.DNSSEC = true;
networking.nameservers = [ eth1IP ];
# Configure systemd-timesyncd to use our NTP hostname