From 4c7865cd8b0fd2dbdd89387970a2bf591644cdfc Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 17 Aug 2026 19:25:27 +0200 Subject: [PATCH] docs: trim the reload rationale to the live constraint Keeps why the setting exists (the bridge writes this file and cannot restart authelia) and drops the incident narrative and the answered objections -- that history belongs in the PR discussion, not in three comment blocks a future reader has to scroll past. --- nix/host-modules/swarm-authelia.nix | 25 +++++---------------- nix/host-modules/swarm-controller.nix | 3 --- swarmctl/src/main.rs | 32 +++++---------------------- 3 files changed, 11 insertions(+), 49 deletions(-) diff --git a/nix/host-modules/swarm-authelia.nix b/nix/host-modules/swarm-authelia.nix index 3c3d3965..cd63c2a6 100644 --- a/nix/host-modules/swarm-authelia.nix +++ b/nix/host-modules/swarm-authelia.nix @@ -967,25 +967,12 @@ in server.address = "tcp://127.0.0.1:${toString cfg.port}"; log.level = "info"; - # Authelia reads this file once, at STARTUP. `watch` makes it - # re-read on change, and that is load-bearing rather than a - # convenience. - # - # `swarm-authelia-bridge` writes this file to create agent - # identities and **cannot** restart authelia: running - # unprivileged inside the container is the whole reason it is - # allowed to write the file at all, so "restart the unit" is - # exactly the privilege it was designed not to hold. Without - # `watch` every identity it creates is real on disk and - # invisible to the running authelia until something unrelated - # bounces the unit. - # - # `swarmctl` does restart authelia after writing — but that is - # a `systemctl -M` shellout that can fail, and when it did the - # symptom was a login refused for a user whose record was - # already correct on disk, with nothing implicating the - # reload. This setting is what makes correctness stop - # depending on that restart succeeding. + # `watch` is load-bearing, not a convenience: authelia reads + # this file once at startup, and `swarm-authelia-bridge` writes + # it to create agent identities while being unable to restart + # authelia — running unprivileged is the whole reason it may + # write the file at all. Without this, an identity it creates is + # real on disk and invisible until something unrelated restarts. authentication_backend.file = { path = cfg.usersFile; watch = true; diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index 06c42b5f..44464fd4 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -29,9 +29,6 @@ let # parameters baked into a hash have to match the verifier's. SWARMCTL_AUTHELIA_BIN = "${autheliaCfg.package}/bin/authelia"; SWARMCTL_AUTHELIA_USERS_FILE = autheliaCfg.hostUsersFile; - # No MACHINE/UNIT here any more: `swarmctl` no longer restarts authelia, - # because authelia watches the users file itself. Those two values existed - # solely to name a `systemctl -M` target. }; natsCfg = config.services.hyperhive.swarm.nats; diff --git a/swarmctl/src/main.rs b/swarmctl/src/main.rs index fd0b88b3..925605f6 100644 --- a/swarmctl/src/main.rs +++ b/swarmctl/src/main.rs @@ -343,33 +343,11 @@ fn publish(paths: &Paths, store: &UserStore) -> Result<()> { write_atomic(&paths.store, &format!("{store_json}\n"))?; write_atomic(&paths.users_file, &rendered)?; - // No restart. Authelia is configured with - // `authentication_backend.file.watch`, so it re-reads this file itself. - // - // This used to shell out to `systemctl -M restart `. That - // was the wrong shape twice over: it could fail (it did — a login refused - // for a user whose record was already correct on disk, with nothing in - // either log implicating the reload), and it only ever worked for THIS - // writer. `swarm-authelia-bridge` writes the same file to create agent - // identities and cannot restart anything: running unprivileged inside the - // container is the whole reason it may write the file at all. A reload - // that depends on which process did the writing is not a reload. - // - // The three objections that previously kept `watch` out of this path are - // all now answered, and they were good objections — recorded here so the - // next reader does not have to re-earn them: - // - // - "could not be verified against the pinned build" — it is now: - // authelia v4.39.20's own `validate-config` accepts `watch` and - // *rejects* a deliberate misspelling of it, so the key is recognised - // rather than silently swallowed. - // - "does the watch survive the rename(2) used above" — yes: authelia - // watches the containing *directory*, so a rename into it is observed. - // A watch on the old inode alone would indeed have missed it. - // - "can it observe a partially written file" — it cannot, and that is - // structural rather than a debounce we are trusting: every writer of - // this file goes through `write_atomic` below, so no partial content is - // ever visible under the final name. (Authelia debounces as well.) + // No restart: authelia watches this file + // (`authentication_backend.file.watch`). Deliberately not `swarmctl`'s job + // — `swarm-authelia-bridge` writes the same file and *cannot* restart + // anything, since running unprivileged is the whole reason it may write + // it. A reload that depends on which process wrote is not a reload. Ok(()) }