Deployment guide

Self-hosting Authelia on a VPS: MFA and SSO for your entire stack

Deploy on a VPS Cloud →

Tutorial

Self-hosting Authelia on a VPS: MFA and SSO for your entire stack

Security & Monitoring10 min read9 steps

Authelia is an open-source authentication gateway written in Go that sits in front of your self-hosted services via your reverse proxy. In a single lightweight container (~30 MB), it centralizes authentication, enforces MFA, and can act as an OIDC provider for true SSO across your entire stack. This guide covers the full installation, group-based access rules, available MFA methods — including WebAuthn passkeys — migration to LLDAP, smooth upgrades, and monitoring.

Contents· Why an authentication gateway in the reverse proxy1/13
  1. 01Why an authentication gateway in the reverse proxy
  2. 02What self-hosted Authelia gives you
  3. 03Prerequisites
  4. 04Deploy Authelia with Docker Compose
  5. 05Use Authelia as an OIDC provider for true SSO
  6. 06Access control rules: concrete examples
  7. 07MFA: TOTP, WebAuthn/passkey and Duo
  8. 08Migrating to LLDAP: team management
  9. 09Updating Authelia: avoiding breaking changes
  10. 10Monitoring: logs and Prometheus metrics
  11. 11Authelia vs Authentik: which one to choose?
  12. 12Troubleshooting common errors
  13. 13Final advice: start simple, evolve progressively

Why an authentication gateway in the reverse proxy

Without a centralized gateway, each service manages its own login: Grafana has its own user database, Nextcloud has its own, Portainer has its own. The result: different passwords everywhere, no consistent MFA, and a multiplied attack surface. Authelia solves this by intercepting the HTTP flow: your reverse proxy (Nginx, Traefik, Caddy) submits each request to it before relaying it, and Authelia decides — based on identity, group, requested path, and required MFA level — whether the request should pass. The protected application only sees an authenticated request with injected identity headers (Remote-User, Remote-Groups). It doesn't need to manage authentication itself.

What self-hosted Authelia gives you

  • Centralized authentication for all your services without modifying their code
  • Native MFA: TOTP (Google Authenticator, Aegis), WebAuthn/passkey (hardware keys, Touch ID, Windows Hello), Duo
  • OIDC provider in production since v4.34: your OIDC-compatible apps delegate auth to Authelia
  • Granular access control by domain, path, user group, and authentication level
  • Native integration with Traefik (forwardAuth), Nginx (auth_request), Caddy (forward_auth)
  • LDAP/Active Directory support for team management, compatible with LLDAP
  • Single Go binary (~30 MB), lightweight Docker image, low memory footprint
  • Structured JSON logs and Prometheus metrics for observability

Prerequisites

