Authelia SSO Authentication
Overview
Authelia is a robust authentication and authorization server providing Single Sign-On (SSO) capabilities for the mixi.cz infrastructure. It integrates with our existing LDAP directory and provides multi-factor authentication for secure access to services like Grafana and Home Assistant.
Key Features
- LDAP Integration: Authenticates against LLDAP (it used to be OpenLDAP directory on julie in past)
- Multi-Factor Authentication: TOTP (Google Authenticator) and WebAuthn/FIDO2 support
- Network-Based Access Control: Internal network bypass, external authentication required
- Session Management: Configurable session timeouts and remember-me functionality
- Go-Based: Lightweight, fast, and secure implementation
Architecture
Infrastructure Components
- Platform: k3s cluster with Traefik ingress controller
- Storage: Longhorn persistent volumes, SQLite database
- Load Balancer: Apache2 reverse proxy for internet-facing access
- Network: Internal bypass for 192.168.0.0/22, external authentication required
- LDAP: OpenLDAP server (julie-local.mixi.cz:389)
Authentication Flow
graph TB
User[👤 User] --> Browser[🌐 Browser]
Browser --> Apache[Apache Reverse Proxy
SSL Termination]
Apache --> Traefik[Traefik Ingress
piks01.intranet]
Traefik --> AuthMiddleware{Authelia Middleware
ForwardAuth}
AuthMiddleware --> IPCheck{IP Address Check}
IPCheck -->|192.168.0.0/22| Bypass[✅ Internal Bypass]
IPCheck -->|External IP| AuthRequired[🔐 Authentication Required]
AuthRequired --> AuthPage[Authelia Login Page
auth.mixi.cz]
AuthPage --> LDAP[OpenLDAP
julie-local.mixi.cz:389]
LDAP -->|Valid Credentials| MFA{Multi-Factor Auth}
MFA --> TOTP[📱 TOTP Code
Google Authenticator]
MFA --> WebAuthn[🔑 WebAuthn/FIDO2
YubiKey, Touch ID]
TOTP --> Authenticated[✅ Authenticated]
WebAuthn --> Authenticated
Bypass --> Service[🎯 Target Service]
Authenticated --> Service
Service --> Grafana[📊 Grafana]
Service --> HomeAssistant[🏠 Home Assistant]
style User fill:#263345
style AuthRequired fill:#423627
style Authenticated fill:#26382d
style Service fill:#362d3b
Traffic Flow Patterns
External Access (Internet → Services)
Internet User → Apache (SSL:443) → Traefik → Authelia → Authentication → Target Service
Internal Access (LAN → Services)
Internal User → Traefik → Authelia (IP Bypass) → Target Service
Configuration
Core Settings
Server Configuration
server:
address: "tcp://0.0.0.0:9091"
timeouts:
read: 6s
write: 6s
idle: 30s
LDAP Authentication
authentication_backend:
ldap:
url: ldap://julie-local.mixi.cz:389
base_dn: ou=People,dc=mixi,dc=cz
username_attribute: mail
users_filter: "(&({username_attribute}={input})(objectClass=inetOrgPerson))"
user: cn=auth,dc=mixi,dc=cz
Access Control Rules
access_control:
default_policy: deny
rules:
# Internal network bypass
- domain: ["*.mixi.cz"]
policy: bypass
networks: ["192.168.0.0/22"]
# External access requires 2FA
- domain: ["grafana.mixi.cz", "ha.mixi.cz"]
policy: two_factor
Session Management
session:
domain: mixi.cz
expiration: 16h # Maximum session lifetime
inactivity: 30m # Idle timeout
remember_me: 30d # "Remember me" duration
Multi-Factor Authentication
TOTP (Time-based One-Time Password)
totp:
issuer: mixi.cz
algorithm: sha256
digits: 6
period: 30
Supported Apps: Google Authenticator, Authy, 1Password, Microsoft Authenticator
WebAuthn/FIDO2
webauthn:
display_name: "mixinet přihlášení"
timeout: 60s
user_verification: preferred
Supported Devices: YubiKey, SoloKey, Touch ID, Face ID, Windows Hello
Deployment
Prerequisites
- k3s cluster with Traefik ingress controller
- Longhorn storage class available
- OpenLDAP server accessible from cluster
- Apache reverse proxy configured for SSL termination
- DNS records for auth.mixi.cz, grafana.mixi.cz, ha.mixi.cz
Deployment Steps
-
Generate Secrets
# Generate random secrets (32+ characters) openssl rand -hex 32 # JWT_SECRET openssl rand -hex 32 # SESSION_SECRET openssl rand -hex 32 # STORAGE_ENCRYPTION_KEY -
Configure Secrets
# Edit authelia-secret.yaml with generated secrets # Add LDAP and SMTP passwords kubectl apply -f authelia-secret.yaml -
Deploy Authelia Components
kubectl apply -f authelia-deployment.yaml # Namespace, PVC, Deployment, Service kubectl apply -f authelia-config.yaml # ConfigMap with configuration kubectl apply -f authelia-middleware.yaml # Traefik ForwardAuth middleware -
Configure Services
# Apply service-specific ingress configurations kubectl apply -f grafana-ingress.yaml kubectl apply -f home-assistant-ingress.yaml -
Enable Authentication (Gradual Migration)
# Uncomment middleware annotation in ingress files: # traefik.ingress.kubernetes.io/router.middlewares: authelia-authelia@kubernetescrd
Health Check
# Port forward to test Authelia health
kubectl port-forward -n authelia svc/authelia 9091:80
curl http://localhost:9091/api/health
# Expected response: {"status":"UP"}
User Experience
First-Time Setup
- User navigates to grafana.mixi.cz from external network
- Redirected to auth.mixi.cz login page
- Enters credentials (email + password)
- Sets up 2FA: Scans QR code with authenticator app or registers security key
- Access granted to Grafana with session valid for 16 hours
Daily Usage
Internal Network (192.168.0.0/22)
- Direct access to all services
- No authentication required
- Seamless experience for home users
External Network (Internet)
- Authentication required for each service
- 2FA prompt on new devices/sessions
- Remember me option for 30-day sessions
- Session sharing across mixi.cz services
Session Behavior
| Scenario | Experience |
|---|---|
| Active browsing | Session valid for 16 hours maximum |
| Idle for 30min | Automatic logout, re-authentication required |
| Remember me checked | 30-day session on trusted device |
| Multiple services | Single login for grafana.mixi.cz + ha.mixi.cz |
Security Features
Network-Based Access Control
- Internal bypass: 192.168.0.0/22 network automatically trusted
- External enforcement: Internet users always require authentication
- Real IP detection: Apache forwards X-Real-IP headers for accurate detection
Multi-Factor Authentication
- TOTP codes: Time-based, 6-digit codes rotating every 30 seconds
- Hardware keys: FIDO2/WebAuthn support for YubiKey, security keys
- Biometric authentication: Touch ID, Face ID, Windows Hello support
Session Security
- Secure cookies: HttpOnly, Secure, SameSite=Lax
- Session encryption: AES encryption with rotating keys
- Automatic expiration: Both absolute and inactivity timeouts
- Cross-site protection: Domain-scoped sessions
Troubleshooting
Common Issues
Authentication Failures
Symptom: "Invalid credentials" despite correct password
# Check LDAP connectivity
kubectl logs -n authelia -l app=authelia | grep -i ldap
# Verify LDAP user search
ldapsearch -H ldap://julie-local.mixi.cz:389 \
-D "cn=auth,dc=mixi,dc=cz" -W \
-b "ou=People,dc=mixi,dc=cz" \
"(&(mail=user@mixi.cz)(objectClass=inetOrgPerson))"
Session Issues
Symptom: Frequent logouts or "session expired"
# Check session configuration
kubectl get configmap -n authelia authelia-config -o yaml | grep -A 5 session
# Verify session storage
kubectl exec -n authelia deployment/authelia -- ls -la /config/
TOTP Setup Problems
Symptom: QR code not working or codes rejected
# Check TOTP configuration
kubectl logs -n authelia -l app=authelia | grep -i totp
# Verify time synchronization
kubectl exec -n authelia deployment/authelia -- date
Health Monitoring
Service Status
# Check Authelia pod status
kubectl get pods -n authelia
# View logs
kubectl logs -n authelia -l app=authelia -f
# Test health endpoint
kubectl port-forward -n authelia svc/authelia 9091:80
curl http://localhost:9091/api/health
Performance Metrics
# Check resource usage
kubectl top pods -n authelia
# Database size
kubectl exec -n authelia deployment/authelia -- du -h /config/db.sqlite3
Log Analysis
Authentication Events
# Recent authentication attempts
kubectl logs -n authelia -l app=authelia --tail=100 | grep -i "authentication"
# Failed login attempts
kubectl logs -n authelia -l app=authelia | grep -i "failed\|error"
# Session creation/destruction
kubectl logs -n authelia -l app=authelia | grep -i "session"
Maintenance
Regular Tasks
Secret Rotation (Quarterly)
# Generate new secrets
openssl rand -hex 32 > new_session_secret
# Update secret
kubectl patch secret -n authelia authelia-secret -p='{"stringData":{"SESSION_SECRET":"'$(cat new_session_secret)'"}}'
# Restart Authelia
kubectl rollout restart -n authelia deployment/authelia
Database Maintenance (Monthly)
# Backup database
kubectl exec -n authelia deployment/authelia -- sqlite3 /config/db.sqlite3 ".backup /tmp/backup.db"
kubectl cp authelia/$(kubectl get pods -n authelia -l app=authelia -o name | cut -d/ -f2):/tmp/backup.db ./authelia-backup-$(date +%Y%m%d).db
# Vacuum database
kubectl exec -n authelia deployment/authelia -- sqlite3 /config/db.sqlite3 "VACUUM;"
Log Rotation (Weekly)
# Check log size
kubectl logs -n authelia -l app=authelia | wc -l
# Archive old logs if needed
kubectl logs -n authelia -l app=authelia --previous > authelia-logs-$(date +%Y%m%d).log
Updates
Authelia Version Updates
# Check current version
kubectl get deployment -n authelia authelia -o jsonpath='{.spec.template.spec.containers[0].image}'
# Update image version in authelia-deployment.yaml
# Apply updated deployment
kubectl apply -f authelia-deployment.yaml
# Monitor rollout
kubectl rollout status -n authelia deployment/authelia
Configuration Changes
# Update configuration
kubectl apply -f authelia-config.yaml
# Restart to reload config
kubectl rollout restart -n authelia deployment/authelia
Integration Examples
Adding New Services
New Application with Authentication
# my-app-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
traefik.ingress.kubernetes.io/router.middlewares: authelia-authelia@kubernetescrd
name: my-app
spec:
rules:
- host: myapp.mixi.cz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
Access Control Rules
# Add to authelia-config.yaml access_control.rules
- domain: ["myapp.mixi.cz"]
policy: two_factor
# Optional: restrict to specific users
# subject: ["user:admin@mixi.cz"]
Apache Virtual Host Template
# myapp.mixi.cz.conf
<VirtualHost *:443>
ServerName myapp.mixi.cz
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/mixi.cz/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mixi.cz/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/mixi.cz/fullchain.pem
# Forward real client IP for Authelia
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Real-IP "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Proto "https"
ProxyPass / https://piks01.intranet/
ProxyPassReverse / https://piks01.intranet/
SSLProxyEngine On
SSLProxyVerify none
</VirtualHost>
File Structure
Configuration files are located in /home/mixi/pg/home/automation/kube/auth/:
Core Files
authelia-config.yaml- Main configuration (ConfigMap)authelia-deployment.yaml- Kubernetes deployment, service, PVCauthelia-middleware.yaml- Traefik ForwardAuth middlewareauthelia-secret.yaml- Sensitive data (excluded from git)
Service Files
grafana-ingress.yaml- Grafana ingress with authenticationhome-assistant-ingress.yaml- Home Assistant ingress with authenticationoptional-middlewares.yaml- Additional security middlewares
Apache Configuration
auth.mixi.cz.conf- Apache virtual host for Authelia*.mixi.cz.conf- Apache virtual hosts for individualapplications
Documentation
MIGRATION_GUIDE.md- Step-by-step deployment instructions.gitignore- Excludes sensitive files from git
References
Last updated: 2025-01-29 Deployment: mixi.cz k3s cluster