Feature Specification: Component authelia

Created: 2026-10-07

Status: Implemented

Input: Reconstructed from the code at 093e68b6f (core/components/shared/authelia/default.nix, core/components/operator/operator-facing-options.csv, core/setups/hosts-common.nix, core/setups/groups/hosting-provider.nix, core/setups/groups/operator.nix, core/components/hosting-provider/default.nix, core/resources/oidc/), pull requests #1383, #1822, #1835, #1852 and #1874.

User Scenarios & Testing (mandatory)

User Story 1 - Give a group one single sign-on portal (Priority: P1)

Each group of a deployment needs one place where people sign in. The authelia component marks a node as the SSO portal of its group. It declares provides = [ "oidc" ], so this node answers the oidc requests of the group (see oidc). The setup then puts the daemon, the aggregated OIDC clients and the secret delivery on this node (see setups and wiring).

Why this priority: without the portal, no application of the group can sign a user in, and no admin UI behind forward-auth is reachable.

Independent Test: nix-unit-components-authelia covers the settings that the operator can set, and the postgresql storage of FR-007. nix-unit-testers-oidc-routing and nix-unit-setups-supporting-requests cover the routing of oidc requests to the provider node.

Acceptance Scenarios:

  1. Given a group with an authelia machine, When the setups evaluate, Then the "auth-server".oidc request of that node has enable = true, and its domain is auth.<domain>.
  2. Given an application that requests oidc, When the setups evaluate, Then the setup adds its client to the aggregated supportingRequests.oidc of the authelia node.

User Story 2 - Sign users in against the group directory (Priority: P2)

The group keeps its users in lldap. When the group has an lldap machine, the setup gives Authelia an LDAP first-factor backend. The bind account is the cross-node consumer authelia in the group authelia-users. OpenBao rotates its password (see ldap).

Why this priority: the portal works without a directory, but then it has no users to sign in.

Independent Test: test-ldap-engine. It covers the rotation of the authelia-bind password by the OpenBao LDAP engine.

Acceptance Scenarios:

  1. Given a group with authelia and lldap machines, When the setups evaluate, Then oidc.autheliaLdapBackend is set on the authelia node.
  2. Given a group with an smtp machine, When the setups evaluate, Then fediversity.authelia.smtp has a submission://<host>:<port> address, a sender and a password in KV.

User Story 3 - Show the portal in the catalog (Priority: P3)

A surface lists the components of a group with a name, an icon and a description. The component gives the name Authelia, the cropped logo of pkgs.authelia and uiSubdomain = "auth".

Why this priority: the catalog entry is informational.

Independent Test: applications-catalog.

Acceptance Scenarios:

  1. Given the catalog, When a surface renders it, Then the authelia entry shows logo-cropped.svg from the source of pkgs.authelia.

Edge Cases

  • A group without an lldap machine gets no LDAP backend. The portal then has no users from a directory.
  • A group without an smtp machine gets no notifier account in fediversity.authelia.smtp.
  • On the tf-incus-operator-hosts deployment, the LDAP engine is the mount ldapMountFor group ns on the central OpenBao. On the central group (the one group whose roster provides varsBackend) it is the ldap mount. Elsewhere it is null.
  • On the central group (the one group whose roster provides varsBackend), the setup also adds the OIDC clients of each group that sets centralLogin, such as the hypervisor group (aggregatedHypervisorOidc). The clients of such a group log in through the portal of the central group.
  • A group without a routed postgresql provider keeps the state in a local SQLite database, which has no offsite backup.

Requirements (mandatory)

Functional Requirements

  • FR-001: The component MUST declare provides = [ "oidc" ], so the node answers the oidc requests of its group.
  • FR-002: The component MUST declare uiSubdomain = "auth". The setup MUST compose the portal name and the OIDC issuer name from this one label.
  • FR-003: The implementation MUST request "spiffe".spiffe.enable = true, so the node logs in to OpenBao with its SVID and reads its rotated secrets.
  • FR-004: The implementation MUST publish TCP ports 80 and 443 through "web".firewall.publicTCPPorts, because people on the internet reach the login UI.
  • FR-005: The component MUST NOT request an admin-UI forward-auth oidc request for itself, because it is the portal.
  • FR-006: The setup MUST set the daemon configuration, the OIDC clients, the LDAP backend, the secret delivery and the SMTP notifier from the oidc resource.
  • FR-007: The implementation MUST request postgresql with database, consumer and user authelia, and the password file owner authelia-main. The settings module MUST render contracts.postgresql.results.authelia.default into storage.postgres, and MUST render nothing when the result is absent, so that the daemon keeps its local SQLite database.
  • FR-008: The implementation MUST request garage through mkBackupsGarageRequest with the bucket authelia-backups, and a streamingBackup of the postgres database to that bucket with the restic provider, as the user authelia-main.

Key Entities

  • "auth-server".oidc: the request of the setup on the portal node. It carries domain, cookieDomain, deploymentDomain, instanceName and deployAdminUIs.
  • oidc.autheliaLdapBackend: the bind account and the OpenBao LDAP engine for the first factor.
  • fediversity.authelia.smtp: the notifier account: address, username, sender and passwordKv.
  • operator-facing-options.csv: rows with application = authelia. 32 options have the audience fediversity and 14 have the audience operator.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: nix-unit-components-authelia, nix-unit-testers-oidc-routing and nix-unit-setups-supporting-requests pass.
  • SC-002: test-ldap-engine passes.
  • SC-003: applications-catalog passes with the authelia icon.

Assumptions

  • The hosting-provider and operator groups both declare an authelia machine. Each group runs its own portal.
  • core/components/hosting-provider/default.nix imports this component for both groups.
  • The OIDC provider implementation is in core/resources/oidc/, not in this component.

Known Deviations

None.