Authelia
Deploy Authelia on Kubernetes — a full-featured authentication and authorization server with single sign-on (SSO), multi-factor authentication (TOTP, WebAuthn/FIDO2), OpenID Connect identity provider, and forward-auth middleware support for Traefik, nginx, Caddy, and Envoy.
Authelia requires three secrets before it can start. The most critical is storageEncryptionKey (20+ chars), which
encrypts all MFA secrets stored in the database — TOTP keys and WebAuthn credentials. If this key is lost or rotated,
all MFA device registrations become permanently unreadable and users must re-enroll. Always persist all three
secrets via secrets.existingSecret before the first deployment.
| Secret | Minimum Length | Purpose |
|---|---|---|
jwtSecret | 64 chars | Signs identity tokens for password resets. |
sessionSecret | 64 chars | Encrypts session cookies. |
storageEncryptionKey | 20 chars | Encrypts MFA secrets (TOTP, WebAuthn) in the DB. |
Generate with: openssl rand -base64 64 | head -c 64
Key Features
- Forward auth middleware — native Traefik, nginx, Caddy, and Envoy integration
- MFA — TOTP, WebAuthn/FIDO2, and Duo Push
- OpenID Connect IdP — certified OIDC provider for app SSO
- File or LDAP auth backends — local YAML user database or LDAP/AD directory
- Access control rules — domain, user, group, network, and method policies
- Brute force protection — configurable regulation (
max_retries,ban_time) - Prometheus metrics with optional ServiceMonitor
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install authelia helmforge/authelia -f values.yaml
OCI registry:
helm install authelia oci://ghcr.io/helmforgedev/helm/authelia -f values.yaml
Deployment Examples
# values.yaml — Authelia with SQLite and file-based user database
secrets:
existingSecret: authelia-master-secrets
existingSecretJwtKey: jwt-secret # 64+ chars
existingSecretSessionKey: session-secret # 64+ chars
existingSecretStorageEncryptionKey: storage-encryption-key # 20+ chars
config:
session:
cookies:
- domain: example.com
authelia_url: 'https://auth.example.com'
default_redirection_url: 'https://www.example.com'
access_control:
default_policy: one_factor
rules:
- domain: 'public.example.com'
policy: bypass
- domain: '*.example.com'
policy: two_factor
notifier:
# filesystem notifier logs to /data/notification.txt — email not sent
# Switch to smtp notifier for production email delivery
filesystem:
filename: /data/notification.txt
usersDatabase:
enabled: true
users:
admin:
displayname: 'Administrator'
email: 'admin@example.com'
# Generate password hash: authelia crypto hash generate argon2 --password 'mypassword'
password: '$argon2id$v=19$m=65536,t=3,p=4$...'
groups:
- admins
persistence:
enabled: true
size: 1Gi
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: auth.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: authelia-tls
hosts:
- auth.example.com# values.yaml — Authelia HA: PostgreSQL + Redis (required for multi-replica)
replicaCount: 2 # requires Redis for session coordination
secrets:
existingSecret: authelia-master-secrets
config:
session:
cookies:
- domain: example.com
authelia_url: 'https://auth.example.com'
access_control:
default_policy: two_factor
notifier:
smtp:
address: 'submissions://smtp.example.com:465'
sender: 'Authelia <authelia@example.com>'
username: 'authelia@example.com'
password: 'smtp-password' # use extraEnv with secretKeyRef in production
postgresql:
enabled: true
auth:
database: authelia
username: authelia
password: 'strong-db-password'
redis:
enabled: true
auth:
password: 'strong-redis-password'
database:
type: postgres
persistence:
enabled: true
size: 1Gi
backup:
enabled: true
schedule: '0 2 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: authelia-backups
existingSecret: authelia-s3-credentials
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: auth.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Authelia configured for Traefik forwardAuth middleware
# After deploying, create a Traefik Middleware resource in the same namespace:
#
# apiVersion: traefik.io/v1alpha1
# kind: Middleware
# metadata:
# name: authelia
# spec:
# forwardAuth:
# address: http://authelia.authelia.svc.cluster.local/api/authz/forward-auth
# trustForwardHeader: true
# authResponseHeaders:
# - Remote-User
# - Remote-Groups
# - Remote-Name
# - Remote-Email
#
# Then add annotation to protected services:
# traefik.ingress.kubernetes.io/router.middlewares: <namespace>-authelia@kubernetescrd
secrets:
existingSecret: authelia-master-secrets
config:
session:
cookies:
- domain: example.com
authelia_url: 'https://auth.example.com'
access_control:
default_policy: one_factor
rules:
- domain: 'auth.example.com'
policy: bypass
- domain: '*.example.com'
policy: one_factor
usersDatabase:
enabled: true
users:
admin:
displayname: 'Admin'
email: 'admin@example.com'
password: '$argon2id$v=19$m=65536,t=3,p=4$...'
groups:
- admins
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: auth.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Authelia as OIDC identity provider
secrets:
existingSecret: authelia-master-secrets
existingSecretOidcHmacKey: oidc-hmac-secret # required for OIDC
config:
session:
cookies:
- domain: example.com
authelia_url: 'https://auth.example.com'
access_control:
default_policy: two_factor
identity_providers:
oidc:
clients:
- client_id: grafana
client_name: Grafana
client_secret: '$pbkdf2-sha512$310000$...' # hashed client secret
public: false
authorization_policy: two_factor
redirect_uris:
- 'https://grafana.example.com/login/generic_oauth'
scopes:
- openid
- profile
- email
- groups
userinfo_signed_response_alg: none
postgresql:
enabled: true
auth:
password: 'strong-db-password'
redis:
enabled: true
auth:
password: 'strong-redis-password'
database:
type: postgres
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: auth.example.com
paths:
- path: /
pathType: PrefixConfiguration Reference
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository | string | docker.io/authelia/authelia | Authelia image. |
image.tag | string | "4.39.16" | Image tag. |
Secrets
| Parameter | Type | Default | Description |
|---|---|---|---|
secrets.jwtSecret | string | "" | JWT signing secret (64+ chars). Required. |
secrets.sessionSecret | string | "" | Session cookie encryption secret (64+ chars). Required. |
secrets.storageEncryptionKey | string | "" | MFA data encryption key (20+ chars). Required. Never rotate. |
secrets.oidcHmacSecret | string | "" | OIDC HMAC secret. Required only when using OIDC. |
secrets.existingSecret | string | "" | Existing secret containing all secret keys. |
secrets.existingSecretJwtKey | string | jwt-secret | Key for JWT secret. |
secrets.existingSecretSessionKey | string | session-secret | Key for session secret. |
secrets.existingSecretStorageEncryptionKey | string | storage-encryption-key | Key for storage encryption key. |
secrets.existingSecretOidcHmacKey | string | oidc-hmac-secret | Key for OIDC HMAC secret. |
Configuration
The config block is rendered as Authelia’s configuration.yml. Key sub-sections:
| Section | Description |
|---|---|
config.session.cookies | Domain and Authelia URL for cookie scope (must match ingress). |
config.access_control.rules | Access control policies per domain, group, user, and network. |
config.access_control.default_policy | Default policy: bypass, one_factor, two_factor, deny. |
config.notifier.filesystem | Log notifications to file (no email). Default. |
config.notifier.smtp | SMTP notifier for email delivery (password resets, device enroll). |
config.totp | TOTP algorithm, period, digits. |
config.webauthn | WebAuthn/FIDO2 display name and timeout. |
config.regulation | Brute force: max_retries, find_time, ban_time. |
config.identity_providers.oidc | OIDC client registrations. |
Users Database
| Parameter | Type | Default | Description |
|---|---|---|---|
usersDatabase.enabled | boolean | true | Enable file-based user database at /config/users_database.yml. |
usersDatabase.existingSecret | string | "" | Existing secret with the users_database.yml content. |
usersDatabase.users | object | {} | Inline user definitions. Passwords must be Argon2 hashes. |
Authelia enforces Argon2id hashes for user passwords. Generate a hash using the CLI:
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'mypassword'The output hash goes in usersDatabase.users.<user>.password.
Database
| Parameter | Type | Default | Description |
|---|---|---|---|
database.type | string | sqlite | Storage backend: sqlite, postgres, mysql. |
database.external.host | string | "" | External database hostname. |
database.external.existingSecret | string | "" | Existing secret with database password. |
database.external.existingSecretPasswordKey | string | password | Key for the database password. |
Subcharts
| Parameter | Type | Default | Description |
|---|---|---|---|
postgresql.enabled | boolean | false | Deploy the bundled PostgreSQL subchart. |
postgresql.auth.password | string | "" | Password. Required when using the subchart. |
mysql.enabled | boolean | false | Deploy the bundled MySQL subchart. |
redis.enabled | boolean | false | Deploy the bundled Redis subchart (required for HA). |
redis.auth.password | string | "" | Password. Required when using the subchart. |
Persistence, Service, Metrics
| Parameter | Type | Default | Description |
|---|---|---|---|
persistence.enabled | boolean | true | Enable PVC for /data (SQLite DB, filesystem notifier). |
persistence.size | string | 1Gi | PVC size. |
service.port | integer | 80 | Service port (Authelia listens on 9091). |
metrics.enabled | boolean | false | Enable separate metrics service on port 9959. |
metrics.serviceMonitor.enabled | boolean | false | Enable Prometheus ServiceMonitor. |
Backup
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled | boolean | false | Enable scheduled S3 backup CronJob. |
backup.schedule | string | "0 2 * * *" | Cron schedule. |
backup.s3.endpoint | string | "" | S3-compatible endpoint URL. |
backup.s3.bucket | string | "" | Target bucket name. |
backup.s3.existingSecret | string | "" | Existing secret with S3 credentials. |
extraManifests | array | [] | Extra Kubernetes manifests. |