8 cfg = config.services.authelia;
10 format = pkgs.formats.yaml { };
12 autheliaOpts = with lib; { name, ... }: {
14 enable = mkEnableOption "Authelia instance";
20 Name is used as a suffix for the service name, user, and group.
21 By default it takes the value you use for `<instance>` in:
22 {option}`services.authelia.<instance>`
26 package = mkPackageOption pkgs "authelia" { };
29 default = "authelia-${name}";
31 description = "The name of the user for this authelia instance.";
35 default = "authelia-${name}";
37 description = "The name of the group for this authelia instance.";
42 It is recommended you keep your secrets separate from the configuration.
43 It's especially important to keep the raw secrets out of your nix configuration,
44 as the values will be preserved in your nix store.
45 This attribute allows you to configure the location of secret files to be loaded at runtime.
47 https://www.authelia.com/configuration/methods/secrets/
50 type = types.submodule {
56 Configuring authelia's secret files via the secrets attribute set
57 is intended to be convenient and help catch cases where values are required
59 If a user wants to set these values themselves and bypass the validation they can set this value to true.
65 jwtSecretFile = mkOption {
66 type = types.nullOr types.path;
69 Path to your JWT secret used during identity verificaton.
73 oidcIssuerPrivateKeyFile = mkOption {
74 type = types.nullOr types.path;
77 Path to your private key file used to encrypt OIDC JWTs.
81 oidcHmacSecretFile = mkOption {
82 type = types.nullOr types.path;
85 Path to your HMAC secret used to sign OIDC JWTs.
89 sessionSecretFile = mkOption {
90 type = types.nullOr types.path;
93 Path to your session secret. Only used when redis is used as session storage.
98 storageEncryptionKeyFile = mkOption {
99 type = types.nullOr types.path;
102 Path to your storage encryption key.
109 environmentVariables = mkOption {
110 type = types.attrsOf types.str;
112 Additional environment variables to provide to authelia.
113 If you are providing secrets please consider the options under {option}`services.authelia.<instance>.secrets`
114 or make sure you use the `_FILE` suffix.
115 If you provide the raw secret rather than the location of a secret file that secret will be preserved in the nix store.
116 For more details: https://www.authelia.com/configuration/methods/secrets/
121 settings = mkOption {
123 Your Authelia config.yml as a Nix attribute set.
124 There are several values that are defined and documented in nix such as `default_2fa_method`,
125 but additional items can also be included.
127 https://github.com/authelia/authelia/blob/master/config.template.yml
133 default_2fa_method = "totp";
135 server.disable_healthcheck = true;
138 type = types.submodule {
139 freeformType = format.type;
142 type = types.enum [ "light" "dark" "grey" "auto" ];
145 description = "The theme to display.";
148 default_2fa_method = mkOption {
149 type = types.enum [ "" "totp" "webauthn" "mobile_push" ];
151 example = "webauthn";
153 Default 2FA method for new users and fallback for preferred but disabled methods.
160 default = "tcp://:9091/";
161 example = "unix:///var/run/authelia.sock?path=authelia&umask=0117";
162 description = "The address to listen on.";
168 type = types.enum [ "trace" "debug" "info" "warn" "error" ];
171 description = "Level of verbosity for logs.";
175 type = types.enum [ "json" "text" ];
178 description = "Format the logs are written as.";
181 file_path = mkOption {
182 type = types.nullOr types.path;
184 example = "/var/log/authelia/authelia.log";
185 description = "File path where the logs will be written. If not set logs are written to stdout.";
188 keep_stdout = mkOption {
192 description = "Whether to also log to stdout when a `file_path` is defined.";
202 description = "Enable Metrics.";
207 default = "tcp://127.0.0.1:9959";
208 example = "tcp://0.0.0.0:8888";
209 description = "The address to listen on for metrics. This should be on a different port to the main `server.port` value.";
217 settingsFiles = mkOption {
218 type = types.listOf types.path;
220 example = [ "/etc/authelia/config.yml" "/etc/authelia/access-control.yml" "/etc/authelia/config/" ];
222 Here you can provide authelia with configuration files or directories.
223 It is possible to give authelia multiple files and use the nix generated configuration
224 file set via {option}`services.authelia.<instance>.settings`.
230 writeOidcJwksConfigFile = oidcIssuerPrivateKeyFile: pkgs.writeText "oidc-jwks.yaml" ''
234 - key: {{ secret "${oidcIssuerPrivateKeyFile}" | mindent 10 "|" | msquote }}
237 # Remove an attribute in a nested set
238 # https://discourse.nixos.org/t/modify-an-attrset-in-nix/29919/5
239 removeAttrByPath = set: pathList:
240 lib.updateManyAttrsByPath [{
241 path = lib.init pathList;
243 lib.filterAttrs (n: v: n != (lib.last pathList)) old;
248 options.services.authelia.instances = with lib; mkOption {
250 type = types.attrsOf (types.submodule autheliaOpts);
252 Multi-domain protection currently requires multiple instances of Authelia.
253 If you don't require multiple instances of Authelia you can define just the one.
255 https://www.authelia.com/roadmap/active/multi-domain-protection/
261 secrets.storageEncryptionKeyFile = "/etc/authelia/storageEncryptionKeyFile";
262 secrets.jwtSecretFile = "/etc/authelia/jwtSecretFile";
265 default_2fa_method = "totp";
267 server.disable_healthcheck = true;
272 secrets.storageEncryptionKeyFile = "/mnt/pre-prod/authelia/storageEncryptionKeyFile";
273 secrets.jwtSecretFile = "/mnt/pre-prod/jwtSecretFile";
276 default_2fa_method = "webauthn";
277 server.host = "0.0.0.0";
281 test.secrets.manual = true;
282 test.settings.theme = "grey";
283 test.settings.server.disable_healthcheck = true;
284 test.settingsFiles = [ "/mnt/test/authelia" "/mnt/test-authelia.conf" ];
292 mkInstanceServiceConfig = instance:
295 if (instance.settings.server?host || instance.settings.server?port || instance.settings.server?path) then
296 # Old settings are used: display a warning and remove the default value of server.address
297 # as authelia does not allow both old and new settings to be set
298 lib.warn "Please replace services.authelia.instances.${instance.name}.settings.{host,port,path} with services.authelia.instances.${instance.name}.settings.address, before release 5.0.0"
299 (removeAttrByPath instance.settings [ "server" "address" ])
303 execCommand = "${instance.package}/bin/authelia";
304 configFile = format.generate "config.yml" cleanedSettings;
305 oidcJwksConfigFile = lib.optional (instance.secrets.oidcIssuerPrivateKeyFile != null) (writeOidcJwksConfigFile instance.secrets.oidcIssuerPrivateKeyFile);
306 configArg = "--config ${builtins.concatStringsSep "," (lib.concatLists [[configFile] instance.settingsFiles oidcJwksConfigFile])}";
309 description = "Authelia authentication and authorization server";
310 wantedBy = [ "multi-user.target" ];
311 after = [ "network.target" ];
313 (lib.filterAttrs (_: v: v != null) {
314 X_AUTHELIA_CONFIG_FILTERS = lib.mkIf (oidcJwksConfigFile != [ ]) "template";
315 AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE = instance.secrets.jwtSecretFile;
316 AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = instance.secrets.storageEncryptionKeyFile;
317 AUTHELIA_SESSION_SECRET_FILE = instance.secrets.sessionSecretFile;
318 AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = instance.secrets.oidcHmacSecretFile;
320 // instance.environmentVariables;
322 preStart = "${execCommand} ${configArg} validate-config";
324 User = instance.user;
325 Group = instance.group;
326 ExecStart = "${execCommand} ${configArg}";
329 StateDirectory = "authelia-${instance.name}";
330 StateDirectoryMode = "0700";
333 AmbientCapabilities = "";
334 CapabilityBoundingSet = "";
336 LockPersonality = true;
337 MemoryDenyWriteExecute = true;
338 NoNewPrivileges = true;
341 PrivateDevices = true;
345 ProtectControlGroups = true;
346 ProtectHome = "read-only";
347 ProtectHostname = true;
348 ProtectKernelLogs = true;
349 ProtectKernelModules = true;
350 ProtectKernelTunables = true;
351 ProtectProc = "noaccess";
352 ProtectSystem = "strict";
354 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
355 RestrictNamespaces = true;
356 RestrictRealtime = true;
357 RestrictSUIDSGID = true;
359 SystemCallArchitectures = "native";
360 SystemCallErrorNumber = "EPERM";
373 mkInstanceUsersConfig = instance: {
374 groups."authelia-${instance.name}" =
375 lib.mkIf (instance.group == "authelia-${instance.name}") {
376 name = "authelia-${instance.name}";
378 users."authelia-${instance.name}" =
379 lib.mkIf (instance.user == "authelia-${instance.name}") {
380 name = "authelia-${instance.name}";
382 group = instance.group;
385 instances = lib.attrValues cfg.instances;
388 assertions = lib.flatten (lib.flip lib.mapAttrsToList cfg.instances (name: instance:
391 assertion = instance.secrets.manual || (instance.secrets.jwtSecretFile != null && instance.secrets.storageEncryptionKeyFile != null);
393 Authelia requires a JWT Secret and a Storage Encryption Key to work.
394 Either set them like so:
395 services.authelia.${name}.secrets.jwtSecretFile = /my/path/to/jwtsecret;
396 services.authelia.${name}.secrets.storageEncryptionKeyFile = /my/path/to/encryptionkey;
397 Or set services.authelia.${name}.secrets.manual = true and provide them yourself via
398 environmentVariables or settingsFiles.
399 Do not include raw secrets in nix settings.
405 systemd.services = lib.mkMerge
407 (instance: lib.mkIf instance.enable {
408 "authelia-${instance.name}" = mkInstanceServiceConfig instance;
413 (instance: lib.mkIf instance.enable (mkInstanceUsersConfig instance))