diff --git a/nixos/doc/manual/release-notes/rl-2611.section.md b/nixos/doc/manual/release-notes/rl-2611.section.md index f993a9c3cbd6..b286c10f7cb9 100644 --- a/nixos/doc/manual/release-notes/rl-2611.section.md +++ b/nixos/doc/manual/release-notes/rl-2611.section.md @@ -24,6 +24,8 @@ - Python 2 has been removed from the top-level package set, as it is long past end-of-life. The `python2`, `python27`, `python2Full`, `python27Full`, `python2Packages`, and `python27Packages` attributes, along with the legacy `python`, `pythonFull`, and `pythonPackages` aliases, now throw an error directing you to `python3`. The `isPy2` and `isPy27` package flags have been removed accordingly. The only remaining Python 2 interpreter is vendored inside the `resholve` package for its `oil` dependency and is not exposed for general use. +- `services.timesyncd.extraConfig` has been removed in favor of the structured [](#opt-services.timesyncd.settings.Time) option. Use `services.timesyncd.settings.Time` to set any `timesyncd.conf(5)` option directly. For example, replace `services.timesyncd.extraConfig = "PollIntervalMaxSec=180";` with `services.timesyncd.settings.Time.PollIntervalMaxSec = 180;`. + ## Other Notable Changes {#sec-release-26.11-notable-changes} diff --git a/nixos/modules/system/boot/timesyncd.nix b/nixos/modules/system/boot/timesyncd.nix index 4584837896fb..ec1deeaad49f 100644 --- a/nixos/modules/system/boot/timesyncd.nix +++ b/nixos/modules/system/boot/timesyncd.nix @@ -1,26 +1,37 @@ -{ config, lib, ... }: - -with lib; +{ + config, + lib, + utils, + ... +}: let cfg = config.services.timesyncd; in { + imports = [ + (lib.mkRemovedOptionModule [ + "services" + "timesyncd" + "extraConfig" + ] "Use services.timesyncd.settings.Time instead.") + ]; + options = { - services.timesyncd = with types; { - enable = mkOption { + services.timesyncd = { + enable = lib.mkOption { default = !config.boot.isContainer; - defaultText = literalExpression "!config.boot.isContainer"; - type = bool; + defaultText = lib.literalExpression "!config.boot.isContainer"; + type = lib.types.bool; description = '' Enables the systemd NTP client daemon. ''; }; - servers = mkOption { + servers = lib.mkOption { default = null; - type = nullOr (listOf str); + type = lib.types.nullOr (lib.types.listOf lib.types.str); description = '' The set of NTP servers from which to synchronise. @@ -31,10 +42,10 @@ in See {manpage}`timesyncd.conf(5)` for details. ''; }; - fallbackServers = mkOption { + fallbackServers = lib.mkOption { default = config.networking.timeServers; - defaultText = literalExpression "config.networking.timeServers"; - type = nullOr (listOf str); + defaultText = lib.literalExpression "config.networking.timeServers"; + type = lib.types.nullOr (lib.types.listOf lib.types.str); description = '' The set of fallback NTP servers from which to synchronise. @@ -45,21 +56,23 @@ in See {manpage}`timesyncd.conf(5)` for details. ''; }; - extraConfig = mkOption { - default = ""; - type = lines; - example = '' - PollIntervalMaxSec=180 - ''; + settings.Time = lib.mkOption { + default = { }; + type = lib.types.submodule { + freeformType = lib.types.attrsOf utils.systemdUtils.unitOptions.unitOption; + }; + example = { + PollIntervalMaxSec = 180; + }; description = '' - Extra config options for systemd-timesyncd. See - {manpage}`timesyncd.conf(5)` for available options. + Settings for systemd-timesyncd. See {manpage}`timesyncd.conf(5)` for + available options. ''; }; }; }; - config = mkIf cfg.enable { + config = lib.mkIf cfg.enable { systemd.additionalUpstreamSystemUnits = [ "systemd-timesyncd.service" ]; @@ -76,16 +89,17 @@ in environment.LD_LIBRARY_PATH = config.system.nssModules.path; }; - environment.etc."systemd/timesyncd.conf".text = '' - [Time] - '' - + optionalString (cfg.servers != null) '' - NTP=${concatStringsSep " " cfg.servers} - '' - + optionalString (cfg.fallbackServers != null) '' - FallbackNTP=${concatStringsSep " " cfg.fallbackServers} - '' - + cfg.extraConfig; + services.timesyncd.settings.Time = lib.mkMerge [ + (lib.mkIf (cfg.servers != null) { + NTP = lib.mkDefault (lib.concatStringsSep " " cfg.servers); + }) + (lib.mkIf (cfg.fallbackServers != null) { + FallbackNTP = lib.mkDefault (lib.concatStringsSep " " cfg.fallbackServers); + }) + ]; + + environment.etc."systemd/timesyncd.conf".text = + utils.systemdUtils.lib.settingsToSections cfg.settings; users.users.systemd-timesync = { uid = config.ids.uids.systemd-timesync; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index c2c42468f727..7bc42039f2a3 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1666,6 +1666,7 @@ in systemd-sysusers-immutable = runTest ./systemd-sysusers-immutable.nix; systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix; systemd-sysusers-password-option-override-ordering = runTest ./systemd-sysusers-password-option-override-ordering.nix; + systemd-timesyncd = runTest ./systemd-timesyncd.nix; systemd-timesyncd-nscd-dnssec = runTest ./systemd-timesyncd-nscd-dnssec.nix; systemd-user-linger = runTest ./systemd-user-linger.nix; systemd-user-linger-purge = runTest ./systemd-user-linger-purge.nix; diff --git a/nixos/tests/systemd-timesyncd-nscd-dnssec.nix b/nixos/tests/systemd-timesyncd-nscd-dnssec.nix index a57cd4802dec..b8eebd4443d9 100644 --- a/nixos/tests/systemd-timesyncd-nscd-dnssec.nix +++ b/nixos/tests/systemd-timesyncd-nscd-dnssec.nix @@ -20,7 +20,7 @@ let ntpIP = "192.0.2.1"; in { - name = "systemd-timesyncd"; + name = "systemd-timesyncd-nscd-dnssec"; nodes.machine = { pkgs, @@ -50,9 +50,7 @@ in # Configure systemd-timesyncd to use our NTP hostname services.timesyncd.enable = lib.mkForce true; services.timesyncd.servers = [ ntpHostname ]; - services.timesyncd.extraConfig = '' - FallbackNTP=${ntpHostname} - ''; + services.timesyncd.settings.Time.FallbackNTP = ntpHostname; # The debug output is necessary to determine whether systemd-timesyncd successfully resolves our NTP hostname or not systemd.services.systemd-timesyncd.environment.SYSTEMD_LOG_LEVEL = "debug"; diff --git a/nixos/tests/systemd-timesyncd.nix b/nixos/tests/systemd-timesyncd.nix new file mode 100644 index 000000000000..7a88fd7e2499 --- /dev/null +++ b/nixos/tests/systemd-timesyncd.nix @@ -0,0 +1,31 @@ +{ + name = "systemd-timesyncd"; + meta = { + maintainers = [ ]; + }; + + nodes.machine = + { lib, ... }: + { + services.timesyncd = { + enable = lib.mkForce true; + servers = [ "ntp.example.com" ]; + fallbackServers = [ "fallback.example.com" ]; + settings.Time = { + PollIntervalMaxSec = "180"; + RootDistanceMaxSec = "5"; + }; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + + with subtest("settings.Time renders timesyncd.conf"): + machine.succeed("grep -F '[Time]' /etc/systemd/timesyncd.conf") + machine.succeed("grep -F 'NTP=ntp.example.com' /etc/systemd/timesyncd.conf") + machine.succeed("grep -F 'FallbackNTP=fallback.example.com' /etc/systemd/timesyncd.conf") + machine.succeed("grep -F 'PollIntervalMaxSec=180' /etc/systemd/timesyncd.conf") + machine.succeed("grep -F 'RootDistanceMaxSec=5' /etc/systemd/timesyncd.conf") + ''; +}