From 1df2a4c729309228f605266ea7acc430fa06c9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A9meint?= Date: Mon, 27 Apr 2026 18:08:53 +0200 Subject: [PATCH] nixos/authelia: Make secrets available to the service even if not readable by the authelia user --- .../manual/release-notes/rl-2611.section.md | 2 + nixos/modules/services/security/authelia.nix | 44 +++++++++++-------- nixos/tests/authelia.nix | 2 - 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2611.section.md b/nixos/doc/manual/release-notes/rl-2611.section.md index 5eec5286eb9f..d9de29b0c06e 100644 --- a/nixos/doc/manual/release-notes/rl-2611.section.md +++ b/nixos/doc/manual/release-notes/rl-2611.section.md @@ -142,6 +142,8 @@ - The `newuidmap` and `newgidmap` security wrappers are now installed with `cap_setuid`/`cap_setgid` file capabilities instead of the setuid-root bit, matching shadow's `--with-fcaps` install mode and other major distributions. Rootless containers (podman, docker-rootless, unprivileged user namespaces) are unaffected. The only behavioural change is that mapping host uid 0 via `/etc/subuid` (which NixOS never configures by default) additionally requires `cap_setfcap`; users who explicitly grant uid 0 in a subuid range can restore the previous behaviour with `security.wrappers.newuidmap.capabilities = lib.mkForce "cap_setuid,cap_setfcap+ep";`. +- The `authelia` module now uses systemd's `LoadCredential` to load all files defined in `secrets`. As such, these files no longer need to be readable by the authelia user and group: they can for example be set to be only readable by the root user. + - `zoneminder` has been updated to 1.38.x release. See [upstream release note](https://github.com/ZoneMinder/zoneminder/releases/tag/1.38.0). While database migration should happen automatically, it's recommended that you make a backup of the database before upgrading your system. - The latest available version of Nextcloud is v34 (available as `pkgs.nextcloud34`). The installation logic is as follows: diff --git a/nixos/modules/services/security/authelia.nix b/nixos/modules/services/security/authelia.nix index f8bcc4bb15b9..5fe0d6bc23e3 100644 --- a/nixos/modules/services/security/authelia.nix +++ b/nixos/modules/services/security/authelia.nix @@ -268,15 +268,6 @@ let }; }; - writeOidcJwksConfigFile = - oidcIssuerPrivateKeyFile: - pkgs.writeText "oidc-jwks.yaml" '' - identity_providers: - oidc: - jwks: - - key: {{ secret "${oidcIssuerPrivateKeyFile}" | mindent 10 "|" | msquote }} - ''; - # Remove an attribute in a nested set # https://discourse.nixos.org/t/modify-an-attrset-in-nix/29919/5 removeAttrByPath = @@ -362,7 +353,12 @@ in execCommand = "${instance.package}/bin/authelia"; configFile = format.generate "config.yml" cleanedSettings; oidcJwksConfigFile = lib.optional (instance.secrets.oidcIssuerPrivateKeyFile != null) ( - writeOidcJwksConfigFile instance.secrets.oidcIssuerPrivateKeyFile + pkgs.writeText "oidc-jwks.yaml" '' + identity_providers: + oidc: + jwks: + - key: {{ mustEnv "CREDENTIALS_DIRECTORY" | printf "%s/oidcIssuerPrivateKeyFile" | secret | mindent 10 "|" | msquote }} + '' ); configArg = "--config ${ builtins.concatStringsSep "," ( @@ -373,21 +369,25 @@ in ] ) }"; + # Mapping between the Authelia env variables and the secret keys defined in the module + envSecretsMap = { + AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE = "jwtSecretFile"; + AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = "storageEncryptionKeyFile"; + AUTHELIA_SESSION_SECRET_FILE = "sessionSecretFile"; + AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = "oidcHmacSecretFile"; + }; + nonNullEnvSecretsMap = lib.filterAttrs (_: v: instance.secrets.${v} != null) envSecretsMap; in { description = "Authelia authentication and authorization server"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; # Checks SMTP notifier creds during startup wants = [ "network-online.target" ]; - environment = - (lib.filterAttrs (_: v: v != null) { - X_AUTHELIA_CONFIG_FILTERS = lib.mkIf (oidcJwksConfigFile != [ ]) "template"; - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE = instance.secrets.jwtSecretFile; - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = instance.secrets.storageEncryptionKeyFile; - AUTHELIA_SESSION_SECRET_FILE = instance.secrets.sessionSecretFile; - AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = instance.secrets.oidcHmacSecretFile; - }) - // instance.environmentVariables; + environment = { + X_AUTHELIA_CONFIG_FILTERS = lib.mkIf (oidcJwksConfigFile != [ ]) "template"; + } + // lib.mapAttrs (_: v: "%d/${v}") nonNullEnvSecretsMap + // instance.environmentVariables; preStart = "${execCommand} ${configArg} validate-config"; serviceConfig = { @@ -399,6 +399,12 @@ in StateDirectory = autheliaName instance.name; StateDirectoryMode = "0700"; + LoadCredential = + lib.optional ( + instance.secrets.oidcIssuerPrivateKeyFile != null + ) "oidcIssuerPrivateKeyFile:${instance.secrets.oidcIssuerPrivateKeyFile}" + ++ lib.mapAttrsToList (_: v: "${v}:${instance.secrets.${v}}") nonNullEnvSecretsMap; + # Security options: AmbientCapabilities = ""; CapabilityBoundingSet = ""; diff --git a/nixos/tests/authelia.nix b/nixos/tests/authelia.nix index 98abca0fbc57..256c92cd706e 100644 --- a/nixos/tests/authelia.nix +++ b/nixos/tests/authelia.nix @@ -28,12 +28,10 @@ # This is purely for testing purposes! environment.etc."authelia/storageEncryptionKeyFile" = { mode = "0400"; - user = "authelia-testing"; text = "you_must_generate_a_random_string_of_more_than_twenty_chars_and_configure_this"; }; environment.etc."authelia/jwtSecretFile" = { mode = "0400"; - user = "authelia-testing"; text = "a_very_important_secret"; }; environment.etc."authelia/users_database.yml" = {