aboutsummaryrefslogtreecommitdiffstats
path: root/openspec/changes/archive
diff options
context:
space:
mode:
Diffstat (limited to 'openspec/changes/archive')
-rw-r--r--openspec/changes/archive/2026-09-24-add-automatic-timezone/.openspec.yaml2
-rw-r--r--openspec/changes/archive/2026-09-24-add-automatic-timezone/design.md41
-rw-r--r--openspec/changes/archive/2026-09-24-add-automatic-timezone/proposal.md26
-rw-r--r--openspec/changes/archive/2026-09-24-add-automatic-timezone/specs/automatic-timezone/spec.md23
-rw-r--r--openspec/changes/archive/2026-09-24-add-automatic-timezone/tasks.md10
5 files changed, 102 insertions, 0 deletions
diff --git a/openspec/changes/archive/2026-09-24-add-automatic-timezone/.openspec.yaml b/openspec/changes/archive/2026-09-24-add-automatic-timezone/.openspec.yaml
new file mode 100644
index 0000000..75289e4
--- /dev/null
+++ b/openspec/changes/archive/2026-09-24-add-automatic-timezone/.openspec.yaml
@@ -0,0 +1,2 @@
1schema: spec-driven
2created: 2026-09-24
diff --git a/openspec/changes/archive/2026-09-24-add-automatic-timezone/design.md b/openspec/changes/archive/2026-09-24-add-automatic-timezone/design.md
new file mode 100644
index 0000000..0037bd5
--- /dev/null
+++ b/openspec/changes/archive/2026-09-24-add-automatic-timezone/design.md
@@ -0,0 +1,41 @@
1## Context
2
3See `proposal.md` - Why. Current state: `modules/nixos/common.nix` sets `time.timeZone = lib.mkDefault "Etc/UTC";` and nothing ever updates it. Relevant constraints discovered while investigating the pinned `nixos-unstable` nixpkgs (`nixos/modules/services/system/automatic-timezoned.nix`, `nixos/modules/services/desktops/geoclue2.nix`, `nixos/modules/services/desktop-managers/plasma6.nix`, and `systemd`'s shipped `org.freedesktop.timedate1.policy`):
4
5- `systemd`'s own default polkit policy requires `auth_admin` for `org.freedesktop.timedate1.set-timezone` for any subject, active or not. Nothing in nixpkgs relaxes that for GNOME.
6- The KDE Plasma 6 module (`plasma6.nix`) adds its own polkit rule allowing an *active* session to call `set-timezone` without a prompt, backing Plasma's own automatic-timezone UI toggle.
7- nixpkgs' GNOME module (`nixos/modules/services/desktops/gnome`) adds no equivalent rule. GNOME Settings' own "Automatic Time Zone" toggle (backed by `gnome-settings-daemon`'s datetime plugin) would therefore hit the default `auth_admin` prompt on this flake's NixOS hosts today - it isn't wired to a passwordless mechanism the way Plasma's is.
8- `services.automatic-timezoned` (a small dedicated daemon) is nixpkgs' own DE-agnostic answer to this gap: when enabled it sets `time.timeZone = null;` itself, turns on `services.geoclue2` with its own `appConfig` entry, and ships a polkit rule scoped to its own dedicated `automatic-timezoned` system user - so it runs unattended regardless of desktop environment or which user is logged in.
9
10## Goals / Non-Goals
11
12**Goals:**
13- Every NixOS host's `time.timeZone` reflects actual physical location shortly after boot, with no manual step and no interactive authentication.
14- The mechanism works the same regardless of which user (if any) is logged into the GNOME session, since it's a system service, not a per-session one.
15
16**Non-Goals:**
17- Making GNOME Settings' own "Automatic Time Zone" toggle functional. It's a separate, unwired mechanism on NixOS (see Context) and fixing that is out of scope - `automatic-timezoned` achieves the actual user-visible goal (correct system timezone, which GNOME's clock/calendar read directly from `time.timeZone`/`/etc/localtime`) without it.
18- Manual/static location configuration (`services.geoclue2.enableStatic` + `location.latitude`/`longitude`). Network-based geolocation is sufficient for a desktop machine that's expected to have network access shortly after boot.
19- Any change to `homeConfigurations` (standalone home-manager, no NixOS layer) - they have no `time.timeZone` to manage.
20
21## Decisions
22
23**Use `services.automatic-timezoned.enable = true;` in `modules/nixos/common.nix`, rather than trying to make GNOME's own toggle work.**
24
25Alternatives considered:
261. **Add a NixOS polkit rule scoped to active GNOME sessions**, mirroring `plasma6.nix`'s `subject.active` rule, then rely on GNOME's own `gsd-datetime` plugin (toggled on via a `dconf` default, the same pattern already used for dark mode in `common.nix`). Rejected: this reverse-engineers and depends on `gsd-datetime`'s internal behavior, which isn't a stable, documented NixOS integration point the way `automatic-timezoned` is: it's exactly the gap `automatic-timezoned` exists to fill for GNOME. It would also only run while a graphical session is active, whereas `automatic-timezoned` is a system service independent of any login.
272. **`services.automatic-timezoned.enable = true;`** (chosen): purpose-built for this exact scenario, self-contained (enables and configures its own `geoclue2` + polkit rule, no manual wiring), maintained in nixpkgs itself, and already proven for the same problem this repo solved for Docker (`container-runtime`) - prefer an existing, documented NixOS module over recreating its internals.
28
29**Leave `time.timeZone = lib.mkDefault "Etc/UTC";` in place rather than removing it.**
30
31`automatic-timezoned`'s module sets `time.timeZone = null;` at normal priority when enabled, which unconditionally overrides the existing `mkDefault`. Leaving the line in place costs nothing and keeps `Etc/UTC` as the documented, explicit fallback if `automatic-timezoned` is ever disabled again on a specific host, without needing to touch `common.nix` a second time.
32
33## Risks / Trade-offs
34
35- **[Risk]** A host with no network access at boot (or geoclue2's beacondb.net lookup failing) never gets a timezone update, and stays on whatever was last applied (or `Etc/UTC` on first boot). → **Mitigation**: none needed for this repo's target hardware (desktops/laptops expected to have network shortly after boot); already called out as a known limitation in `proposal.md`.
36- **[Risk]** GNOME's own "Automatic Time Zone" toggle in Settings remains visually present but functionally disconnected from what's actually keeping the timezone correct, which could read as broken/confusing if a user flips it expecting it to be the mechanism. → **Mitigation**: documented as a known limitation in `proposal.md`; the actual observable goal (correct time shown everywhere) is met regardless of that toggle's state, and no further UI work is planned here.
37- **[Risk]** A future host that legitimately needs a fixed, non-default timezone must remember to set it at higher-than-default priority (`lib.mkForce` or a plain assignment beats `automatic-timezoned`'s normal-priority `null`, but a naive `lib.mkDefault` override would silently lose to it). → **Mitigation**: called out explicitly in `proposal.md`'s BREAKING/Impact notes; the module's own evaluation-time error (if a plain/default-priority conflicting value is set) makes a silent miss unlikely.
38
39## Migration Plan
40
41Additive, single-file change (`modules/nixos/common.nix`) applied to every NixOS host on next `nixos-rebuild switch` (or equivalent activation). No data migration. Rollback is reverting the one-line addition and rebuilding; `time.timeZone` immediately falls back to the existing `Etc/UTC` default with no other state to clean up (the `automatic-timezoned`/`geoclue` system user and services are removed by NixOS's normal generation switch).
diff --git a/openspec/changes/archive/2026-09-24-add-automatic-timezone/proposal.md b/openspec/changes/archive/2026-09-24-add-automatic-timezone/proposal.md
new file mode 100644
index 0000000..6c2c77c
--- /dev/null
+++ b/openspec/changes/archive/2026-09-24-add-automatic-timezone/proposal.md
@@ -0,0 +1,26 @@
1## Why
2
3Every NixOS host built from this flake currently defaults to `Etc/UTC` (`modules/nixos/common.nix`) and nothing ever changes that, so a freshly booted or freshly relocated machine shows the wrong local time/date everywhere (GNOME's clock, calendar, screenshots, log timestamps) until someone manually runs `timedatectl set-timezone`. Tom wants the timezone detected automatically instead.
4
5## What Changes
6
7- Enable `services.automatic-timezoned` unconditionally on every NixOS host, in `modules/nixos/common.nix`, alongside the other unconditional host-level services (GNOME, SSH, printing). This is the NixOS-native daemon for this purpose: it uses `geoclue2` (which it enables and configures itself) to determine location and `systemd-timedated` to actually apply the timezone, and it ships its own polkit rule so the update happens automatically with no interactive auth prompt.
8- The existing `time.timeZone = lib.mkDefault "Etc/UTC";` in `modules/nixos/common.nix` is left as-is: `automatic-timezoned` overrides it internally (`time.timeZone = null;`, at normal priority) whenever it's enabled, so `Etc/UTC` only remains as the boot-time value until the daemon determines and applies the real one shortly after boot (network permitting). No host in this repo (checked `hosts/test-vm`, the only real host, and `hosts/template`) sets `time.timeZone` explicitly, so there's no conflict with the module's requirement that an explicit timezone be set with a priority lower than default.
9- **Not** relying on GNOME's own Settings → Date & Time → "Automatic Time Zone" toggle: NixOS's `systemd` package ships `org.freedesktop.timedate1.set-timezone` requiring `auth_admin` by default, and unlike the KDE Plasma module (`nixos/modules/services/desktop-managers/plasma6.nix`), nixpkgs' GNOME module adds no polkit rule to relax that for GNOME's own timezone daemon. `automatic-timezoned` ships and enables exactly that rule for its own dedicated service user, so it works without depending on GNOME-side authorization plumbing that isn't wired up on NixOS today. See `design.md` for the alternatives considered here.
10- **BREAKING**: none — additive only. A host that later needs a fixed non-`Etc/UTC` timezone can still set `time.timeZone` at a priority higher than default (`lib.mkForce` or a plain assignment) in its own `configuration.nix`; doing so alongside this change without adjusting priority would now raise the same explicit "you set a timezone with `automatic-timezoned` enabled" evaluation error the upstream module already raises by design, which is the intended, deliberate-override behavior — not a silent conflict.
11
12## Capabilities
13
14### New Capabilities
15- `automatic-timezone`: every NixOS host built from this flake keeps its system timezone (and therefore the desktop's clock/calendar) in sync with the host's actual location automatically, without manual `timedatectl` intervention or an interactive authorization prompt.
16
17### Modified Capabilities
18(none)
19
20## Impact
21
22- **Affected code**: `modules/nixos/common.nix` (add `services.automatic-timezoned.enable = true;`).
23- **Not affected**: `modules/home/*` (home-manager-only `homeConfigurations` have no NixOS-level timezone service and are unaffected — they already inherit whatever timezone the host OS provides), `hosts/*/configuration.nix` (no host currently overrides `time.timeZone`), `lib/unfree-allowlist.nix` (`automatic-timezoned` is GPL-3.0, free).
24- **Dependencies**: nixpkgs' `automatic-timezoned` and `geoclue2` packages, both already present in the pinned `nixos-unstable` input; no new flake inputs. `geoclue2`'s default network-based location source (`api.beacondb.net`) requires outbound internet access, which this repo's firewall config (inbound-only restrictions) doesn't block.
25- **Platforms**: NixOS hosts only (`modules/nixos/common.nix`), via any host built by `lib/mkNixos.nix`. No effect on `homeConfigurations` (`tom@linux`, `tom@darwin`).
26- **Known limitation, out of scope**: GNOME's own "Automatic Time Zone" toggle in Settings → Date & Time is not wired to this mechanism and may still prompt for authentication if the user flips it manually; the actual timezone is kept correct by the independent `automatic-timezoned` service regardless of that toggle's state. No reverse-geocoding/location-display UI is added — this only keeps `time.timeZone` current. Timezone detection is network-dependent (Wi-Fi/IP-based geolocation via `geoclue2`); a host with no network at boot keeps whatever timezone was last applied (or `Etc/UTC` on first boot) until connectivity returns.
diff --git a/openspec/changes/archive/2026-09-24-add-automatic-timezone/specs/automatic-timezone/spec.md b/openspec/changes/archive/2026-09-24-add-automatic-timezone/specs/automatic-timezone/spec.md
new file mode 100644
index 0000000..c9c50bf
--- /dev/null
+++ b/openspec/changes/archive/2026-09-24-add-automatic-timezone/specs/automatic-timezone/spec.md
@@ -0,0 +1,23 @@
1## Purpose
2
3Keeps every NixOS host's system timezone in sync with its actual physical location automatically, so the system clock, GNOME's clock/calendar, and log timestamps reflect local time without any manual `timedatectl` step.
4
5## ADDED Requirements
6
7### Requirement: NixOS hosts detect and apply their timezone automatically
8Every NixOS host built from this flake's shared system module SHALL determine its current timezone based on location and apply it to the system, without requiring the user to run a manual command or interactively authenticate the change.
9
10#### Scenario: Timezone is applied after boot with network access
11- **WHEN** a NixOS host built from this flake's shared system module boots with network connectivity available
12- **THEN** the system's active timezone is set to the timezone matching the host's current location, without any interactive prompt
13
14#### Scenario: No per-host opt-in required
15- **WHEN** a NixOS host is built from this flake's shared system module and its own `hosts/<name>/configuration.nix` does not configure timezone detection itself
16- **THEN** automatic timezone detection is still active, exactly as if it had been configured directly
17
18### Requirement: A host can still pin an explicit fixed timezone
19A NixOS host built from this flake SHALL be able to override automatic detection with a fixed, explicitly configured timezone when that host's own configuration requires one.
20
21#### Scenario: Host-level override takes effect
22- **WHEN** a host's own `hosts/<name>/configuration.nix` sets an explicit timezone at a priority higher than the shared default
23- **THEN** that host uses the explicitly configured timezone instead of an automatically detected one
diff --git a/openspec/changes/archive/2026-09-24-add-automatic-timezone/tasks.md b/openspec/changes/archive/2026-09-24-add-automatic-timezone/tasks.md
new file mode 100644
index 0000000..e139bbd
--- /dev/null
+++ b/openspec/changes/archive/2026-09-24-add-automatic-timezone/tasks.md
@@ -0,0 +1,10 @@
1## 1. Enable automatic timezone detection
2
3- [x] 1.1 Add `services.automatic-timezoned.enable = true;` to `modules/nixos/common.nix`, alongside the other unconditional host-level services
4- [x] 1.2 Verify `nix eval '.#nixosConfigurations.test-vm.config.services.automatic-timezoned.enable'` (or the appropriate real host output) evaluates to `true`, and that `.config.services.geoclue2.enable` and `.config.time.timeZone` evaluate to `true` and `null` respectively (confirming `automatic-timezoned` took over from the `Etc/UTC` default as expected) — this repo has no host tracked in git today (`hosts/test-vm` is a local-only scratch VM excluded via `.git/info/exclude`, so it's invisible to the flake's git-tree evaluation and `nixosConfigurations` is currently empty); verified instead via a synthetic `nixpkgs.lib.nixosSystem` built directly from `modules/nixos/common.nix`, confirming `services.automatic-timezoned.enable = true`, `services.geoclue2.enable = true`, and `time.timeZone = null`
5
6## 2. Verification
7
8- [x] 2.1 Run `nix flake check` and confirm it passes
9- [x] 2.2 Run `nix build '.#nixosConfigurations.test-vm.config.system.build.toplevel'` (or the appropriate real host output) and confirm it succeeds — same test-vm caveat as 1.2; built the synthetic `nixosSystem`'s `config.system.build.toplevel` instead, which succeeded natively (this machine is aarch64-linux) and produced a closure including the `automatic-timezoned`, `automatic-timezoned-geoclue-agent`, `geoclue`, and `systemd-timedated` units
10- [x] 2.3 Run `nix fmt` and confirm `modules/nixos/common.nix` is formatted with no diff