11 KiB
Authentik Forward Authentication Deployment Summary
Overview
Successfully deployed Authentik forward authentication to all NPM-managed domains. All protected sites now require SSO authentication via Authentik before access is granted.
Deployment Date
2025-11-16
Architecture
Components
-
Authentik Server (
authentik-server)- Port: 9000
- Container:
authentik-server - Purpose: Main authentication server
-
Authentik Proxy Outpost (
authentik-proxy-outpost)- Port: 9001 (HTTP), 9300 (Metrics)
- Container:
authentik-proxy-outpost - Purpose: Forward authentication endpoint for NPM
- Network: host mode (to match NPM)
- Image:
ghcr.io/goauthentik/proxy:latest
-
Nginx Proxy Manager (
nginx-proxy-manager)- Ports: 80, 81, 443
- Purpose: Reverse proxy with SSL termination
- Forward auth endpoint:
http://192.168.86.149:9001/outpost.goauthentik.io/auth/nginx
Authentication Flow
1. User → https://home.schweitz.net
2. NPM → auth_request to http://192.168.86.149:9001/outpost.goauthentik.io/auth/nginx
3. Outpost → validates session with Authentik Server (port 9000)
4. If not authenticated:
a. NPM → redirects to /outpost.goauthentik.io/start?rd=https://home.schweitz.net/
b. Outpost → redirects to https://auth.schweitz.net/if/flow/...
c. User → logs in via Google OAuth
d. Authentik → sets session cookie
e. Redirect → back to https://home.schweitz.net/
5. If authenticated:
a. Request passes through with user headers
Protected Domains
All NPM proxy hosts now require authentication:
- 192.168.86.149 - Direct IP access
- amp.schweitz.net - AMP Server
- cloud.schweitz.net - Nextcloud
- code.schweitz.net - VS Code Server
- git.schweitz.net - Gitea
- home.schweitz.net - Home Assistant/Dashboard
- media.schweitz.net - Media Server
- tatlock.schweitz.net - Tatlock Services
- tower-of-joy - Tower of Joy Services
Excluded Domains
- auth.schweitz.net - Authentik itself (cannot protect the auth provider)
Configuration Details
Authentik Proxy Provider
- Name:
npm-forward-auth-provider - ID: 2
- Mode:
forward_single - External Host:
https://auth.schweitz.net - Token Validity: 480 minutes (8 hours)
- Session Duration: 480 minutes (8 hours)
- Rolling Expiration: Active (sessions extend on use)
Authentik Outpost
- Name:
npm-forward-auth-outpost - ID:
5fbba1f4-e50f-4d3f-94e8-8d9f30bf7a51 - Type:
proxy - Provider:
npm-forward-auth-provider(ID: 2) - Token:
aVJXnn3I44NhTYRYxGtbP3kJLEKQrTEMwu9IPVrhzN3NZV4vakgztcEf2L44 - Container:
authentik-proxy-outpost - Listen:
0.0.0.0:9001(HTTP),0.0.0.0:9300(metrics)
NPM Configuration
Each protected proxy host has this advanced nginx configuration:
# Authentik Forward Authentication
# Send authentication requests to Authentik
auth_request /outpost.goauthentik.io/auth/nginx;
# Preserve authentication cookies
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# Get user information from Authentik
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
# Pass user info to backend
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
# On authentication failure, redirect to Authentik login
error_page 401 = @authentik_proxy_signin;
location @authentik_proxy_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}
# Authentik authentication endpoint
location /outpost.goauthentik.io {
proxy_pass http://192.168.86.149:9001/outpost.goauthentik.io;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Host $host;
}
Deployment Steps Taken
1. Created Proxy Provider
docker exec core-api /venv/bin/python /app/setup_authentik_forward_auth.py
- Created
npm-forward-auth-providerproxy provider (ID: 2) - Created
NPM Forward Authapplication (slug:npm-forward-auth) - Updated embedded outpost to include provider
2. Enabled Forward Auth on NPM Hosts
docker exec core-api /venv/bin/python /app/enable_npm_forward_auth.py
- Added forward auth configuration to all 9 NPM proxy hosts
- Initially pointed to
http://192.168.86.149:9000(incorrect)
3. Created Proxy Outpost
python3 -c "..." # Created outpost via Authentik API
- Created
npm-forward-auth-outpost(ID:5fbba1f4-e50f-4d3f-94e8-8d9f30bf7a51) - Authentik auto-created container via Docker service connection
- Retrieved token from auto-created container environment variables
4. Deployed Proxy Outpost Container
docker run -d \
--name authentik-proxy-outpost \
--restart unless-stopped \
--network host \
-e AUTHENTIK_HOST=http://192.168.86.149:9000 \
-e AUTHENTIK_TOKEN=aVJXnn3I44NhTYRYxGtbP3kJLEKQrTEMwu9IPVrhzN3NZV4vakgztcEf2L44 \
-e AUTHENTIK_LISTEN__HTTP=0.0.0.0:9001 \
-e AUTHENTIK_LISTEN__METRICS=0.0.0.0:9300 \
ghcr.io/goauthentik/proxy:latest
5. Updated NPM Hosts to Port 9001
docker exec core-api /venv/bin/python /app/fix_port_to_9001.py
- Updated all 9 hosts to point to
http://192.168.86.149:9001instead of port 9000
Verification
Testing Forward Auth
# Test ping endpoint
curl http://192.168.86.149:9001/outpost.goauthentik.io/ping
# Expected: 204 No Content
# Test unauthenticated request
curl -I http://home.schweitz.net
# Expected: 302 redirect to /outpost.goauthentik.io/start?rd=...
Logs
# Outpost logs
docker logs authentik-proxy-outpost
# Authentik server logs
docker logs authentik-server
# NPM logs
docker logs nginx-proxy-manager
Token & Session Management
Token Validity
- Initial validity: 480 minutes (8 hours)
- Rolling expiration: Token stays active on use
- Idle timeout: 8 hours after last activity
- Explicit logout: Token invalidated immediately at https://auth.schweitz.net/if/user/#/settings
Session Behavior
- Single login protects all domains under
*.schweitz.net - Cookie domain: Shared across all sites (set by individual domain)
- Persistent: Survives browser restarts until expiration/logout
- Secure: HTTPS-only, HttpOnly flag set
User Management
Adding Users
- Go to https://auth.schweitz.net/if/admin/
- Navigate to Directory → Users
- Click Create → Create and enroll user
- Enter user details
- Send enrollment invite
Current Access Control
All authenticated users can access all protected sites. To restrict:
- Go to https://auth.schweitz.net/if/admin/#/core/applications
- Select NPM Forward Auth application
- Go to Policy / Group / User Bindings
- Add specific users or groups
Troubleshooting
Check Outpost Status
docker ps | grep authentik-proxy-outpost
docker logs authentik-proxy-outpost --tail 50
Check Authentik Server
docker logs authentik-server --tail 50 | grep -i outpost
Test Endpoints
# Ping (should return 204)
curl -I http://192.168.86.149:9001/outpost.goauthentik.io/ping
# Auth endpoint (needs proper headers from nginx)
curl -I http://home.schweitz.net
Common Issues
-
502 Bad Gateway: Outpost not running or not reachable
- Check:
docker ps | grep authentik-proxy-outpost - Fix: Restart outpost container
- Check:
-
Redirect Loop: Misconfigured nginx or outpost
- Check: NPM advanced config points to port 9001
- Check: Outpost logs for errors
-
Session Expires Too Quickly: Token validity too short
- Check: Provider token_validity setting (should be 480 minutes)
Automation Scripts
Enable Forward Auth on New Sites
from src.clients.npm_client import get_npm_client
npm = get_npm_client()
proxy = await npm.create_proxy_host(
domain_names=["newsite.schweitz.net"],
forward_host="backend-container",
forward_port=8080,
ssl_enabled=True
)
await npm.enable_authentik_forward_auth(proxy["id"])
Bulk Operations
# Enable on all hosts
docker exec core-api /venv/bin/python /app/enable_npm_forward_auth.py
# Update to port 9001
docker exec core-api /venv/bin/python /app/fix_port_to_9001.py
Security Considerations
- ✓ HTTPS Required: All sites use SSL termination at NPM
- ✓ Secure Cookies: HttpOnly and Secure flags prevent XSS/MITM
- ✓ Token Rotation: Tokens extend on activity for security
- ✓ Audit Logging: Authentik logs all authentication events
- ⚠ MFA: Not yet enabled (future enhancement)
Monitoring
Health Checks
# Authentik server
curl http://192.168.86.149:9000/-/health/live/
# Proxy outpost
curl http://192.168.86.149:9001/outpost.goauthentik.io/ping
# Metrics
curl http://192.168.86.149:9300/metrics
Authentik Admin Dashboard
- URL: https://auth.schweitz.net/if/admin/
- Events: System → Events (view login attempts, failures)
- Active Sessions: System → Tokens
- Outpost Status: System → Outposts
Future Enhancements
- Multi-Factor Authentication: Enable TOTP/SMS for high-security sites
- Per-Site Access Control: Different user groups for different domains
- Rate Limiting: Prevent brute force attacks
- IP Whitelisting: Allow certain IPs without auth
- API Key Support: Service-to-service authentication
- Integration with Core API: Expose auth status via REST API
Related Documentation
- Main Documentation:
FORWARD_AUTH_CONFIGURATION.md - SSO Progress:
SSO_IMPLEMENTATION_PROGRESS.md - Security Plan:
security-implementation-plan.md - Authentik Docs: https://docs.goauthentik.io/docs/providers/proxy/
Notes
- The embedded Authentik outpost (ID:
fbbefe20-b2e1-4706-8533-7bfece51989c) is for Authentik's own web UI, not for external forward auth - Forward auth requires a separate proxy outpost container listening on its own port (9001)
- The outpost automatically created by Authentik via Docker service connection had the wrong port configuration
- We manually deployed the outpost with correct settings using
docker run - NPM uses host network mode, so the outpost must also use host mode or be accessible via host IP:port
- Token keys are only visible once during creation in the Authentik UI; we retrieved it from the auto-created container's environment variables
Completion Status
✅ COMPLETE - All protected sites now require Authentik authentication
Deployment successful as of 2025-11-16 15:41 UTC