Authelia is the authentication layer I put in front of services that should not be directly accessible from the Internet.
The idea is simple:
Internet
│
▼
Traefik
│
├──► Authelia
│ │
│ └──► MariaDB
│
▼
Protected application
Traefik remains responsible for ingress and TLS. Before forwarding a request to a protected application, it asks Authelia whether that request should be allowed.
This gives me one authentication policy instead of implementing authentication independently in every application.
My deployment currently runs Authelia 4.39.20 on Kubernetes using Kustomize and Rancher Fleet.
Why Authelia?
A homelab eventually accumulates applications with very different authentication capabilities.
Some support OIDC properly. Some have basic local authentication. Some have no authentication worth trusting on the public Internet.
Rather than solving that problem separately in every application, I use Authelia as a shared authentication gateway.
user
↓
Traefik
↓
Authelia policy
↓
MFA if required
↓
application
For Internet-facing services, my default policy is two-factor authentication. Trusted internal or VPN networks can bypass MFA for selected applications where forcing a browser authentication flow would be impractical.
The important part is that bypasses are explicit exceptions rather than the default.
Authentication methods
My current setup supports three second-factor mechanisms:
- TOTP as the normal MFA mechanism
- Duo Push for phone-based approval
- WebAuthn for compatible authenticators
TOTP is intentionally the baseline. It is simple, portable and does not make the authentication platform entirely dependent on an external push provider. Duo remains a convenient additional option, while WebAuthn gives me a stronger path where supported.
Deployment layout
I keep a reusable base and cluster-specific overlays:
authelia/
├── base/
│ └── kustomization.yaml
└── overlays/
├── homelab/
├── local/
└── jls/
Fleet reconciles the appropriate overlay into each target cluster. The application lives in the auth namespace and consists primarily of an Authelia Deployment and a MariaDB StatefulSet.
This keeps common configuration centralised while allowing environment-specific storage, routing and resources to remain in overlays. It is much easier to reason about than three nearly identical copies of the entire deployment.
Configuration and secrets
Authelia needs considerably more secret material than a typical stateless application. The deployment depends on values for:
session encryption
storage encryption
identity validation
database access
mail delivery
MFA providers
Those values must survive disaster recovery.
Losing the workload is mostly harmless. Losing encryption keys while retaining the database is considerably more interesting.
My recovery rule is therefore:
Configuration, database and cryptographic secrets belong to the same recovery plan.
Secrets currently come from Kubernetes Secret manifests managed with the deployment. Moving them to a dedicated secret-management system is a separate migration. Changing the storage mechanism and rotating authentication secrets at the same time would make rollback unnecessarily difficult.
Database
Authelia currently uses MariaDB. The database preserves session and service state, so it runs as a StatefulSet with persistent storage.
For a new deployment I would evaluate PostgreSQL first, but there is little value in migrating a working authentication database merely for architectural aesthetics.
A database migration deserves its own sequence:
backup
→ migration
→ validation
→ rollback plan
It should not be hidden inside an Authelia upgrade.
SMTP matters more than it looks
Mail delivery is part of the authentication system. Password resets and identity workflows depend on it, which means authentication can appear partially functional even when SMTP is broken.
After changing mail configuration I test a complete workflow rather than checking only whether the Authelia pod is Ready.
A healthy pod does not necessarily mean a healthy authentication service.
Operating Authelia
When authentication starts behaving strangely, I inspect the complete request chain instead of immediately restarting Authelia.
My first commands are usually:
kubectl -n auth get pods,svc,pvc,ingressroute
kubectl -n auth get deploy,statefulset
kubectl -n auth logs deploy/authelia --tail=200
Then I validate the active configuration:
kubectl -n auth exec deploy/authelia -- \
authelia validate-config \
--config /config/configuration.yaml
This catches a surprising number of problems before deeper investigation becomes necessary.
Check the database too
Because an authentication request crosses several components, inspecting only Authelia can be misleading.
kubectl -n auth describe deploy authelia
kubectl -n auth describe statefulset authelia-db
kubectl -n auth logs statefulset/authelia-db --tail=100
The failure patterns I care about most are:
Authelia
├── database connectivity
├── invalid or missing secrets
├── mail failures
├── MFA enrolment problems
└── stale sessions after secret rotation
Traefik
└── broken forward-auth middleware
MariaDB
└── unavailable or damaged persistent state
Authentication redirect loops are particularly useful clues. They often indicate that each component is individually running but the integration between Traefik, Authelia and the application is wrong.
Resource sizing
Authelia itself is inexpensive for my workload:
CPU request 100m
Memory request 128 MiB
Memory limit 512 MiB
One environment receives more headroom. The extra capacity is mainly useful during memory-intensive password hashing such as Argon2.
MariaDB currently requests 50m CPU and 128 MiB memory with a 512 MiB memory limit.
I change these values in Git and let GitOps reconcile them rather than editing live resources. Actual use can be checked with:
kubectl -n auth top pod
Backup and recovery
Because Authelia sits in front of several applications, I treat it as a Tier-1 homelab service.
The useful backup set is not simply the PVC:
MariaDB data
+
Authelia secrets
+
configuration
+
Traefik integration
My recovery order is:
1. Restore secrets
2. Restore database or PVC state
3. Reconcile the GitOps overlay
4. Wait for Authelia and MariaDB
5. Validate configuration
6. Test forward authentication against a real protected application
The final step matters. Seeing 1/1 Running is not a recovery test. Successfully authenticating through Traefik is.
Rollback
Application changes are deployed through Git, so the normal rollback is equally boring:
revert Git revision
↓
Fleet reconciliation
↓
previous known-good state
If an upgrade modified persistent state, the corresponding database snapshot may also have to be restored.
Authentication policy changes need slightly different treatment. If an MFA policy unexpectedly locks users out, I revert the access-control rule rather than changing encryption secrets in an attempt to regain access.
Change the smallest thing necessary.
Things worth remembering
Authelia itself is not particularly difficult to run. The interesting part is everything around it.
It sits at the intersection of:
DNS
TLS
Traefik
sessions
database
mail
secrets
MFA
application routing
That means an “Authelia outage” frequently is not an Authelia outage.
At the time of writing:
Authelia 4.39.20
Ingress Traefik
Database MariaDB
Deployment Kustomize + Rancher Fleet
MFA default TOTP
Additional Duo Push + WebAuthn
Backups database + secrets + PVC snapshot
Authentication is one of the places where I prefer boring components, explicit recovery procedures and predictable Git history over clever infrastructure.
The service only becomes interesting when it disappears. Ideally, it does not.