From 75648a75942f44c51adcd99cb4d33f3252df097e Mon Sep 17 00:00:00 2001 From: damocles Date: Sat, 30 May 2026 18:28:37 +0200 Subject: [PATCH] matrix: registration token mode 0644 so tuwunel (dynamic user) can read it (#644) --- hive-c0re/src/matrix.rs | 8 +++++++- nix/modules/hive-matrix.nix | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/hive-c0re/src/matrix.rs b/hive-c0re/src/matrix.rs index ac317790..0c2d96be 100644 --- a/hive-c0re/src/matrix.rs +++ b/hive-c0re/src/matrix.rs @@ -123,7 +123,13 @@ pub fn ensure_register_token() -> Result { } std::fs::write(path, format!("{token}\n")) .with_context(|| format!("write registration token to {}", path.display()))?; - let _ = std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600)); + // Mode 0644: tuwunel inside the hive-matrix container runs as its + // own dynamic user (not root), so the bind-mounted file needs to + // be world-readable for tuwunel to load it. 0600 root-owned would + // block tuwunel with `Permission denied (os error 13)` (#644). On + // a single-tenant host the trade-off is acceptable; multi-tenant + // would need group-readable with explicit gid matching. + let _ = std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o644)); 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 dd125074..fa3401a1 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -249,15 +249,27 @@ 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. + # + # Mode 0644 (world-readable): tuwunel inside the hive-matrix + # container runs as its own dynamic user, which doesn't match the + # host's root UID, so a 0600 root-owned bind mount blocks tuwunel + # from reading the file (`Permission denied (os error 13)` — + # observed on #644). 0644 trades "any user on the host can read + # the token" for "tuwunel can actually start". On a single-tenant + # host that's an acceptable trade; tightening to a group-readable + # mode with explicit gid matching is a follow-up if multi-tenant + # hosts need it. 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 the mode (covers existing 0600 files from + # before #644 — `chmod` is idempotent). + chmod 644 "$tokenFile" ''; containers.hive-matrix = {