1{ config, lib, ... }:
2
3with lib;
4
5{
6
7 options = {
8
9 services.timesyncd = {
10 enable = mkOption {
11 default = !config.boot.isContainer;
12 defaultText = literalExpression "!config.boot.isContainer";
13 type = types.bool;
14 description = lib.mdDoc ''
15 Enables the systemd NTP client daemon.
16 '';
17 };
18 servers = mkOption {
19 default = config.networking.timeServers;
20 defaultText = literalExpression "config.networking.timeServers";
21 type = types.listOf types.str;
22 description = lib.mdDoc ''
23 The set of NTP servers from which to synchronise.
24 '';
25 };
26 extraConfig = mkOption {
27 default = "";
28 type = types.lines;
29 example = ''
30 PollIntervalMaxSec=180
31 '';
32 description = lib.mdDoc ''
33 Extra config options for systemd-timesyncd. See
34 [
35 timesyncd.conf(5)](https://www.freedesktop.org/software/systemd/man/timesyncd.conf.html) for available options.
36 '';
37 };
38 };
39 };
40
41 config = mkIf config.services.timesyncd.enable {
42
43 systemd.additionalUpstreamSystemUnits = [ "systemd-timesyncd.service" ];
44
45 systemd.services.systemd-timesyncd = {
46 wantedBy = [ "sysinit.target" ];
47 aliases = [ "dbus-org.freedesktop.timesync1.service" ];
48 restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
49 };
50
51 environment.etc."systemd/timesyncd.conf".text = ''
52 [Time]
53 NTP=${concatStringsSep " " config.services.timesyncd.servers}
54 ${config.services.timesyncd.extraConfig}
55 '';
56
57 users.users.systemd-timesync = {
58 uid = config.ids.uids.systemd-timesync;
59 group = "systemd-timesync";
60 };
61 users.groups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
62
63 system.activationScripts.systemd-timesyncd-migration =
64 # workaround an issue of systemd-timesyncd not starting due to upstream systemd reverting their dynamic users changes
65 # - https://github.com/NixOS/nixpkgs/pull/61321#issuecomment-492423742
66 # - https://github.com/systemd/systemd/issues/12131
67 mkIf (versionOlder config.system.stateVersion "19.09") ''
68 if [ -L /var/lib/systemd/timesync ]; then
69 rm /var/lib/systemd/timesync
70 mv /var/lib/private/systemd/timesync /var/lib/systemd/timesync
71 fi
72 '';
73 system.activationScripts.systemd-timesyncd-init-clock =
74 # Ensure that we have some stored time to prevent systemd-timesyncd to
75 # resort back to the fallback time.
76 # If the file doesn't exist we assume that our current system clock is
77 # good enough to provide an initial value.
78 ''
79 if ! [ -f /var/lib/systemd/timesync/clock ]; then
80 test -d /var/lib/systemd/timesync || mkdir -p /var/lib/systemd/timesync
81 touch /var/lib/systemd/timesync/clock
82 fi
83 '';
84 };
85
86}