Self-Host Authelia: Add SSO & 2FA to All Your Apps in 15 Minutes
Every self-hosted app has its own login screen. You juggle passwords, manage separate user accounts, and pray you didn't forget to disable that default admin user. Authelia changes the game — it's an open-source authentication and authorization server that sits in front of your applications and adds single sign-on (SSO), two-factor authentication (2FA), and access control with minimal configuration.
In this guide, you'll deploy Authelia with Docker Compose, integrate it with Traefik as your reverse proxy, and protect any application behind a unified login portal. No more scattered credentials. No more sleepless nights about exposed dashboards.
What Authelia Solves
- Single Sign-On (SSO): One login for all your self-hosted services
- Two-Factor Authentication: TOTP, WebAuthn, and push notifications
- Access Control: Rules based on users, groups, IP addresses, and time
- Session Management: Remember-me functionality and secure cookie handling
- Self-Hosted: Your credentials stay on your infrastructure
Prerequisites
- A VPS or server with Docker and Docker Compose installed
- Traefik running as reverse proxy (see our Traefik guide)
- A domain pointed to your server (we'll use
auth.yourdomain.com) - At least 512MB RAM available for the Authelia container
Step 1: Create the Directory Structure
mkdir -p ~/authelia/config
mkdir -p ~/authelia/secrets
cd ~/authelia
Step 2: Generate Secrets
Authelia requires strong random secrets. Generate them:
# Generate secrets
docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --charset alphanumeric > secrets/JWT_SECRET
docker run --rm authelia/authelia:latest authelia crypto rand --length 128 --charset alphanumeric > secrets/SESSION_SECRET
docker run --rm authelia/authelia:latest authelia crypto rand --length 128 --charset alphanumeric > secrets/STORAGE_ENCRYPTION_KEY
# Create a hashed password for your first user
# Replace 'yourpassword' with a strong password
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'yourpassword'
Copy the generated hash — you'll need it in the users database.
Step 3: Create the Configuration File
Create ~/authelia/config/configuration.yml:
server:
address: 'tcp://:9091'
disable_healthcheck: false
log:
level: info
totp:
issuer: authelia.com
authentication_backend:
file:
path: /config/users_database.yml
password:
algorithm: argon2id
iterations: 1
key_length: 32
salt_length: 16
memory: 64
parallelism: 8
access_control:
default_policy: two_factor
rules:
- domain: "*.yourdomain.com"
policy: two_factor
- domain: "public.yourdomain.com"
policy: bypass
session:
name: authelia_session
secret: {{ secret "/secrets/SESSION_SECRET" }}
expiration: 1h
inactivity: 5m
domain: yourdomain.com
regulation:
max_retries: 3
find_time: 2m
ban_time: 5m
storage:
encryption_key: {{ secret "/secrets/STORAGE_ENCRYPTION_KEY" }}
local:
path: /config/db.sqlite3
notifier:
filesystem:
filename: /config/notification.txt
identity_providers:
oidc:
hmac_secret: {{ secret "/secrets/JWT_SECRET" }}
issuer_private_key: |
# Generate with: openssl genrsa -out oidc.pem 2048
# Then paste the private key here
cors:
endpoints:
- authorization
- token
- revocation
- introspection
allowed_origins:
- https://*.yourdomain.com
allowed_origins_from_client_redirect_uris: true
Step 4: Create the Users Database
Create ~/authelia/config/users_database.yml:
users:
admin:
disabled: false
displayname: "Admin User"
password: "$argon2id$v=19$m=65536,t=3,p=4$YOUR_HASH_HERE"
email: [email protected]
groups:
- admins
- devops
developer:
disabled: false
displayname: "Developer"
password: "$argon2id$v=19$m=65536,t=3,p=4$ANOTHER_HASH_HERE"
email: [email protected]
groups:
- developers
Replace YOUR_HASH_HERE with the hash generated in Step 2.
Step 5: Docker Compose Deployment
Create ~/authelia/docker-compose.yml:
version: '3.8'
services:
authelia:
image: authelia/authelia:latest
container_name: authelia
restart: unless-stopped
expose:
- 9091
volumes:
- ./config:/config
- ./secrets:/secrets
environment:
- TZ=UTC
- AUTHELIA_JWT_SECRET_FILE=/secrets/JWT_SECRET
- AUTHELIA_SESSION_SECRET_FILE=/secrets/SESSION_SECRET
- AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/secrets/STORAGE_ENCRYPTION_KEY
labels:
- "traefik.enable=true"
- "traefik.http.routers.authelia.rule=Host(`auth.yourdomain.com`)"
- "traefik.http.routers.authelia.entrypoints=websecure"
- "traefik.http.routers.authelia.tls.certresolver=letsencrypt"
- "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.yourdomain.com"
- "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
networks:
- traefik
networks:
traefik:
external: true
Step 6: Deploy Authelia
cd ~/authelia
docker compose up -d
Step 7: Protect an Application
To protect any app behind Authelia, add these labels to its Docker Compose service:
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app.yourdomain.com`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
- "traefik.http.routers.myapp.middlewares=authelia@docker"
The authelia@docker middleware redirects unauthenticated users to the Authelia login portal.
Step 8: Verification
- Access the portal: Visit
https://auth.yourdomain.com - Log in: Use the credentials from your users database
- Configure 2FA: Follow the TOTP setup (scan QR code with your authenticator app)
- Test protected app: Visit
https://app.yourdomain.com— you should be redirected to Authelia - Check logs:
docker logs authelia
Step 9: Enable OIDC for Modern Apps
Authelia supports OpenID Connect. Add clients to your configuration:
identity_providers:
oidc:
clients:
- client_id: "grafana"
client_name: "Grafana"
client_secret: "$pbkdf2-sha512$310000$..."
public: false
authorization_policy: two_factor
redirect_uris:
- "https://grafana.yourdomain.com/login/generic_oauth"
scopes:
- openid
- profile
- groups
- email
userinfo_signed_response_alg: none
Production Hardening
- Use LDAP/Active Directory: Replace file backend with corporate directory
- Redis for sessions: Scale beyond single instance
- SMTP notifier: Replace filesystem with real email for 2FA and notifications
- Backup config:
users_database.ymland secrets are critical - Monitor logs: Failed login attempts and access patterns
Next Steps
- Deploy Traefik if you haven't already
- Add Grafana & Prometheus for monitoring login metrics
- Integrate with Portainer for Docker management SSO
- Explore LDAP integration for enterprise user management
Your homelab just got enterprise-grade authentication. No more scattered logins, no more weak default credentials — just one secure gateway to everything you self-host.