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