1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 inherit (pkgs) chrony;
8
9 stateDir = "/var/lib/chrony";
10
11 chronyUser = "chrony";
12
13 cfg = config.services.chrony;
14
15 configFile = pkgs.writeText "chrony.conf" ''
16 ${toString (map (server: "server " + server + "\n") cfg.servers)}
17
18 ${optionalString cfg.initstepslew.enabled ''
19 initstepslew ${toString cfg.initstepslew.threshold} ${toString (map (server: server + " ") cfg.initstepslew.servers)}
20 ''}
21
22 driftfile ${stateDir}/chrony.drift
23
24 ${optionalString (!config.time.hardwareClockInLocalTime) "rtconutc"}
25
26 ${cfg.extraConfig}
27 '';
28
29 chronyFlags = "-m -f ${configFile} -u ${chronyUser}";
30
31in
32
33{
34
35 ###### interface
36
37 options = {
38
39 services.chrony = {
40
41 enable = mkOption {
42 default = false;
43 description = ''
44 Whether to synchronise your machine's time using chrony.
45 Make sure you disable NTP if you enable this service.
46 '';
47 };
48
49 servers = mkOption {
50 default = [
51 "0.nixos.pool.ntp.org"
52 "1.nixos.pool.ntp.org"
53 "2.nixos.pool.ntp.org"
54 "3.nixos.pool.ntp.org"
55 ];
56 description = ''
57 The set of NTP servers from which to synchronise.
58 '';
59 };
60
61 initstepslew = mkOption {
62 default = {
63 enabled = true;
64 threshold = 1000; # by default, same threshold as 'ntpd -g' (1000s)
65 servers = cfg.servers;
66 };
67 description = ''
68 Allow chronyd to make a rapid measurement of the system clock error at
69 boot time, and to correct the system clock by stepping before normal
70 operation begins.
71 '';
72 };
73
74 extraConfig = mkOption {
75 default = "";
76 description = ''
77 Extra configuration directives that should be added to
78 <literal>chrony.conf</literal>
79 '';
80 };
81 };
82
83 };
84
85
86 ###### implementation
87
88 config = mkIf config.services.chrony.enable {
89
90 # Make chronyc available in the system path
91 environment.systemPackages = [ pkgs.chrony ];
92
93 users.extraUsers = singleton
94 { name = chronyUser;
95 uid = config.ids.uids.chrony;
96 description = "chrony daemon user";
97 home = stateDir;
98 };
99
100 jobs.chronyd =
101 { description = "chrony daemon";
102
103 wantedBy = [ "multi-user.target" ];
104 after = [ "network.target" ];
105
106 path = [ chrony ];
107
108 preStart =
109 ''
110 mkdir -m 0755 -p ${stateDir}
111 chown ${chronyUser} ${stateDir}
112 '';
113
114 exec = "chronyd -n ${chronyFlags}";
115 };
116
117 };
118
119}