Many self-hosted apps (dashboards, admin panels, download managers, monitoring UIs) have weak login pages, or none at all. Authelia sits in front of them as an authentication portal. Your reverse proxy asks Authelia whether each request is allowed, users log in once with two-factor authentication, and that session covers all your apps (single sign-on). It can also act as an OpenID Connect provider for apps that support OIDC.

How forward auth works

Browser ──▶ Nginx / Traefik ──"is this user allowed?"──▶ Authelia
                 │                                           │
                 │◀──────── 200 OK or redirect to login ─────┘
                 ▼
            protected app
  1. A request for grafana.example.com hits the proxy.
  2. The proxy makes a sub-request to Authelia.
  3. Not logged in: redirect to auth.example.com, with login plus 2FA.
  4. Logged in, and the rules allow it: the request goes through, with user and group headers available to the app.

Requirements

  • Docker. See install Docker.
  • All protected apps under one parent domain (*.example.com), since session cookies are per domain.
  • HTTPS everywhere.
  • Redis (recommended for sessions), and SMTP for password reset and 2FA enrolment emails.

Docker Compose

# /opt/authelia/compose.yaml
services:
  authelia:
    image: authelia/authelia:4
    restart: unless-stopped
    volumes:
      - ./config:/config
    ports:
      - "127.0.0.1:9091:9091"
    environment:
      TZ: Etc/UTC
  redis:
    image: redis:7-alpine
    restart: unless-stopped

Configuration

./config/configuration.yml (essentials, for version 4.38+ syntax):

server:
  address: 'tcp://:9091'

log:
  level: info

identity_validation:
  reset_password:
    jwt_secret: '<long-random>'

authentication_backend:
  file:
    path: /config/users_database.yml
    password:
      algorithm: argon2

session:
  secret: '<long-random>'
  cookies:
    - domain: 'example.com'
      authelia_url: 'https://auth.example.com'
      default_redirection_url: 'https://home.example.com'
  redis:
    host: redis
    port: 6379

storage:
  encryption_key: '<long-random-at-least-20-chars>'
  local:
    path: /config/db.sqlite3

notifier:
  smtp:
    address: 'submission://smtp.example.com:587'
    username: '[email protected]'
    password: '<smtp-password>'
    sender: 'Authelia <[email protected]>'

totp:
  issuer: example.com

access_control:
  default_policy: deny
  rules:
    - domain: 'home.example.com'
      policy: one_factor
    - domain: ['grafana.example.com', 'portainer.example.com']
      subject: 'group:admins'
      policy: two_factor
    - domain: '*.example.com'
      policy: two_factor

Generate secrets with openssl rand -hex 64. Better still, provide them as files via AUTHELIA_*_FILE environment variables, instead of in the YAML. See secrets management.

Users file (users_database.yml):

users:
  alice:
    displayname: 'Alice'
    password: '$argon2id$v=19$m=65536,t=3,p=4$…'
    email: [email protected]
    groups: [admins]

Create password hashes with docker run --rm authelia/authelia:4 authelia crypto hash generate argon2 --password 'secret'. For larger setups, use LDAP as the backend. See OpenLDAP.

Nginx integration

Authelia’s documentation provides ready-made snippets (authelia-location.conf and authelia-authrequest.conf). The pattern, for each protected site:

server {
    server_name grafana.example.com;
    include /etc/nginx/snippets/authelia-location.conf;      # internal /internal/authelia/authz location

    location / {
        include /etc/nginx/snippets/authelia-authrequest.conf;   # auth_request + redirect on 401
        proxy_pass http://127.0.0.1:3001;
    }
    # listen 443 ssl; certificates via certbot
}

And a normal reverse proxy server block for auth.example.com → 127.0.0.1:9091. Traefik uses a forwardAuth middleware, and Caddy uses forward_auth. See Nginx reverse proxy.

Second factors

Users enrol on first login at auth.example.com:

  • TOTP apps (Aegis, 2FAS, Google Authenticator, Bitwarden);
  • WebAuthn / passkeys (YubiKeys, platform authenticators), the strongest option;
  • Duo push (optional).

OIDC provider

Authelia can also be an OpenID Connect provider, so apps with native SSO support (Gitea/Forgejo, Nextcloud, Grafana, Outline, Portainer…) log users in via Authelia. Configure identity_providers.oidc with clients, and their redirect URIs. See OAuth 2.0 and OIDC.

Tips

  • Start with default_policy: deny, and allow explicitly.
  • Exempt API paths and webhooks that machines call (with policy: bypass plus network restrictions, or app tokens).
  • Regulation (lockout after failed attempts) is enabled by default. Tune it in regulation:.
  • Back up ./config (database, users file and config), and keep it secret.

Quick reference

Item Value
Portal https://auth.example.com (port 9091)
Policies bypass, one_factor, two_factor, deny
Users file (argon2 hashes) or LDAP
2FA TOTP, WebAuthn/passkeys, Duo
Proxy integration Nginx auth_request, Traefik forwardAuth, Caddy forward_auth

Related: Keycloak and zero trust networking.

  • Self-Hosting
  • Security
  • Authentication