Authelia: Lightweight SSO for Homelabs
Single sign-on and 2FA with minimal resources. Perfect for resource-constrained homelabs.
Introduction
Managing authentication across multiple homelab services becomes cumbersome as your infrastructure grows. Each application with its own login credentials creates security risks and user friction. Authelia solves this problem by providing a lightweight, open-source authentication and authorization server that adds single sign-on (SSO) and multi-factor authentication (MFA) to your existing applications through your reverse proxy.
Unlike heavyweight identity providers like Keycloak or Authentik, Authelia is purpose-built for homelabs and small deployments. It runs with minimal resources (50-100MB RAM), integrates seamlessly with popular reverse proxies (Traefik, Nginx Proxy Manager, Caddy), and provides enterprise-grade security features without the complexity.
In this comprehensive guide, you’ll learn how to deploy Authelia with Docker, configure two-factor authentication, integrate with Traefik and Nginx reverse proxies, implement granular access control rules, and set up bypass rules for specific services.
What You’ll Build:
- Production-ready Authelia instance with PostgreSQL backend
- TOTP-based two-factor authentication
- WebAuthn/security key support
- Integration with Traefik reverse proxy
- Alternative Nginx Proxy Manager integration
- Fine-grained access control policies
- Bypass rules for API endpoints and specific services
- Session management and remember-me functionality
Why Choose Authelia?
- Lightweight: 50-100MB RAM (vs Keycloak’s 4-8GB or Authentik’s 2-4GB)
- Fast Deployment: Running in under 10 minutes with Docker Compose
- Reverse Proxy Native: Designed specifically for forward auth patterns
- Privacy-First: All authentication data stays on your infrastructure
- Active Development: Regular updates and security patches
- Flexible Storage: Supports PostgreSQL, MySQL, SQLite, and file-based backends
Prerequisites
Before starting, ensure you have:
Technical Requirements:
- Server with 1 CPU core, 1GB RAM, 5GB storage
- Docker 20.10.0+ and Docker Compose 1.27.0+
- Reverse proxy: Traefik 2.0+ or Nginx/Nginx Proxy Manager
- Domain name (e.g.,
auth.example.com,example.local) - DNS configured to point to your server
- (Optional) SMTP credentials for password reset emails
Knowledge Requirements:
- Basic Docker and command line familiarity
- Understanding of DNS and reverse proxies
- YAML configuration experience helpful
Preparation:
# Verify Docker installation
docker --version # Should be 20.10.0+
docker-compose --version # Should be 1.27.0+
# Create working directory
mkdir -p ~/authelia
cd ~/authelia Section 1: Understanding Authelia Architecture
What is Forward Authentication?
Authelia implements the “forward authentication” pattern, where your reverse proxy delegates authentication decisions to Authelia:
User Request → Reverse Proxy → Authelia (check auth)
↓
Protected Service (if authenticated)
or
Login Page (if not authenticated) Flow breakdown:
- User requests
https://app.example.com - Reverse proxy sends auth verification request to Authelia
- Authelia checks for valid session cookie
- If valid: reverse proxy forwards request to application
- If invalid: redirect to
https://auth.example.comlogin portal
Benefits:
- Applications don’t need to know about Authelia
- Centralized authentication for all services
- Add SSO to apps without native support
- Consistent login experience
Authelia Components
Authentication Portal: Web interface where users log in, enroll 2FA devices, and manage sessions. Served by Authelia at your authentication domain (e.g., auth.example.com).
Session Provider: Manages authenticated sessions using encrypted cookies. Supports Redis for distributed deployments or in-memory for single instances.
User Database: Stores user credentials and metadata. Supports file-based YAML (simple), LDAP (enterprise), or custom backends.
Storage Backend: Persists TOTP secrets, WebAuthn devices, consent records. PostgreSQL, MySQL, or SQLite.
Notifier: Sends email notifications for password resets and identity verification. Requires SMTP configuration.
Access Control Engine: Evaluates rules to determine if users can access resources based on domain, path, groups, IP addresses, and more.
Authelia vs Alternatives
| Feature | Authelia | Authentik | Keycloak |
|---|---|---|---|
| Primary Use Case | Forward auth for reverse proxies | Full IdP | Enterprise IdP |
| RAM Usage | 50-100MB | 2-4GB | 4-8GB |
| Setup Time | 10 minutes | 30 minutes | 60+ minutes |
| OAuth2/OIDC | Limited (v4.38+) | ✅ Full Support | ✅ Full Support |
| LDAP Provider | ❌ Client only | ✅ Yes | ✅ Yes |
| Forward Auth | ✅ Native | ⚠️ Via proxy | ⚠️ Manual setup |
| Best For | Homelab reverse proxies | SMB with diverse SSO needs | Enterprise deployments |
Choose Authelia if:
- Using Traefik, Nginx, or Caddy reverse proxy
- Want minimal resource usage
- Need quick setup with file-based user management
- Primarily protecting web applications behind reverse proxy
- Don’t need SAML or complex OAuth2 provider functionality
Section 2: Installing Authelia with Docker
Step 1: Create Project Structure
Set up the directory structure for Authelia configuration:
# Create directories
mkdir -p ~/authelia/{config,secrets}
cd ~/authelia
# Set restrictive permissions on secrets
chmod 700 secrets Step 2: Generate Secrets
Authelia requires several cryptographic secrets for security:
# Generate JWT secret (used for session tokens)
openssl rand -hex 32 > secrets/jwt_secret
# Generate session secret (encrypts session cookies)
openssl rand -hex 32 > secrets/session_secret
# Generate storage encryption key (encrypts TOTP secrets)
openssl rand -hex 32 > secrets/storage_encryption_key
# Display generated secrets (save these securely!)
echo "JWT Secret: $(cat secrets/jwt_secret)"
echo "Session Secret: $(cat secrets/session_secret)"
echo "Storage Encryption Key: $(cat secrets/storage_encryption_key)"
# Secure permissions
chmod 600 secrets/* Important: Store these secrets in a password manager. Loss of the storage encryption key means loss of all TOTP enrollments.
Step 3: Create Docker Compose Configuration
Create the Docker Compose file for Authelia and PostgreSQL:
# docker-compose.yml
version: '3.8'
services:
authelia:
image: authelia/authelia:latest
container_name: authelia
volumes:
- ./config:/config
- ./secrets:/secrets:ro
networks:
- proxy
- authelia
environment:
- TZ=America/New_York
ports:
- "9091:9091"
restart: unless-stopped
depends_on:
- postgres
postgres:
image: postgres:16-alpine
container_name: authelia-postgres
environment:
POSTGRES_DB: authelia
POSTGRES_USER: authelia
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- authelia
secrets:
- postgres_password
restart: unless-stopped
networks:
proxy:
external: true # Shared with Traefik/Nginx
authelia:
driver: bridge
volumes:
postgres-data:
secrets:
postgres_password:
file: ./secrets/postgres_password Generate PostgreSQL password:
# Generate and save PostgreSQL password
openssl rand -base64 24 > secrets/postgres_password
chmod 600 secrets/postgres_password Network configuration notes:
proxynetwork: External network shared with your reverse proxy (Traefik/Nginx)authelianetwork: Internal network for Authelia and PostgreSQL only- Ensures PostgreSQL is not accessible from reverse proxy network
Step 4: Create Authelia Configuration
Create the main Authelia configuration file:
# config/configuration.yml
---
theme: auto # Options: light, dark, auto
server:
address: 'tcp://0.0.0.0:9091'
buffers:
read: 4096
write: 4096
timeouts:
read: 6s
write: 6s
idle: 30s
log:
level: info # Options: trace, debug, info, warn, error
format: text # Options: text, json
jwt_secret: '/secrets/jwt_secret'
default_redirection_url: https://example.com # Change to your domain
totp:
disable: false
issuer: authelia.com
algorithm: sha1
digits: 6
period: 30
skew: 1
webauthn:
disable: false
display_name: Authelia
attestation_conveyance_preference: indirect
user_verification: preferred
timeout: 60s
authentication_backend:
password_reset:
disable: false
refresh_interval: 5m
file:
path: /config/users_database.yml
password:
algorithm: argon2id
iterations: 3
key_length: 32
salt_length: 16
memory: 65536
parallelism: 4
access_control:
default_policy: deny
rules:
# Allow access to Authelia portal itself
- domain: auth.example.com
policy: bypass
# Protect all other services (require authentication)
- domain: "*.example.com"
policy: two_factor
session:
secret: '/secrets/session_secret'
name: authelia_session
domain: example.com # Root domain for cookies
same_site: lax
expiration: 1h
inactivity: 5m
remember_me: 1M
cookies:
- domain: example.com
authelia_url: https://auth.example.com
redis:
host: authelia-redis
port: 6379
regulation:
max_retries: 5
find_time: 2m
ban_time: 5m
storage:
encryption_key: '/secrets/storage_encryption_key'
postgres:
address: 'tcp://postgres:5432'
database: authelia
username: authelia
password: '/secrets/postgres_password'
notifier:
disable_startup_check: false
smtp:
address: smtp.resend.com:587
username: resend
password: 'your-resend-api-key' # Or use file: /secrets/smtp_password
sender: "Authelia <[email protected]>"
startup_check_address: [email protected] Important configuration notes:
- Replace
example.comwith your actual domain throughout - Update SMTP settings if you want password reset functionality
- For testing, you can set
notifier.filesystem.filename: /config/notifications.txtinstead of SMTP
Step 5: Create Users Database
Create a file-based user database:
# config/users_database.yml
---
users:
admin:
disabled: false
displayname: "Admin User"
password: "$argon2id$v=19$m=65536,t=3,p=4$placeholder" # Will be replaced
email: [email protected]
groups:
- admins
- users
john:
disabled: false
displayname: "John Doe"
password: "$argon2id$v=19$m=65536,t=3,p=4$placeholder"
email: [email protected]
groups:
- users Generate password hashes:
# Generate password hash for admin user
docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'YourSecurePassword123!'
# Copy the generated hash and replace the placeholder in users_database.yml Step 6: Add Redis for Session Storage (Optional but Recommended)
For production deployments, use Redis for session storage:
# Add to docker-compose.yml services section
redis:
image: redis:7-alpine
container_name: authelia-redis
volumes:
- redis-data:/data
networks:
- authelia
command: redis-server --save 60 1 --loglevel warning
restart: unless-stopped
# Add to volumes section
volumes:
redis-data: If using in-memory sessions (not recommended for production), modify configuration.yml:
session:
# ... other session settings ...
# Remove or comment out redis section
provider: memory # Add this line Step 7: Start Authelia
Launch all services:
# Pull latest images
docker-compose pull
# Start services
docker-compose up -d
# Monitor startup logs
docker-compose logs -f authelia
# Wait for "Authelia is listening on 0.0.0.0:9091" message Verify services are running:
# Check container status
docker-compose ps
# Expected output:
# NAME STATUS
# authelia Up
# authelia-postgres Up
# authelia-redis Up
# Test Authelia API
curl -I http://localhost:9091/api/health
# Expected: HTTP/1.1 200 OK Section 3: Two-Factor Authentication Setup
TOTP (Time-based One-Time Passwords)
TOTP is the most common 2FA method, compatible with authenticator apps.
Configuration (already in configuration.yml):
totp:
disable: false
issuer: authelia.com # Name shown in authenticator app
algorithm: sha1 # sha1 (most compatible), sha256, sha512
digits: 6 # 6 or 8 digits
period: 30 # Seconds between code rotations
skew: 1 # Allow 1 period before/after for clock drift User enrollment process:
- User logs in with username and password
- Authelia prompts: “Two-factor authentication is required”
- User scans QR code with authenticator app:
- Google Authenticator (iOS/Android)
- Authy (iOS/Android/Desktop)
- Microsoft Authenticator (iOS/Android)
- 1Password (if available)
- User enters 6-digit code to verify enrollment
- Authelia displays one-time backup codes (print and store securely)
- Subsequent logins require both password and TOTP code
Testing TOTP enrollment:
# Access Authelia portal (adjust URL to your domain)
# https://auth.example.com
# Login with credentials from users_database.yml
# Follow TOTP enrollment wizard WebAuthn (Security Keys and Biometrics)
WebAuthn provides phishing-resistant authentication using hardware security keys or platform authenticators.
Configuration (already in configuration.yml):
webauthn:
disable: false
display_name: Authelia
attestation_conveyance_preference: indirect # indirect, direct, none
user_verification: preferred # required, preferred, discouraged
timeout: 60s Supported devices:
- Hardware keys: YubiKey 5 series, Google Titan, Nitrokey
- Platform authenticators: Windows Hello, TouchID, FaceID, Android biometrics
- Passkeys: Chrome/Safari passkey storage
User enrollment:
- Navigate to Authelia portal → User settings
- Click “Register Security Key”
- Insert security key or prepare biometric authenticator
- Click “Register” and follow browser prompts
- Touch key or perform biometric verification
- Give device a friendly name (e.g., “YubiKey 5C NFC”)
- Device is now enrolled for 2FA
Multiple device enrollment: Users can enroll multiple TOTP apps and multiple WebAuthn devices for redundancy.
Backup Codes
Authelia generates one-time backup codes during 2FA enrollment for account recovery.
Best practices:
- Print codes and store in secure location
- Never store backup codes digitally alongside passwords
- Regenerate codes if compromised
- Use codes only as last resort
Manual backup code generation:
# Access user settings in Authelia portal
# Navigate to "Two-Factor Authentication"
# Click "Regenerate backup codes"
# Print or write down codes Section 4: Traefik Integration
Traefik 2.x has native support for forward authentication with Authelia.
Step 1: Ensure Shared Network
Verify Traefik and Authelia share the proxy network:
# Create proxy network if not exists
docker network create proxy
# Verify Authelia is connected
docker network inspect proxy | grep authelia Step 2: Configure Traefik Middleware
Create Authelia forward auth middleware in Traefik:
Dynamic configuration (YAML file method):
# traefik/dynamic/authelia.yml
http:
middlewares:
authelia:
forwardAuth:
address: http://authelia:9091/api/verify?rd=https://auth.example.com
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Name
- Remote-Email
authelia-basic:
forwardAuth:
address: http://authelia:9091/api/verify?auth=basic
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups Docker labels method:
# In your Traefik docker-compose.yml
services:
traefik:
labels:
- "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.example.com"
- "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email" Step 3: Expose Authelia Portal via Traefik
Create Traefik router for Authelia authentication portal:
# Add to authelia service in docker-compose.yml
services:
authelia:
labels:
- "traefik.enable=true"
- "traefik.http.routers.authelia.rule=Host(`auth.example.com`)"
- "traefik.http.routers.authelia.entrypoints=websecure"
- "traefik.http.routers.authelia.tls=true"
- "traefik.http.routers.authelia.tls.certresolver=letsencrypt"
- "traefik.http.services.authelia.loadbalancer.server.port=9091" Restart Authelia:
docker-compose up -d Step 4: Protect Applications with Authelia
Add Authelia middleware to any service you want to protect:
Example: Protecting Portainer
services:
portainer:
image: portainer/portainer-ce:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
- "traefik.http.routers.portainer.entrypoints=websecure"
- "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
# Add Authelia protection
- "traefik.http.routers.portainer.middlewares=authelia@docker"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
networks:
- proxy Example: Protecting multiple services
services:
grafana:
labels:
- "traefik.http.routers.grafana.middlewares=authelia@docker"
jellyfin:
labels:
- "traefik.http.routers.jellyfin.middlewares=authelia@docker"
nextcloud:
labels:
- "traefik.http.routers.nextcloud.middlewares=authelia@docker" Step 5: Test Authentication Flow
- Clear browser cookies
- Navigate to protected service:
https://portainer.example.com - Expect redirect: Browser redirects to
https://auth.example.com - Enter credentials: Username and password from users_database.yml
- Complete 2FA: Enter TOTP code or touch security key
- Redirect back: Automatically redirected to
https://portainer.example.com - Access granted: Service loads normally
Troubleshooting:
- 404 error → Check Authelia container is running
- Redirect loop → Verify access control rules don’t block auth.example.com
- 401 unauthorized → Check middleware configuration
- No redirect → Middleware not applied to router
Section 5: Nginx Proxy Manager Integration
Nginx Proxy Manager (NPM) requires manual Nginx configuration for forward auth.
Step 1: Access Authelia from NPM Network
Update docker-compose.yml to share network with NPM:
networks:
proxy:
external: true # NPM's network
name: npm_default # Adjust to your NPM network name Find NPM network name:
docker network ls | grep npm
# Output example: npm_default Step 2: Create Proxy Host for Authelia Portal
In Nginx Proxy Manager web UI:
- Proxy Hosts → Add Proxy Host
- Domain Names:
auth.example.com - Scheme:
http - Forward Hostname/IP:
authelia - Forward Port:
9091 - SSL Tab:
- ✅ Force SSL
- ✅ Request new SSL certificate (Let’s Encrypt)
- Save
Step 3: Create Advanced Configuration Snippet
NPM → Advanced → Custom Nginx Configuration (for each protected service):
# Advanced configuration for protected-app.example.com
location / {
# Send auth verification to Authelia
auth_request /authelia;
# Pass auth headers to backend
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
# Redirect to Authelia if unauthenticated
error_page 401 =302 https://auth.example.com/?rd=$scheme://$http_host$request_uri;
}
# Internal location for auth verification
location /authelia {
internal;
proxy_pass http://authelia:9091/api/verify;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
} Step 4: Alternative - Authelia Authentication Preset
Create a reusable Nginx snippet:
SSH into NPM container:
docker exec -it npm bash
# Create custom snippet directory
mkdir -p /data/nginx/custom
# Create Authelia snippet
cat > /data/nginx/custom/authelia-auth.conf << 'EOF'
# Authelia Forward Auth Configuration
location /authelia {
internal;
proxy_pass http://authelia:9091/api/verify;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
EOF
exit Reference in proxy host custom configuration:
# Include Authelia auth check
include /data/nginx/custom/authelia-auth.conf;
location / {
auth_request /authelia;
auth_request_set $user $upstream_http_remote_user;
proxy_set_header Remote-User $user;
error_page 401 =302 https://auth.example.com/?rd=$scheme://$http_host$request_uri;
} Section 6: Access Control Rules
Authelia’s access control engine evaluates rules top-to-bottom and applies the first match.
Rule Structure
access_control:
default_policy: deny # deny, bypass, one_factor, two_factor
rules:
- domain: "example.com"
policy: bypass
subject:
- "group:admins"
networks:
- "192.168.1.0/24" Rule components:
domain: Domain(s) to match (supports wildcards and regex)policy: Action to take (bypass, one_factor, two_factor, deny)subject: User or group requirements (optional)networks: Source IP restrictions (optional)resources: Path-based matching (optional)
Common Access Control Patterns
Pattern 1: Public landing page, protected dashboard
rules:
# Allow public access to marketing site
- domain: example.com
policy: bypass
# Require authentication for app subdomain
- domain: app.example.com
policy: two_factor Pattern 2: Admin-only services
rules:
# Admin panel accessible only to admins group
- domain: admin.example.com
policy: two_factor
subject:
- "group:admins"
# Deny everyone else
- domain: admin.example.com
policy: deny Pattern 3: Network-based access
rules:
# Internal network can access without 2FA
- domain: "*.internal.example.com"
policy: one_factor
networks:
- "192.168.1.0/24"
- "10.0.0.0/8"
# External access requires 2FA
- domain: "*.internal.example.com"
policy: two_factor Pattern 4: Path-based rules
rules:
# Allow webhook endpoints without auth
- domain: app.example.com
resources:
- "^/api/webhooks/.*$"
policy: bypass
# Require auth for everything else
- domain: app.example.com
policy: two_factor Pattern 5: User-specific access
rules:
# Only john can access personal dashboard
- domain: john.example.com
policy: two_factor
subject:
- "user:john"
# Deny everyone else
- domain: john.example.com
policy: deny Advanced: Regex Domain Matching
rules:
# Match multiple TLDs
- domain_regex: "^app\.(example\.com|example\.local)$"
policy: two_factor
# Match numbered subdomains
- domain_regex: "^service-[0-9]+\.example\.com$"
policy: one_factor Complete Real-World Example
access_control:
default_policy: deny
rules:
# Authelia portal itself (must be first)
- domain: auth.example.com
policy: bypass
# Public services
- domain:
- example.com
- www.example.com
policy: bypass
# Admin services - require admin group and 2FA
- domain:
- portainer.example.com
- proxmox.example.com
policy: two_factor
subject:
- "group:admins"
# Media services - all authenticated users
- domain:
- jellyfin.example.com
- plex.example.com
policy: one_factor
subject:
- "group:users"
# API endpoints - bypass for automation
- domain: api.example.com
resources:
- "^/webhooks/.*$"
- "^/health$"
policy: bypass
# Everything else requires 2FA
- domain: "*.example.com"
policy: two_factor Section 7: Bypass Rules for API and Special Cases
Some services require authentication bypass for specific functionality.
Bypass API Endpoints
rules:
# Allow API access for automation
- domain: nextcloud.example.com
resources:
- "^/remote\.php/dav/.*$" # CalDAV/CardDAV
- "^/ocs/.*$" # OCS API
policy: bypass
# Require auth for web interface
- domain: nextcloud.example.com
policy: two_factor Bypass Health Checks and Monitoring
rules:
# Allow Uptime Kuma to check services
- domain: "*.example.com"
resources:
- "^/health$"
- "^/api/health$"
- "^/ping$"
networks:
- "192.168.1.50/32" # Uptime Kuma IP
policy: bypass Bypass Mobile Apps
rules:
# Allow Jellyfin mobile app access
- domain: jellyfin.example.com
resources:
- "^/emby/.*$"
- "^/mediabrowser/.*$"
policy: bypass Bypass RSS Feeds
rules:
# Public RSS feeds
- domain: blog.example.com
resources:
- "^/feed$"
- "^/rss$"
- "^\/.*\.xml$"
policy: bypass Bypass with User-Agent Detection
Authelia doesn’t natively support user-agent matching, but you can implement this in Nginx:
# In NPM custom configuration
location / {
# Bypass auth for specific user agents
if ($http_user_agent ~* "JellyfinClient|PlexClient") {
proxy_pass http://backend;
break;
}
# Normal Authelia auth for browsers
auth_request /authelia;
error_page 401 =302 https://auth.example.com/?rd=$scheme://$http_host$request_uri;
} Testing Bypass Rules
# Test API endpoint bypass
curl -I https://api.example.com/webhooks/github
# Expected: 200 OK (no redirect to auth portal)
# Test protected endpoint
curl -I https://api.example.com/admin
# Expected: 302 Redirect to https://auth.example.com Section 8: Session Management and Remember Me
Session Configuration Deep Dive
session:
secret: '/secrets/session_secret'
name: authelia_session # Cookie name
domain: example.com # Root domain for cookie sharing
same_site: lax # lax, strict, none
expiration: 1h # Session expires after 1 hour
inactivity: 5m # Session expires after 5 min of inactivity
remember_me: 1M # Remember me extends session to 1 month Session behavior:
- User logs in → Session created with 1 hour expiration
- User inactive for 5 minutes → Session expires, requires re-login
- User checks “Remember me” → Session extended to 1 month
- User closes browser → Session persists (unless browser clears cookies)
Multi-Domain Session Sharing
To share sessions across multiple root domains:
session:
cookies:
- domain: example.com
authelia_url: https://auth.example.com
- domain: example.net
authelia_url: https://auth.example.net Logout Functionality
Manual logout:
- Navigate to
https://auth.example.com - Click user icon → Logout
- Session cookie deleted
Programmatic logout:
# Delete session cookie via JavaScript
document.cookie = "authelia_session=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.example.com"; Session Security Best Practices
- Use HTTPS only: Set
session.secure: truein production - Minimize expiration: Shorter sessions reduce attack window
- Enable inactivity timeout: Auto-logout idle users
- Restrict remember_me: Limit to trusted devices only
- Monitor active sessions: Check Redis for suspicious sessions
# View active sessions in Redis
docker exec -it authelia-redis redis-cli
# List all keys (sessions)
KEYS authelia:session:*
# Inspect specific session
GET authelia:session:abc123def456 Section 9: LDAP Integration (Optional)
For environments with existing LDAP/Active Directory:
Replace File Backend with LDAP
authentication_backend:
password_reset:
disable: false
refresh_interval: 5m
ldap:
address: ldap://openldap:389
implementation: custom # custom, activedirectory, rfc2307bis
timeout: 5s
start_tls: false
tls:
skip_verify: false
base_dn: dc=example,dc=com
username_attribute: uid
additional_users_dn: ou=users
users_filter: (&({username_attribute}={input})(objectClass=person))
additional_groups_dn: ou=groups
groups_filter: (&(member={dn})(objectClass=groupOfNames))
group_name_attribute: cn
mail_attribute: mail
display_name_attribute: displayName
user: cn=admin,dc=example,dc=com
password: 'ldap-admin-password' Active Directory Example
authentication_backend:
ldap:
address: ldap://dc.example.com:389
implementation: activedirectory
start_tls: true
base_dn: DC=example,DC=com
username_attribute: sAMAccountName
additional_users_dn: CN=Users
users_filter: (&({username_attribute}={input})(objectCategory=person)(objectClass=user))
additional_groups_dn: CN=Users
groups_filter: (&(member={dn})(objectClass=group))
group_name_attribute: cn
user: CN=authelia,CN=Users,DC=example,DC=com
password: '/secrets/ldap_password' Section 10: Troubleshooting Common Issues
Issue 1: Redirect Loop
Symptoms: Browser repeatedly redirects between app and auth portal
Causes and solutions:
# 1. Check access control rules
# Ensure auth.example.com has bypass policy
# 2. Verify Traefik middleware isn't applied to Authelia itself
# Remove authelia middleware from auth portal router
# 3. Check cookie domain configuration
# Ensure session.domain matches your setup
# 4. Clear browser cookies
# Browser dev tools → Application → Cookies → Delete all for domain Issue 2: 401 Unauthorized After Login
Symptoms: Login succeeds but still shows 401 on protected service
Diagnostic steps:
# Check Authelia logs
docker-compose logs authelia | grep -i error
# Verify middleware configuration
docker exec traefik cat /etc/traefik/dynamic/authelia.yml
# Test Authelia verify endpoint directly
curl -H "Cookie: authelia_session=abc123" http://localhost:9091/api/verify
# Check access control rules match the domain
docker exec authelia cat /config/configuration.yml | grep -A 20 access_control Issue 3: 2FA Not Prompting
Symptoms: Login with password succeeds, but no 2FA prompt appears
Solutions:
# 1. Verify TOTP is enabled in configuration
docker exec authelia cat /config/configuration.yml | grep -A 5 totp
# 2. Check access control policy
# Rules must specify 'two_factor' policy
# 3. Force re-enrollment
# Delete TOTP secret from database
docker exec -it authelia-postgres psql -U authelia -d authelia
DELETE FROM totp_configurations WHERE username = 'admin';
q Issue 4: SMTP Errors
Symptoms: Cannot send password reset emails
Diagnostic steps:
# Test SMTP connectivity
docker exec authelia telnet smtp.resend.com 587
# Check SMTP credentials
docker exec authelia cat /config/configuration.yml | grep -A 10 smtp
# View detailed SMTP errors
docker-compose logs authelia | grep -i smtp
# Test with filesystem notifier instead
# Modify configuration.yml:
# notifier:
# filesystem:
# filename: /config/notifications.txt Issue 5: High Memory Usage
Symptoms: Authelia consuming excessive RAM
Solutions:
# 1. Set resource limits in docker-compose.yml
services:
authelia:
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 128M
# 2. Optimize session storage
# Use Redis instead of memory provider
# 3. Clean up old sessions
docker exec -it authelia-redis redis-cli FLUSHDB
# 4. Reduce session duration
# Lower session.expiration and session.inactivity values Section 11: Monitoring and Metrics
Health Check Endpoint
# Check Authelia health
curl http://localhost:9091/api/health
# Expected response:
# {"status":"UP"} Prometheus Metrics (Optional)
Enable metrics in configuration:
# Add to configuration.yml
telemetry:
metrics:
enabled: true
address: tcp://0.0.0.0:9959
buffers:
read: 4096
write: 4096
timeouts:
read: 6s
write: 6s
idle: 30s Expose metrics port:
# Update docker-compose.yml
services:
authelia:
ports:
- "9091:9091"
- "9959:9959" # Metrics endpoint Scrape with Prometheus:
# prometheus.yml
scrape_configs:
- job_name: 'authelia'
static_configs:
- targets: ['authelia:9959'] Import Grafana dashboard:
- Dashboard ID: 14837 (Authelia Overview)
Log Monitoring
# View authentication attempts
docker-compose logs authelia | grep "Successful authentication"
# View failed logins
docker-compose logs authelia | grep "failed authentication"
# View 2FA enrollments
docker-compose logs authelia | grep "TOTP registration"
# Monitor in real-time
docker-compose logs -f authelia Conclusion
Congratulations! You’ve deployed a production-ready Authelia instance with comprehensive SSO and 2FA protection for your homelab. You now have:
- ✅ Centralized authentication for all services behind reverse proxy
- ✅ Multi-factor authentication with TOTP and WebAuthn
- ✅ Integration with Traefik or Nginx Proxy Manager
- ✅ Granular access control with user, group, and network-based rules
- ✅ Bypass rules for API endpoints and special cases
- ✅ Secure session management with remember-me functionality
- ✅ (Optional) LDAP integration for enterprise environments
Next Steps
- Add More Protected Services: Apply Authelia middleware to additional applications
- Fine-tune Access Rules: Create user-specific and group-based policies
- Enable Monitoring: Set up Prometheus and Grafana dashboards
- Implement High Availability: Deploy Redis cluster and multiple Authelia instances
- Regular Backups: Automate PostgreSQL and configuration backups
Maintenance Checklist
Weekly:
- Review authentication logs for suspicious activity
- Check failed login attempts
- Verify backup codes are stored securely
Monthly:
- Update Authelia to latest version
- Review and update access control rules
- Test disaster recovery procedures
- Rotate SMTP credentials
Quarterly:
- Security audit of all protected services
- Review user accounts and group memberships
- Update documentation
- Test 2FA enrollment and recovery processes
Resources
- Official Documentation: https://www.authelia.com/
- Configuration Reference: https://www.authelia.com/configuration/prologue/introduction/
- GitHub Repository: https://github.com/authelia/authelia
- Community Discord: https://discord.authelia.com/
Final Thoughts
Authelia strikes the perfect balance between security and simplicity for homelabs. Its lightweight footprint, reverse proxy-native design, and comprehensive 2FA support make it ideal for protecting services without the overhead of enterprise IdP solutions.
By implementing Authelia, you’ve transformed your homelab from a collection of individually authenticated services into a unified, secure infrastructure with enterprise-grade authentication—all while maintaining complete control over your data and identity management.
Your homelab is now protected by SSO and 2FA. Happy homelabbing!
Guide Version: 1.0 Last Updated: December 2025 Authelia Version: 4.38+ Tested On: Ubuntu 22.04, Docker 24.0+
Author Note: This guide is maintained as part of the homelabbing.io project. Found an issue or have improvements? Contribute on GitHub!