From c1ada736d21d5c497584ea2b1e47f71f826de667 Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 24 Sep 2026 23:11:49 +0200 Subject: [PATCH] feat(deploy): give the upgrade window its own timezone, not the system An upgrade restarts the app and the Fujitsu dispenser runs an audible init routine when it does. On sintra that was firing at 10:17 in the morning, in the room, because `dates = "04:00"` is local time and every machine inherits America/Guatemala from the shared base config. The obvious fix is to set the system timezone per machine. This does the narrower thing instead: systemd 252+ accepts a timezone suffix on a calendar spec, so the timer follows Europe/Paris and its DST while the system clock stays a fleet default nobody maintains per host. The only other consumer of machine-local time is a technician reading the journal at the machine, and for correlating against relay created_at stamps, UTC is easier anyway. The operator dashboard never needed this. It renders timestamps in the reader's own browser locale, which is why the cassettes tab read correctly while the journal did not. Verified by resolving the config for all four hosts, and against systemd-analyze on sintra itself: 04:00 Europe/Paris is 02:00 UTC in summer, 04:00 America/Guatemala is 10:00 UTC. A warning is in the comment because it nearly caught me: the same check under `nix-shell -p systemd` silently computes EVERY named zone as UTC while echoing the zone back in its normalized form. It looks accepted and is wrong. Test on a real system. --- flake.nix | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 194ca55..ffedf6c 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,34 @@ batm3 = "USD"; }; + # Nightly auto-upgrade window per machine model, as a systemd calendar + # spec. An upgrade restarts the app, and the Fujitsu dispenser runs an + # audible init routine when it does, so this wants to land in the middle + # of the machine's own night rather than its business hours. + # + # The timezone suffix (systemd 252+) is what makes that work WITHOUT + # setting the system clock: the timer follows the named zone and its DST, + # while time.timeZone stays a fleet-wide default nobody has to maintain + # per host. Verified on sintra with systemd-analyze — `04:00 + # Europe/Paris` resolves to 02:00 UTC in summer, `04:00 + # America/Guatemala` to 10:00 UTC. + # + # Do NOT check a spec like this under `nix-shell -p systemd`. The sandbox + # cannot resolve named zones and silently computes EVERY one of them as + # UTC, while still echoing the zone back in its "Normalized form" line. + # It looks accepted and is wrong. Test on a real system. + # + # Keyed on model like fiatCodeForModel above, and inheriting the same + # limitation: model is a hardware model, and it only doubles as host + # identity while there is one machine of each. A second sintra in another + # country needs this keyed on host instead, along with the fiat code and + # the app build that bakes it in. + # + # Unlisted models get 04:00 in whatever time.timeZone says, unchanged. + upgradeWindowForModel = { + sintra = "04:00 Europe/Paris"; + }; + lib = nixpkgs.lib; # Helper to create a live USB NixOS config for a specific machine model @@ -182,7 +210,9 @@ enable = true; flake = "git+ssh://forgejo@git.atitlan.io/aiolabs/bitspire.git?ref=dev#${machineModel}-installed"; flags = [ "--refresh" ]; - dates = "04:00"; # daily at 4am + # Daily at 4am in the machine's own zone; see + # upgradeWindowForModel above. + dates = upgradeWindowForModel.${machineModel} or "04:00"; allowReboot = false; };