Commit 2b724de1 authored by novenary's avatar novenary
Browse files

shutdown: stop manually saving hwclock

Nowadays, the RTC is fully managed by systemd and the kernel.

In userspace, timedated is enabled by default and the clock can be
adjusted with timedatectl.
Further, NixOS enables timesyncd by default, so the clock should be
synced to NTP as long as the system is connected to the internet.

Since early 2013 (Linux 3.9), CONFIG_RTC_SYSTOHC is available and on by
default. [1]
When userspace reports that NTP is synced, this causes the kernel to
periodically update the RTC.
It therefore makes no sense to keep this service enabled when using NTP.
The kernel has seemingly loaded the time from the RTC at bootup for a
very long time. [2]
Manual `hwclock --hctosys` was removed in #165684.

This all seem to make manual RTC fiddling redundant.
My Arch systems don't do it and they've never had any trouble keeping
the time.

The only remaining raison d'être for this service is offline drift
compensation as documented in hwclock(8). [3]
This isn't implemented in NixOS, and the (unmaintained) tool [4] for
this isn't even packaged.
I don't think anyone is relying on this functionality, and it doesn't
seem right to only implement it partially rather than within a more
complete module.

One thing this service actually implemented, rather shakily, is
time.hardwareClockInLocalTime.
This can more reliably be achieved by creating /etc/adjtime directly.

[1]: https://github.com/torvalds/linux/commit/023f333a99cee9b5cd3268ff87298eb01a31f78e
[2]: https://github.com/torvalds/linux/commit/0c86edc0d4970649f39748c4ce4f2895f728468f
[3]: https://man.archlinux.org/man/hwclock.8#Keeping_Time_without_External_Synchronization
[4]: https://github.com/rogers0/adjtimex
parent ee6b9bcc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -96,6 +96,15 @@ in
    // lib.optionalAttrs (config.time.timeZone != null) {
      localtime.source = "/etc/zoneinfo/${config.time.timeZone}";
      localtime.mode = "direct-symlink";
    }
    // lib.optionalAttrs config.time.hardwareClockInLocalTime {
      # Mirrors timedated
      # https://github.com/systemd/systemd/blob/afaca649ad678031a46182b0cce667cbbbf47a6d/src/timedate/timedated.c#L325-L396
      adjtime.text = ''
        0.0 0 0
        0
        LOCAL
      '';
    };
  };

+0 −5
Original line number Diff line number Diff line
@@ -264,11 +264,6 @@ in

    services.timesyncd.enable = lib.mkForce false;

    # If chrony controls and tracks the RTC, writing it externally causes clock error.
    systemd.services.save-hwclock = lib.mkIf cfg.enableRTCTrimming {
      enable = lib.mkForce false;
    };

    systemd.services.systemd-timedated.environment = {
      SYSTEMD_TIMEDATED_NTP_SERVICES = "chronyd.service";
    };
+0 −23
Original line number Diff line number Diff line
{
  config,
  lib,
  pkgs,
  ...
}:

{

  # This unit saves the value of the system clock to the hardware
  # clock on shutdown.
  systemd.services.save-hwclock = {
    description = "Save Hardware Clock";

    wantedBy = [ "shutdown.target" ];

    unitConfig = {
      DefaultDependencies = false;
      ConditionPathExists = "/dev/rtc";
      ConditionPathIsReadWrite = "/etc/";
    };

    serviceConfig = {
      Type = "oneshot";
      ExecStart = "${pkgs.util-linux}/sbin/hwclock --systohc ${
        if config.time.hardwareClockInLocalTime then "--localtime" else "--utc"
      }";
    };
  };

  boot.kernel.sysctl."kernel.poweroff_cmd" = "${config.systemd.package}/sbin/poweroff";

}