Before deploying Authelia, verify that your environment is ready. You need a Linux VPS with Docker and Docker Compose installed, an existing reverse proxy (Traefik v2/v3 or Nginx), a domain name with a valid TLS certificate (Let's Encrypt recommended), and a Redis instance accessible by Authelia to store sessions (required in production for persistence and scalability). For user storage, you can start with a local YAML file or connect an LDAP server like LLDAP. Authelia also requires a JWT key, a session encryption key, and an OIDC secret if you enable that mode: generate them with openssl rand -hex 32.

Deploy Authelia with Docker Compose

  1. Create the directory structure

    Create /opt/authelia/config/ for configuration files and /opt/authelia/data/ for SQLite storage and keys. Set appropriate permissions: mkdir -p /opt/authelia/{config,data} && chown -R 1000:1000 /opt/authelia.

  2. Write the configuration.yml file

    Create /opt/authelia/config/configuration.yml. Define default_redirection_url, jwt_secret, session.secret, storage.encryption_key, configure the authentication backend (file or LDAP), Redis for sessions, and the default access policy (deny recommended).

  3. Create the users_database.yml file (file backend)

    For a quick start, create /opt/authelia/config/users_database.yml with your users. Passwords must be hashed with Argon2id: docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'YourPassword'. Copy the generated hash into the file.

  4. Configure Redis for sessions

    Add Redis to your docker-compose.yml. In configuration.yml, set session.redis.host: redis and session.redis.port: 6379. Redis is essential for sessions to survive Authelia restarts.

  5. Write the docker-compose.yml

    Define the authelia, redis services, and if you use Traefik, add the appropriate labels. Mount /opt/authelia/config read-only and /opt/authelia/data read-write. Expose port 9091 internally, never directly to the Internet.

  6. Configure Traefik with forwardAuth

    Create a Traefik middleware pointing to http://authelia:9091/api/authz/forward-auth. Apply this middleware to routers of services to protect via the label traefik.http.routers.<service>.middlewares: authelia@docker. For Nginx, use auth_request /authelia with the appropriate proxy_pass directives.

  7. Configure the session domain

    In configuration.yml, set session.domain to your root domain (e.g., mydomain.com) so the cookie is shared between subdomains. This is the most common cause of redirect loops: if session.domain doesn't match the domain of the protected service, the cookie is never sent back.

  8. Start and validate

    Start with docker compose up -d. Check logs: docker compose logs -f authelia. Access https://auth.mydomain.com to see the login portal. Test by accessing a protected service: you should be redirected to the portal, then sent back to the service after authentication.

  9. Enable the OIDC provider (optional)

    Since v4.34, the OIDC provider is production-ready. Add the identity_providers.oidc section to your configuration with your clients (Nextcloud, Grafana, Gitea…). Each client has an id, a secret (hashed with Argon2id), and its allowed redirect_uris. Your OAuth2-compatible apps can then fully delegate authentication to Authelia.

Use Authelia as an OIDC provider for true SSO

OIDC provider mode turns Authelia into true SSO: the user logs in once on the Authelia portal, and all applications configured as OIDC clients retrieve the identity without asking for a password again. Nextcloud, Grafana, Gitea, Portainer, Outline… all support OIDC. Configure each client with client_id, client_secret, and point the discovery URL to https://auth.mydomain.com/.well-known/openid-configuration. The groups scope allows transmitting Authelia groups to client applications for role management.

Access control rules: concrete examples

The access_control section is the heart of Authelia's logic. Since v4.37, policies have been reworked. Here are representative examples. For public access without auth: {domain: 'status.mydomain.com', policy: bypass}. For strong MFA access restricted to admins: {domain: 'portainer.mydomain.com', subject: 'group:admins', policy: two_factor}. For an API path without auth (webhooks): {domain: 'n8n.mydomain.com', resources: ['^/webhook/.*'], policy: bypass}. For the rest of N8N with simple MFA: {domain: 'n8n.mydomain.com', policy: one_factor}. The default_policy: deny rule ensures that anything not explicitly listed is blocked. Rule order matters: the first matching rule applies. The subject field accepts user:alice, group:admins, or a combined list.

MFA: TOTP, WebAuthn/passkey and Duo

Authelia supports three second-factor methods, each with its advantages.

TOTP (Time-based One-Time Password) is the most universal method: the user scans a QR code with an app like Aegis (Android), Raivo (iOS), or Bitwarden Authenticator. A 6-digit code changes every 30 seconds. Simple to deploy, compatible with all devices, but vulnerable to phishing if the code is intercepted in transit.

WebAuthn/passkey is the most robust method, natively supported by Authelia since v4.36. The user registers a hardware key (YubiKey, Nitrokey) or a platform authenticator (Touch ID on macOS, Windows Hello, Face ID on iOS). Public-key cryptography makes phishing impossible: the private key never leaves the device. Authelia implements the full WebAuthn Level 2 spec, which includes synchronized passkeys (via iCloud Keychain or Google Password Manager) in addition to hardware keys.

Duo delegates the second factor to the Duo Security cloud service: mobile push, SMS, or phone call. Convenient for teams already using Duo, but introduces a dependency on a third-party service.

For most self-hosted stacks, the recommended combination is TOTP as the base method and WebAuthn as the preferred method for users who have a YubiKey or a recent Apple/Windows device.

Migrating to LLDAP: team management

The file backend (users_database.yml) works for one user or a small household, but becomes difficult to manage beyond 5-10 users. LLDAP (Light LDAP) is a lightweight LDAP implementation written in Rust, with a simple web interface, that integrates perfectly with Authelia.

Deploy LLDAP by adding its service to your docker-compose.yml with the LLDAP_JWT_SECRET and LLDAP_LDAP_BASE_DN variables (e.g., dc=mydomain,dc=com). Create your groups in the LLDAP interface (admins, users, devops…), then modify your configuration.yml to switch from the file backend to the ldap backend: define authentication_backend.ldap.url, base_dn, users_filter ((&(uid={input})(objectClass=person))), groups_filter, user (the LLDAP service account), and password.

Note the v4.35 breaking change: the field was called authentification_backend (with a typo) before v4.35 and was corrected to authentication_backend. Check your configuration if migrating from an earlier version.

Updating Authelia: avoiding breaking changes

Authelia follows strict semantic versioning and documents its breaking changes per version. Here are the notable changes to know for clean migrations.

v4.34: the OIDC provider goes to production. If you were using it in experimental mode, some options have been renamed.

v4.35: correction of the typo authentification_backend → authentication_backend. Any configuration using the old name must be updated before upgrading to v4.35+, otherwise Authelia refuses to start with a configuration validation error.

v4.37: rework of access_control policies. Rule syntax has evolved to be more explicit. Check the official changelog before upgrading from v4.36 or earlier.

v4.38.x (current version): stabilization, no major breaking change since v4.37.

Recommended update procedure: (1) read the changelog from your current version; (2) back up /opt/authelia/config/ and /opt/authelia/data/; (3) test the new configuration with docker run --rm -v /opt/authelia/config:/config authelia/authelia:4.38.x authelia validate-config before restarting; (4) update the tag in docker-compose.yml and restart. The validate-config command catches schema errors before deployment.

Monitoring: logs and Prometheus metrics

Authelia exposes its Prometheus metrics on /metrics (configurable port, default 9959). Enable them in configuration.yml with telemetry.metrics.enabled: true and telemetry.metrics.address: 'tcp://0.0.0.0:9959'. Don't expose this port publicly: only expose it to your internal monitoring stack.

Key metrics to monitor: authelia_authn_requests_total (total authentication attempts, labeled by success/failure), authelia_authn_duration_seconds (authentication latency), and underlying Redis metrics for session health.

For logs, Authelia supports structured JSON format (log.format: json) ideal for ingestion into Loki or a SIEM. Set log.level: info in production (avoid debug which logs full headers). Authentication logs include source IP, username, target service, and result — valuable for detecting brute-force attempts.

In Grafana, create an alert on an abnormal authentication failure rate (e.g., more than 10 failures in 5 minutes on the same user) to detect dictionary attacks before they succeed.

Authelia vs Authentik: which one to choose?

Scroll the table

CriterionAutheliaAuthentik
Docker footprint~30 MB (Go binary)~1.5 GB (Python/Django + worker)
Minimum RAM~50 MB~512 MB recommended
OIDC providerYes, since v4.34Yes, mature and feature-rich
SAML providerNoYes
Admin interfaceYAML configuration onlyFull web interface
Application proxyNoYes (Authentik tunnels)
SCIM provisioningNoYes
Ideal use caseLightweight stack, pure reverse proxy, config as codeFull IAM, enterprise SSO, SAML/SCIM needs

Troubleshooting common errors

Infinite redirect loop. The user is bounced in a loop between the service and the Authelia portal without ever logging in. Most common cause: session.domain doesn't match the service's domain. If your service is on app.mydomain.com and session.domain is otherdomain.com, the session cookie is never sent back. Also check that the forwardAuth middleware is properly applied and that default_redirection_url points to a valid URL.

Cookie domain mismatch. The browser refuses to send the cookie back. Cause: session.domain must be the common parent domain (mydomain.com), not a subdomain. Verify with DevTools (Application tab > Cookies) that the authelia_session cookie has the correct domain.

Redis unreachable. Authelia starts but sessions don't persist, or the log shows Error connecting to Redis. Verify that the Redis container is on the same Docker network as Authelia, that host in configuration.yml matches the Docker service name (not localhost), and that Redis isn't protected by a password not configured on the Authelia side.

Invalid configuration on startup. Since v4.35, the configuration schema is strictly validated. Use authelia validate-config before any restart. Most common errors: authentification_backend (old typo), wrong YAML indentation, or missing OIDC field (client_secret must be hashed with Argon2id since v4.37).

MFA not prompted despite two_factor in rules. Check that the user has registered a second factor in their profile (https://auth.mydomain.com). Without a registered MFA device, Authelia may fall back to one_factor depending on your default_2fa_method configuration.

Final advice: start simple, evolve progressively

First deploy Authelia with the file backend, a single two_factor rule for your most exposed services, and TOTP as the MFA method. Once stable, migrate to LLDAP for team management, enable the OIDC provider for SSO, then add WebAuthn for users who have a hardware key or a device supporting passkeys. This progression prevents you from debugging multiple new components simultaneously and lets you validate each layer independently.

Deploy Authelia on your VPS in one click

Add MFA and SSO to your entire self-hosted stack without changing a single app. ServOrbit provisions a ready-to-use Authelia instance — configuration generated, admin user created, reverse proxy integration ready.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab