diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 26f4eba707f92..d84136125f934 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -128,10 +128,14 @@ in contents."/etc/dbus-1".source = pkgs.makeDBusConf { inherit (cfg) apparmor; suidHelper = "/bin/false"; - serviceDirectories = [ pkgs.dbus ]; + serviceDirectories = [ pkgs.dbus config.boot.initrd.systemd.package ]; }; packages = [ pkgs.dbus ]; - storePaths = [ "${pkgs.dbus}/bin/dbus-daemon" ]; + storePaths = [ + "${pkgs.dbus}/bin/dbus-daemon" + "${config.boot.initrd.systemd.package}/share/dbus-1/system-services" + "${config.boot.initrd.systemd.package}/share/dbus-1/system.d" + ]; targets.sockets.wants = [ "dbus.socket" ]; }; }) diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix index 64a15179438fe..b658a7a2dc05e 100644 --- a/nixos/modules/system/boot/resolved.nix +++ b/nixos/modules/system/boot/resolved.nix @@ -7,6 +7,20 @@ let 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} + ''; + in { @@ -126,60 +140,87 @@ in ''; }; - }; - - config = mkIf cfg.enable { - - assertions = [ - { assertion = !config.networking.useHostResolvConf; - message = "Using host resolv.conf is not supported with systemd-resolved"; - } - ]; - - users.users.systemd-resolve.group = "systemd-resolve"; - - # add resolve to nss hosts database if enabled and nscd enabled - # system.nssModules is configured in nixos/modules/system/boot/systemd.nix - # 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.services.systemd-resolved = { - wantedBy = [ "multi-user.target" ]; - aliases = [ "dbus-org.freedesktop.resolve1.service" ]; - restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ]; - }; - - environment.etc = { - "systemd/resolved.conf".text = '' - [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} + boot.initrd.services.resolved.enable = mkOption { + default = config.boot.initrd.systemd.network.enable; + defaultText = "config.boot.initrd.systemd.network.enable"; + description = '' + Whether to enable resolved for stage 1 networking. + Uses the toplevel 'services.resolved' options for 'resolved.conf' ''; - - # symlink the dynamic stub resolver of resolv.conf as recommended by upstream: - # https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf - "resolv.conf".source = "/run/systemd/resolve/stub-resolv.conf"; - } // optionalAttrs dnsmasqResolve { - "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf"; }; - # If networkmanager is enabled, ask it to interface with resolved. - networking.networkmanager.dns = "systemd-resolved"; - - networking.resolvconf.package = pkgs.systemd; - }; + config = mkMerge [ + (mkIf cfg.enable { + + assertions = [ + { assertion = !config.networking.useHostResolvConf; + message = "Using host resolv.conf is not supported with systemd-resolved"; + } + ]; + + users.users.systemd-resolve.group = "systemd-resolve"; + + # add resolve to nss hosts database if enabled and nscd enabled + # system.nssModules is configured in nixos/modules/system/boot/systemd.nix + # 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.services.systemd-resolved = { + wantedBy = [ "sysinit.target" ]; + aliases = [ "dbus-org.freedesktop.resolve1.service" ]; + restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ]; + }; + + environment.etc = { + "systemd/resolved.conf".text = resolvedConf; + + # symlink the dynamic stub resolver of resolv.conf as recommended by upstream: + # https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf + "resolv.conf".source = "/run/systemd/resolve/stub-resolv.conf"; + } // optionalAttrs dnsmasqResolve { + "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf"; + }; + + # If networkmanager is enabled, ask it to interface with resolved. + networking.networkmanager.dns = "systemd-resolved"; + + networking.resolvconf.package = pkgs.systemd; + + }) + + (mkIf config.boot.initrd.services.resolved.enable { + + assertions = [ + { + assertion = config.boot.initrd.systemd.enable; + message = "'boot.initrd.services.resolved.enable' can only be enabled with systemd stage 1."; + } + ]; + + boot.initrd.systemd = { + contents = { + "/etc/tmpfiles.d/resolv.conf".text = + "L /etc/resolv.conf - - - - /run/systemd/resolve/stub-resolv.conf"; + "/etc/systemd/resolved.conf".text = resolvedConf; + }; + + additionalUpstreamUnits = ["systemd-resolved.service"]; + users.systemd-resolve = {}; + groups.systemd-resolve = {}; + storePaths = ["${config.boot.initrd.systemd.package}/lib/systemd/systemd-resolved"]; + services.systemd-resolved = { + wantedBy = ["sysinit.target"]; + aliases = [ "dbus-org.freedesktop.resolve1.service" ]; + }; + }; + + }) + ]; + } diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 8146a9b86026f..150ee7953023b 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -930,6 +930,7 @@ in { systemd-oomd = handleTest ./systemd-oomd.nix {}; systemd-portabled = handleTest ./systemd-portabled.nix {}; systemd-repart = handleTest ./systemd-repart.nix {}; + systemd-resolved = handleTest ./systemd-resolved.nix {}; systemd-shutdown = handleTest ./systemd-shutdown.nix {}; systemd-sysupdate = runTest ./systemd-sysupdate.nix; systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix; diff --git a/nixos/tests/systemd-resolved.nix b/nixos/tests/systemd-resolved.nix new file mode 100644 index 0000000000000..3eedc17f4b34f --- /dev/null +++ b/nixos/tests/systemd-resolved.nix @@ -0,0 +1,75 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "systemd-resolved"; + meta.maintainers = [ lib.maintainers.elvishjerricco ]; + + nodes.server = { lib, config, ... }: let + exampleZone = pkgs.writeTextDir "example.com.zone" '' + @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800 + @ A ${(lib.head config.networking.interfaces.eth1.ipv4.addresses).address} + @ AAAA ${(lib.head config.networking.interfaces.eth1.ipv6.addresses).address} + ''; + in { + networking.firewall.enable = false; + networking.useDHCP = false; + + networking.interfaces.eth1.ipv6.addresses = lib.mkForce [ + { address = "fd00::1"; prefixLength = 64; } + ]; + + services.knot = { + enable = true; + settings = { + server.listen = [ + "0.0.0.0@53" + "::@53" + ]; + template.default.storage = exampleZone; + zone."example.com".file = "example.com.zone"; + }; + }; + }; + + nodes.client = { nodes, ... }: let + inherit (lib.head nodes.server.networking.interfaces.eth1.ipv4.addresses) address; + in { + networking.nameservers = [ address ]; + networking.interfaces.eth1.ipv6.addresses = lib.mkForce [ + { address = "fd00::2"; prefixLength = 64; } + ]; + services.resolved.enable = true; + services.resolved.fallbackDns = [ ]; + networking.useNetworkd = true; + networking.useDHCP = false; + systemd.network.networks."40-eth0".enable = false; + + testing.initrdBackdoor = true; + boot.initrd = { + systemd.enable = true; + systemd.initrdBin = [ pkgs.iputils ]; + network.enable = true; + services.resolved.enable = true; + }; + }; + + testScript = { nodes, ... }: let + address4 = (lib.head nodes.server.networking.interfaces.eth1.ipv4.addresses).address; + address6 = (lib.head nodes.server.networking.interfaces.eth1.ipv6.addresses).address; + in '' + start_all() + server.wait_for_unit("multi-user.target") + + def test_client(): + query = client.succeed("resolvectl query example.com") + assert "${address4}" in query + assert "${address6}" in query + client.succeed("ping -4 -c 1 example.com") + client.succeed("ping -6 -c 1 example.com") + + client.wait_for_unit("initrd.target") + test_client() + client.switch_root() + + client.wait_for_unit("multi-user.target") + test_client() + ''; +})