nixos/timesyncd: migrate to RFC 42-style settings (#516318)

This commit is contained in:
nikstur
2026-06-04 15:21:45 +00:00
committed by GitHub
5 changed files with 81 additions and 35 deletions

View File

@@ -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. - 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} ## Other Notable Changes {#sec-release-26.11-notable-changes}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->

View File

@@ -1,26 +1,37 @@
{ config, lib, ... }: {
config,
with lib; lib,
utils,
...
}:
let let
cfg = config.services.timesyncd; cfg = config.services.timesyncd;
in in
{ {
imports = [
(lib.mkRemovedOptionModule [
"services"
"timesyncd"
"extraConfig"
] "Use services.timesyncd.settings.Time instead.")
];
options = { options = {
services.timesyncd = with types; { services.timesyncd = {
enable = mkOption { enable = lib.mkOption {
default = !config.boot.isContainer; default = !config.boot.isContainer;
defaultText = literalExpression "!config.boot.isContainer"; defaultText = lib.literalExpression "!config.boot.isContainer";
type = bool; type = lib.types.bool;
description = '' description = ''
Enables the systemd NTP client daemon. Enables the systemd NTP client daemon.
''; '';
}; };
servers = mkOption { servers = lib.mkOption {
default = null; default = null;
type = nullOr (listOf str); type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = '' description = ''
The set of NTP servers from which to synchronise. The set of NTP servers from which to synchronise.
@@ -31,10 +42,10 @@ in
See {manpage}`timesyncd.conf(5)` for details. See {manpage}`timesyncd.conf(5)` for details.
''; '';
}; };
fallbackServers = mkOption { fallbackServers = lib.mkOption {
default = config.networking.timeServers; default = config.networking.timeServers;
defaultText = literalExpression "config.networking.timeServers"; defaultText = lib.literalExpression "config.networking.timeServers";
type = nullOr (listOf str); type = lib.types.nullOr (lib.types.listOf lib.types.str);
description = '' description = ''
The set of fallback NTP servers from which to synchronise. The set of fallback NTP servers from which to synchronise.
@@ -45,21 +56,23 @@ in
See {manpage}`timesyncd.conf(5)` for details. See {manpage}`timesyncd.conf(5)` for details.
''; '';
}; };
extraConfig = mkOption { settings.Time = lib.mkOption {
default = ""; default = { };
type = lines; type = lib.types.submodule {
example = '' freeformType = lib.types.attrsOf utils.systemdUtils.unitOptions.unitOption;
PollIntervalMaxSec=180 };
''; example = {
PollIntervalMaxSec = 180;
};
description = '' description = ''
Extra config options for systemd-timesyncd. See Settings for systemd-timesyncd. See {manpage}`timesyncd.conf(5)` for
{manpage}`timesyncd.conf(5)` for available options. available options.
''; '';
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.additionalUpstreamSystemUnits = [ "systemd-timesyncd.service" ]; systemd.additionalUpstreamSystemUnits = [ "systemd-timesyncd.service" ];
@@ -76,16 +89,17 @@ in
environment.LD_LIBRARY_PATH = config.system.nssModules.path; environment.LD_LIBRARY_PATH = config.system.nssModules.path;
}; };
environment.etc."systemd/timesyncd.conf".text = '' services.timesyncd.settings.Time = lib.mkMerge [
[Time] (lib.mkIf (cfg.servers != null) {
'' NTP = lib.mkDefault (lib.concatStringsSep " " cfg.servers);
+ optionalString (cfg.servers != null) '' })
NTP=${concatStringsSep " " cfg.servers} (lib.mkIf (cfg.fallbackServers != null) {
'' FallbackNTP = lib.mkDefault (lib.concatStringsSep " " cfg.fallbackServers);
+ optionalString (cfg.fallbackServers != null) '' })
FallbackNTP=${concatStringsSep " " cfg.fallbackServers} ];
''
+ cfg.extraConfig; environment.etc."systemd/timesyncd.conf".text =
utils.systemdUtils.lib.settingsToSections cfg.settings;
users.users.systemd-timesync = { users.users.systemd-timesync = {
uid = config.ids.uids.systemd-timesync; uid = config.ids.uids.systemd-timesync;

View File

@@ -1666,6 +1666,7 @@ in
systemd-sysusers-immutable = runTest ./systemd-sysusers-immutable.nix; systemd-sysusers-immutable = runTest ./systemd-sysusers-immutable.nix;
systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix; systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix;
systemd-sysusers-password-option-override-ordering = runTest ./systemd-sysusers-password-option-override-ordering.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-timesyncd-nscd-dnssec = runTest ./systemd-timesyncd-nscd-dnssec.nix;
systemd-user-linger = runTest ./systemd-user-linger.nix; systemd-user-linger = runTest ./systemd-user-linger.nix;
systemd-user-linger-purge = runTest ./systemd-user-linger-purge.nix; systemd-user-linger-purge = runTest ./systemd-user-linger-purge.nix;

View File

@@ -20,7 +20,7 @@ let
ntpIP = "192.0.2.1"; ntpIP = "192.0.2.1";
in in
{ {
name = "systemd-timesyncd"; name = "systemd-timesyncd-nscd-dnssec";
nodes.machine = nodes.machine =
{ {
pkgs, pkgs,
@@ -50,9 +50,7 @@ in
# Configure systemd-timesyncd to use our NTP hostname # Configure systemd-timesyncd to use our NTP hostname
services.timesyncd.enable = lib.mkForce true; services.timesyncd.enable = lib.mkForce true;
services.timesyncd.servers = [ ntpHostname ]; services.timesyncd.servers = [ ntpHostname ];
services.timesyncd.extraConfig = '' services.timesyncd.settings.Time.FallbackNTP = ntpHostname;
FallbackNTP=${ntpHostname}
'';
# The debug output is necessary to determine whether systemd-timesyncd successfully resolves our NTP hostname or not # 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"; systemd.services.systemd-timesyncd.environment.SYSTEMD_LOG_LEVEL = "debug";

View File

@@ -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")
'';
}