diff --git a/hive-c0re/src/matrix.rs b/hive-c0re/src/matrix.rs index 497c00a7..ac317790 100644 --- a/hive-c0re/src/matrix.rs +++ b/hive-c0re/src/matrix.rs @@ -123,16 +123,7 @@ pub fn ensure_register_token() -> Result { } std::fs::write(path, format!("{token}\n")) .with_context(|| format!("write registration token to {}", path.display()))?; - // Mode 0640: tuwunel inside the hive-matrix container runs as a - // non-root user; the file gets `chown :tuwunel` via the activation - // script in `nix/modules/hive-matrix.nix` so the tuwunel group - // gains read. 0600 would block tuwunel with `Permission denied - // (os error 13)` (#644); 0644 would world-read the token (mara - // veto: footgun). 0640 with a pinned group is the sweet spot. - // The host-side activation script also chowns + chmods on every - // boot, so this is best-effort: hive-c0re may write the file - // before the chown lands, but the next activation reconciles it. - let _ = std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o640)); + let _ = std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600)); tracing::info!(path = %path.display(), "matrix: generated registration token"); Ok(token) } diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index 750c1ea8..dd125074 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -241,18 +241,6 @@ in } ]; - # Pin the `tuwunel` group at a fixed GID on BOTH the host and the - # hive-matrix container. The registration token file lives on the - # host bind-mounted into the container; for tuwunel's non-root - # user inside the container to read it, the file gets `chown - # root:tuwunel` + mode `0640` in the activation script below. That - # ownership only works if the numeric GID resolves to the same - # name on both sides of the bind — without an explicit pin, the - # host's auto-allocated GID for `tuwunel` (if any) almost - # certainly wouldn't match the container's. 10042 sits well - # outside nixos's auto-allocated system-user range (200..399). - users.groups.tuwunel.gid = 10042; - # Generate the registration token at system activation time, BEFORE # the hive-matrix container would otherwise start with an empty # bind-mount target (argus nit on #565: nspawn creates an empty @@ -261,28 +249,15 @@ in # until the next restart). Idempotent: only writes when the file # doesn't exist. 32-byte hex = 64 chars, same shape hive-c0re's # `matrix::ensure_register_token` would produce. - # - # Ownership: tuwunel inside the hive-matrix container runs as its - # own non-root user (nixpkgs's `services.matrix-tuwunel`), so a - # 0600 root-owned file denies it open(2) and tuwunel boots loop- - # fails with `Permission denied (os error 13)` (#644). Fix: - # `chown root:tuwunel` + `chmod 0640` so only the tuwunel group - # gains read access (no world-readable footgun, per mara). The - # `tuwunel` group GID is pinned to 10042 above so the host's name - # → number lookup matches what the container sees. - system.activationScripts.hive-matrix-register-token = lib.stringAfter [ "var" "users" ] '' + system.activationScripts.hive-matrix-register-token = lib.stringAfter [ "var" ] '' tokenFile=${lib.escapeShellArg (toString cfg.registrationTokenFile)} if [ ! -s "$tokenFile" ]; then mkdir -p "$(dirname "$tokenFile")" head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$tokenFile" echo >> "$tokenFile" + chmod 600 "$tokenFile" echo "hive-matrix: generated registration token at $tokenFile" fi - # Always re-apply ownership + mode (covers existing 0600 root- - # owned files from pre-#644 deployments; `chown` + `chmod` are - # both idempotent). - chown root:tuwunel "$tokenFile" - chmod 0640 "$tokenFile" ''; containers.hive-matrix = { @@ -306,14 +281,6 @@ in { ... }: { system.stateVersion = "26.05"; - # Mirror the host's pinned `tuwunel` GID so the bind-mounted - # registration token (chowned `root:tuwunel` on the host) - # resolves to the same group inside the container. Without - # this pin nixos auto-allocates whatever's free, the two - # sides diverge, and tuwunel's user falls back to the - # "other" mode bits (= no read) on the file. See the host- - # side `users.groups.tuwunel.gid` above. - users.groups.tuwunel.gid = 10042; services.matrix-tuwunel = { enable = true; package = cfg.package;