From fd9cae9c40e48293c11cd085f7262b9a897db8f3 Mon Sep 17 00:00:00 2001 From: Noah Masur <7386960+nmasur@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:17:07 +0000 Subject: [PATCH] fix(ssh): use openssh.authorizedPrincipals for cloudflare certificates --- docs/CHANGELOG.md | 6 ++++ .../nmasur/presets/services/cloudflared.nix | 35 +++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7d9bd2ed..27f6ab3a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,12 @@ ## 2026-09-06 +- **Fixed OpenSSH authorized principals certificate authentication for Cloudflare Tunnel**: + - Replaced manual `environment.etc."ssh/authorized_principals/${username}"` symlink and `Match User` config with NixOS native `users.users..openssh.authorizedPrincipals`. + - Root cause: `environment.etc` without an explicit `mode` creates symlinks pointing into `/nix/store`, which has group-writable mode `0775` (`nixbld` group). Under `StrictModes yes`, sshd refused authentication with `bad ownership or modes for directory /nix/store`, causing certificate principal matching to fail with `Certificate does not contain an authorized principal`. + - Setting `users.users..openssh.authorizedPrincipals` causes NixOS to generate `/etc/ssh/authorized_principals.d/` with `mode = "0444"`, copying the file instead of symlinking into the store, and automatically configuring `services.openssh.settings.AuthorizedPrincipalsFile = "/etc/ssh/authorized_principals.d/%u"`. + - Also added `mode = "0444"` to `/etc/ssh/ca.pub` and moved `TrustedUserCAKeys` into `services.openssh.settings`. + - **Configured OpenID Connect (OIDC) authentication for Mealie**: - Configured `services.mealie.settings` with OIDC settings pointing to Pocket ID (`auth.masu.rs`), using client ID `040925ed-b39e-4442-b8e8-369c948c0cd2`. - Added secret management for `mealie-oidc-secret.age` via `secrets.mealie-oidc-secret`, using `prefix = "OIDC_CLIENT_SECRET="` to generate an environment file. diff --git a/platforms/nixos/modules/nmasur/presets/services/cloudflared.nix b/platforms/nixos/modules/nmasur/presets/services/cloudflared.nix index 547c5bbf..bd2943c6 100644 --- a/platforms/nixos/modules/nmasur/presets/services/cloudflared.nix +++ b/platforms/nixos/modules/nmasur/presets/services/cloudflared.nix @@ -25,7 +25,7 @@ # Set ca = "" let - inherit (config.nmasur.settings) username; + inherit (config.nmasur.settings) username hostnames; cfg = config.nmasur.presets.services.cloudflared; in @@ -68,27 +68,24 @@ in # Grant Cloudflare access to SSH into this server environment.etc = { - "ssh/ca.pub".text = '' - ${cfg.tunnel.ca} - ''; - - # Must match the username portion of the email address in Cloudflare - # Access - "ssh/authorized_principals".text = '' - ${username} - ''; + "ssh/ca.pub" = { + text = '' + ${cfg.tunnel.ca} + ''; + mode = "0444"; + }; }; + users.users.${username}.openssh.authorizedPrincipals = [ + username + "${username}@${hostnames.mail}" + ]; + # Adjust SSH config to allow access from Cloudflare's certificate - services.openssh.extraConfig = '' - PubkeyAuthentication yes - TrustedUserCAKeys /etc/ssh/ca.pub - Match User '${username}' - AuthorizedPrincipalsFile /etc/ssh/authorized_principals - # if there is no existing AuthenticationMethods - AuthenticationMethods publickey - ''; - services.openssh.settings.Macs = [ "hmac-sha2-512" ]; # Fix for failure to find matching mac + services.openssh.settings = { + TrustedUserCAKeys = "/etc/ssh/ca.pub"; + Macs = [ "hmac-sha2-512" ]; # Fix for failure to find matching mac + }; # Create credentials file for Cloudflare secrets.cloudflared = {