diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 136a5bda745..21e211e1685 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -43,6 +43,10 @@ in config = { + warnings = + optional (config.services.resolved.enable && config.environment.etc ? "resolvconf.conf") + "Openresolv is disabled if resolved is used, so resolvconf.conf is not referenced."; + environment.etc = { # /etc/services: TCP/UDP port assignments. "services".source = pkgs.iana_etc + "/etc/services"; @@ -62,7 +66,16 @@ in ''} ${cfg.extraHosts} ''; - + } // (if config.services.resolved.enable && dnsmasqResolve then { + "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf"; + } else {}) // (if config.services.resolved.enable then { + # /etc/resolv.conf: Configuration for systemd-resolved. + "resolv.conf" = if hasLocalResolver then { + text = "nameserver 127.0.0.1"; + } else { + source = "/run/systemd/resolve/resolv.conf"; + }; + } else { # /etc/resolvconf.conf: Configuration for openresolv. "resolvconf.conf".text = '' @@ -84,7 +97,7 @@ in dnsmasq_conf=/etc/dnsmasq-conf.conf dnsmasq_resolv=/etc/dnsmasq-resolv.conf ''; - }; + }); # The ‘ip-up’ target is started when we have IP connectivity. So # services that depend on IP connectivity (like ntpd) should be diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix index 5c68dd89fb1..fbb211911f1 100644 --- a/nixos/modules/services/networking/dnsmasq.nix +++ b/nixos/modules/services/networking/dnsmasq.nix @@ -82,7 +82,7 @@ in systemd.services.dnsmasq = { description = "dnsmasq daemon"; - after = [ "network.target" ]; + after = [ "network.target" "systemd-resolved.conf" ]; wantedBy = [ "multi-user.target" ]; path = [ dnsmasq ]; preStart = '' diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index b8d04953e9e..4aceaad9e9f 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -140,6 +140,15 @@ in rec { ''; }; + requisite = mkOption { + default = []; + type = types.listOf types.str; + description = '' + Similar to requires. However if the units listed are not started, + they will not be started and the transaction will fail. + ''; + }; + unitConfig = mkOption { default = {}; example = { RequiresMountsFor = "/data"; }; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index a24edf2b191..8c53d342b36 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -98,6 +98,9 @@ let # Networking "systemd-networkd.service" + "systemd-networkd-wait-online.service" + "systemd-resolved.service" + "systemd-timesyncd.service" # Filesystems. "systemd-fsck@.service" @@ -215,6 +218,8 @@ let { PartOf = toString config.partOf; } // optionalAttrs (config.conflicts != []) { Conflicts = toString config.conflicts; } + // optionalAttrs (config.requisite != []) + { Requisite = toString config.requisite; } // optionalAttrs (config.restartTriggers != []) { X-Restart-Triggers = toString config.restartTriggers; } // optionalAttrs (config.description != "") { @@ -568,8 +573,9 @@ let mkdir -p $out/getty.target.wants/ ln -s ../autovt@tty1.service $out/getty.target.wants/ - ln -s ../local-fs.target ../remote-fs.target ../network.target ../nss-lookup.target \ - ../nss-user-lookup.target ../swap.target $out/multi-user.target.wants/ + ln -s ../local-fs.target ../remote-fs.target ../network.target \ + ../nss-lookup.target ../nss-user-lookup.target ../swap.target \ + $out/multi-user.target.wants/ ''} ''; # */ @@ -786,6 +792,22 @@ in ''; }; + services.resolved.enable = mkOption { + default = false; + type = types.bool; + description = '' + Enables the systemd dns resolver daemon. + ''; + }; + + services.timesyncd.enable = mkOption { + default = false; + type = types.bool; + description = '' + Enables the systemd ntp client daemon. + ''; + }; + systemd.tmpfiles.rules = mkOption { type = types.listOf types.str; default = []; @@ -842,7 +864,7 @@ in ###### implementation - config = { + config = mkMerge [ { warnings = concatLists (mapAttrsToList (name: service: optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no") @@ -949,14 +971,6 @@ in users.extraUsers.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway; users.extraGroups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway; - # Networkd - users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network; - users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network; - systemd.services.systemd-networkd.wantedBy = - optional config.systemd.network.enable "multi-user.target"; - systemd.services.systemd-networkd.restartTriggers = - [ config.environment.etc."systemd/network".source ]; - # Generate timer units for all services that have a ‘startAt’ value. systemd.timers = mapAttrs (name: service: @@ -990,5 +1004,62 @@ in systemd.services.systemd-remount-fs.restartIfChanged = false; systemd.services.systemd-journal-flush.restartIfChanged = false; - }; + } + (mkIf config.systemd.network.enable { + users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network; + users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network; + + systemd.services.systemd-networkd = { + wantedBy = [ "multi-user.target" ]; + restartTriggers = [ config.environment.etc."systemd/network".source ]; + }; + + systemd.services.systemd-networkd-wait-online.wantedBy = [ "network-online.target" ]; + + systemd.services."systemd-network-wait-online@" = { + description = "Wait for Network Interface %I to be Configured"; + conflicts = [ "shutdown.target" ]; + requisite = [ "systemd-networkd.service" ]; + after = [ "systemd-networkd.service" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I"; + }; + }; + + services.resolved.enable = mkDefault true; + services.timesyncd.enable = mkDefault config.services.ntp.enable; + }) + (mkIf config.services.resolved.enable { + users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve; + users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve; + + systemd.services.systemd-resolved = { + wantedBy = [ "multi-user.target" ]; + restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ]; + }; + + environment.etc."systemd/resolved.conf".text = '' + [Resolve] + DNS=${concatStringsSep " " config.networking.nameservers} + ''; + }) + (mkIf config.services.timesyncd.enable { + users.extraUsers.systemd-timesync.uid = config.ids.uids.systemd-timesync; + users.extraGroups.systemd-timesync.gid = config.ids.gids.systemd-timesync; + + systemd.services.systemd-timesyncd = { + wantedBy = [ "sysinit.target" ]; + restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ]; + }; + + environment.etc."systemd/timesyncd.conf".text = '' + [Time] + NTP=${concatStringsSep " " config.services.ntp.servers} + ''; + + systemd.services.ntpd.enable = false; + }) + ]; } diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 9579eaa77d0..6b22cf96e1d 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -581,8 +581,8 @@ in { description = "Networking Setup"; after = [ "network-interfaces.target" ]; - before = [ "network.target" ]; - wantedBy = [ "network.target" ]; + before = [ "network.target" "network-online.target" ]; + wantedBy = [ "network.target" "network-online.target" ]; unitConfig.ConditionCapability = "CAP_NET_ADMIN"; @@ -592,7 +592,7 @@ in serviceConfig.RemainAfterExit = true; script = - '' + (optionalString (!config.services.resolved.enable) '' # Set the static DNS configuration, if given. ${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <