Authelia SSO with Nginx: Two-Factor Authentication for Internal Apps
Security

Authelia SSO with Nginx: Two-Factor Authentication for Internal Apps

  • Author :Liam K.
  • Date :July 02, 2026
  • Time :28 minutes

Authelia is an open-source authentication and authorization server that adds single sign-on (SSO) and two-factor authentication (2FA) in front of your internal applications. Instead of managing separate logins for Grafana, Proxmox, Portainer, and other admin panels, Authelia provides a unified login portal with TOTP, WebAuthn, or Duo push as a second factor. It integrates with Nginx, Caddy, and Traefik via forward-auth — your reverse proxy asks Authelia "is this user allowed?" before forwarding the request to the backend.

This guide deploys Authelia with Docker Compose, configures file-based users with Argon2id password hashing, sets up TOTP 2FA, and protects multiple backend services through Nginx forward-auth. The result is a production-grade authentication layer for any service that does not have built-in SSO support.

How Forward-Auth Works

  • User requests grafana.example.com
  • Nginx sends an auth subrequest to Authelia's verify endpoint
  • If not authenticated → redirect to Authelia login portal
  • User logs in + completes 2FA → Authelia sets a session cookie
  • Nginx receives 200 from verify → forwards request to Grafana

Prerequisites

  • Linux server with Docker and Docker Compose
  • Nginx reverse proxy with TLS (Let's Encrypt)
  • Subdomain for Authelia portal (e.g. auth.example.com)
  • Services to protect (Grafana, Proxmox, internal tools)

Step 1: Create Directory Structure

bash
sudo mkdir -p /opt/authelia/{config,secrets}
cd /opt/authelia

# Generate secrets:
openssl rand -hex 32 | sudo tee secrets/JWT_SECRET
openssl rand -hex 32 | sudo tee secrets/SESSION_SECRET
openssl rand -hex 32 | sudo tee secrets/STORAGE_ENCRYPTION_KEY

Step 2: Create Users Database

bash
# Generate password hash (replace 'yourpassword'):
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'yourpassword'
# Create /opt/authelia/config/users_database.yml:
sudo tee config/users_database.yml >/dev/null <<'EOF'
users:
  admin:
    displayname: "Admin User"
    password: "$argon2id$v=19$m=65536,t=3,p=4$PASTE_HASH_HERE"
[...]
Command truncated. Copy to view full command.

Step 3: Write Authelia Configuration

bash
sudo tee config/configuration.yml >/dev/null <<'EOF'
theme: dark
server:
  address: 'tcp://0.0.0.0:9091'
log:
  level: info
identity_validation:
  reset_password:
[...]
Command truncated. Copy to view full command.

Step 4: Docker Compose Stack

bash
sudo tee docker-compose.yml >/dev/null <<'EOF'
services:
  authelia:
    image: authelia/authelia:latest
    container_name: authelia
    restart: unless-stopped
    volumes:
      - ./config:/config
[...]
Command truncated. Copy to view full command.

Step 5: Nginx Forward-Auth for Protected Services

nginx
# /etc/nginx/snippets/authelia-auth.conf
set $authelia_url http://127.0.0.1:9091;
location /authelia {
    internal;
    proxy_pass $authelia_url/api/verify;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
[...]
Command truncated. Copy to view full command.

Step 6: Nginx Config for Authelia Portal

nginx
server {
    listen 443 ssl http2;
    server_name auth.example.com;
    location / {
        proxy_pass http://127.0.0.1:9091;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
[...]
Command truncated. Copy to view full command.

Step 7: Register TOTP Device

Log in at https://auth.example.com. On first login, Authelia prompts you to register a TOTP device. Scan the QR code with Google Authenticator, Authy, or any TOTP app. Store backup codes securely.

Step 8: Test Protected Service Access

bash
# Open in browser:
# https://grafana.example.com → redirects to auth.example.com
# Login + 2FA → redirects back to Grafana

# Verify from CLI:
curl -I https://grafana.example.com
# Should return 302 to auth.example.com

Access Control Policies

  • bypass — no authentication required (use for auth portal itself).
  • one_factor — password only. Suitable for low-risk internal tools.
  • two_factor — password + TOTP/WebAuthn. Use for admin panels.
  • deny — block access entirely regardless of authentication.

Production Checklist

  • Back up /opt/authelia/config and secrets directory.
  • Use two_factor policy for all admin-facing services.
  • Configure SMTP notifier instead of filesystem for password reset emails.
  • Review access control rules when adding new services.
  • Test login flow after every Authelia upgrade.

"SSO is not just convenience — it is a security control that centralizes authentication, enforces 2FA, and gives you one place to revoke access."

Technical Author

Technical Author - Liam K.
Liam K.

System administrator and technical writer specializing in server infrastructure, security and deployment. Creating comprehensive guides to help you master server administration.