23 KiB
Root Cause Analysis: Authentik Proxy Outpost Configuration Failure
Incident ID: RCA-001
Date: 2026-06-14
Severity: High (Service Outage)
Status: Resolved
Author: AI Assistant (Frank v6)
Executive Summary
Four Authentik proxy outpost containers (prowlarr_outpost, radarr_outpost, sonarr_outpost, sabnzbd_outpost) failed to connect to the Authentik server, resulting in complete inaccessibility of protected services. The outposts continuously returned 404 Not Found errors when attempting to fetch configuration from the Authentik API.
Root Cause: Authentik outpost configuration stored in the database overrides container environment variables. The authentik_host field in the Authentik admin panel contained values that prevented the outposts from successfully connecting to the Authentik server.
Resolution: Updated the authentik_host field in Authentik admin panel to http://authentik_server:9000 for all four outposts, matching the internal Docker network configuration.
Impact Duration: ~2 hours
Services Affected: Prowlarr, Radarr, Sonarr, Sabnzbd
Timeline
Initial State (Before Incident)
- Services running but not externally accessible
- Hairpin NAT issue preventing internal clients from using external DNS
- Services reachable internally via
10.0.0.151 - Traefik reverse proxy functioning correctly
13:00 UTC - Problem Discovery
- User reported services accessible internally but returning 404 externally
- Initial hypothesis: Traefik routing or DNS issue
- Verified Traefik listening on
0.0.0.0:80and0.0.0.0:443 - Confirmed DNS resolving correctly to external IP
73.106.212.82
13:05 UTC - Authentik Outpost Investigation Begins
- Examined outpost container logs
- Found continuous
404 Not Founderrors in all four outpost containers:{"error":"404 Not Found","event":"Failed to fetch outpost configuration, retrying in 3 seconds","level":"error","logger":"authentik.outpost.ak-api-controller"} - Observed exponential backoff pattern (3s → 6s → 12s → 24s → 48s)
13:15 UTC - Configuration Analysis
- Checked container environment variables via
docker exec - Initial configuration:
AUTHENTIK_HOST=https://authentik_server:9443AUTHENTIK_HOST_BROWSER=https://sso.castaldifamily.comAUTHENTIK_INSECURE=false
13:20 UTC - First Remediation Attempt
- Updated compose files to use HTTPS with insecure flag:
- Changed
AUTHENTIK_HOSTtohttps://authentik_server:9443 - Added
AUTHENTIK_HOST_BROWSER=https://sso.castaldifamily.com - Set
AUTHENTIK_INSECURE=true
- Changed
- Deployed via Git push to Komodo
- Result: Failed - 404 errors persisted
13:30 UTC - Authentik Admin Panel Configuration
- Changed Integration type from "Local Docker connection" to "No integration active"
- Set
authentik_host_insecure=truein admin panel - Verified via API that changes were reflected
- Result: Failed - 404 errors persisted
13:40 UTC - Discovery of Configuration Precedence Issue
- Queried Authentik API:
/api/v3/outposts/instances/ - Discovered
authentik_hostin API response:"https://sso.castaldifamily.com/" - Identified that database configuration was overriding environment variables
- User attempted to clear
authentik_hostfield (set to null/blank) - Result: Failed - Authentik validation error: "wrong value type for field 'authentik_host' - should be 'str' instead of value 'None' of type 'NoneType'"
13:50 UTC - Protocol and Port Testing
- Switched from HTTPS port 9443 to HTTP port 9000
- Updated compose files:
AUTHENTIK_HOST=http://authentik_server:9000 - Updated Authentik admin:
authentik_host=http://authentik_server:9000 - Result: Failed - 404 errors persisted
13:55 UTC - Network Debugging
- Tested API accessibility from inside outpost container
- Using hostname:
wget http://authentik_server:9000/api/v3/outposts/instances/→ 404 - Using IP address:
wget http://172.18.0.31:9000/api/v3/outposts/instances/→ 200 OK (Success) - Discovery: Host header validation issue suspected
14:00 UTC - IP Address Configuration Attempt
- Updated compose files to use IP:
AUTHENTIK_HOST=http://172.18.0.31:9000 - Prepared to update Authentik admin panel
- User reported success using hostname
http://authentik_server:9000in admin panel - Result: Success - Outposts connected successfully
14:05 UTC - Resolution Confirmed
- Logs showed
"Loaded application"messages - Successful proxy requests with HTTP 200 status codes
- Services accessible externally through Authentik authentication
- All four outposts (prowlarr, radarr, sonarr, sabnzbd) operational
Root Cause Analysis
Primary Root Cause
Configuration Precedence: Authentik proxy outposts prioritize configuration stored in the Authentik database over container environment variables. When an outpost starts, it queries the Authentik API at /api/v3/outposts/instances/ to fetch its configuration. The response includes a config object with an authentik_host field. If this field has a value in the database, it completely overrides the AUTHENTIK_HOST environment variable.
Contributing Factors
-
Incomplete Documentation Understanding
- The interaction between environment variables and database configuration was not well understood
- Authentik documentation does not clearly state that database values override environment variables
- The admin panel allows setting
authentik_hostbut does not explain when to use it vs. environment variables
-
External URL in Database Configuration
- Initial Authentik setup stored
https://sso.castaldifamily.com/as theauthentik_host - This external URL was inaccessible from within the Docker network due to hairpin NAT limitations
- The outposts attempting to connect to the external URL from inside Docker resulted in routing failures
- Initial Authentik setup stored
-
TLS Certificate Validation
- Initial attempts used HTTPS with the internal hostname
authentik_server - The TLS certificate was valid for
*.castaldifamily.com, not for the Docker internal hostname - This contributed to connection failures even when using the correct internal endpoint
- Initial attempts used HTTPS with the internal hostname
-
Docker Network DNS Resolution
- While Docker DNS correctly resolved
authentik_serverto172.18.0.31, there appeared to be Host header validation differences - Direct
wget/curlrequests from containers tohttp://authentik_server:9000returned 404 - The same requests using the IP address
http://172.18.0.31:9000succeeded - However, the Authentik outpost application code successfully connected using the hostname
- While Docker DNS correctly resolved
-
GitOps Deployment Timing
- Changes to compose files were deployed via Git commits triggering Komodo
- This created a delay between file changes and container updates
- Multiple iterations were required before all configuration aligned
What Worked vs. What Didn't
What Didn't Work
| Approach | Configuration | Result | Reason |
|---|---|---|---|
| External HTTPS URL | https://sso.castaldifamily.com |
404 errors | Hairpin NAT prevented internal Docker containers from reaching external IP |
| Internal HTTPS with hostname | https://authentik_server:9443 |
404 errors | TLS certificate mismatch + database config override |
Blank/null authentik_host |
Attempted to clear field | Validation error | Authentik requires a string value, not null |
| IP address in env var only | AUTHENTIK_HOST=http://172.18.0.31:9000 (env only) |
404 errors | Database config still had old value, which took precedence |
What Worked
| Approach | Configuration | Result | Key Success Factor |
|---|---|---|---|
| Internal HTTP with hostname | Admin Panel: authentik_host=http://authentik_server:9000Env Var: AUTHENTIK_HOST=http://authentik_server:9000 |
✅ Success | Both configurations aligned; outpost application code handles hostname correctly |
| Insecure flag | AUTHENTIK_INSECURE=true and authentik_host_insecure=true |
✅ Success | Disabled TLS verification for internal Docker network |
| Integration type | Changed to "No integration active" | ✅ Success | Removed automatic configuration interference |
Technical Deep Dive
Authentik Outpost Configuration Flow
┌─────────────────────────────────────────────────────────────┐
│ 1. Outpost Container Starts │
│ - Loads environment variables (AUTHENTIK_HOST, etc.) │
│ - Initializes with fallback values │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. Query Authentik API │
│ GET /api/v3/outposts/instances/ │
│ Authorization: Bearer {AUTHENTIK_TOKEN} │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. Receive Configuration from Database │
│ { │
│ "config": { │
│ "authentik_host": "http://authentik_server:9000", │
│ "authentik_host_browser": "", │
│ "authentik_host_insecure": true │
│ } │
│ } │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. Apply Configuration (Database Overrides Environment) │
│ IF config.authentik_host EXISTS AND NOT EMPTY: │
│ USE config.authentik_host │
│ ELSE: │
│ USE AUTHENTIK_HOST environment variable │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. Connect to Authentik Server │
│ - Fetch application configuration │
│ - Load providers, flows, policies │
│ - Initialize proxy routes │
└─────────────────────────────────────────────────────────────┘
Network Topology
External Network (Internet)
│
│ Port Forwarding: 80→10.0.0.151:80, 443→10.0.0.151:443
│
▼
┌────────────────────────────────────────────────────────────┐
│ Heimdall Server (10.0.0.151) │
│ │
│ Docker Network: proxy-net (172.18.0.0/16) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Traefik (172.18.0.x) │ │
│ │ - Listens: 0.0.0.0:80, 0.0.0.0:443 │ │
│ │ - Routes based on Host header │ │
│ └──────────┬──────────────────────────────────────────┘ │
│ │ │
│ ┌──────────┴──────────────────────────────────────────┐ │
│ │ Authentik Server (172.18.0.31) │ │
│ │ - Ports: 9000 (HTTP), 9443 (HTTPS) │ │
│ │ - Hostname: authentik_server │ │
│ └──────────┬──────────────────────────────────────────┘ │
│ │ │
│ ┌──────────┴──────────────────────────────────────────┐ │
│ │ Proxy Outposts │ │
│ │ - prowlarr_outpost (172.18.0.x) │ │
│ │ - radarr_outpost (172.18.0.x) │ │
│ │ - sonarr_outpost (172.18.0.x) │ │
│ │ - sabnzbd_outpost (172.18.0.x) │ │
│ │ │ │
│ │ Each outpost connects to: │ │
│ │ http://authentik_server:9000/api/v3/... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
DNS: *.castaldifamily.com → 73.106.212.82 (External IP)
Hairpin NAT Issue: Internal clients can't reach external IP
Key Configuration Files
Working Configuration:
# nodes/heimdall/prowlarr/compose.yaml
services:
prowlarr_outpost:
image: ghcr.io/goauthentik/proxy:2026.2.2
container_name: prowlarr_outpost
environment:
AUTHENTIK_HOST: http://authentik_server:9000 # ✅ Matches admin panel
AUTHENTIK_HOST_BROWSER: https://sso.castaldifamily.com
AUTHENTIK_TOKEN: 42FCcV9gmTfixaak77xW4eAZIMUUJ0u5vGsxvumfo1Lav5DIyLViDz4xqinE
AUTHENTIK_INSECURE: true # ✅ Disables TLS verification
networks:
- proxy-net
Authentik Admin Panel:
- Navigate to: Applications → Outposts → prowlarr_outpost
- Configuration section:
authentik_host:http://authentik_server:9000✅authentik_host_insecure:true✅authentik_host_browser: (empty/blank) ✅
- Integration: "No integration active"
Lessons Learned
What We Learned
-
Database Configuration Takes Precedence
- Authentik outposts fetch configuration from the database via API
- This configuration overrides container environment variables
- Both sources must be aligned for successful operation
-
Field Validation Requirements
- Authentik requires
authentik_hostto be a valid string - Cannot be set to
null,None, or blank in the admin panel - Must provide a valid URL even if using environment variables
- Authentik requires
-
Internal vs. External URLs
- External URLs (e.g.,
https://sso.castaldifamily.com) don't work for internal Docker communication - Hairpin NAT prevents containers from reaching the host's external IP
- Internal Docker hostnames (e.g.,
authentik_server) or IP addresses work correctly
- External URLs (e.g.,
-
Protocol and Port Selection
- HTTPS (port 9443) requires valid TLS certificates matching the hostname
- HTTP (port 9000) works for internal Docker network communication
- Using
AUTHENTIK_INSECURE=truebypasses TLS validation when necessary
-
GitOps Deployment Considerations
- Environment variable changes require container recreation
- Komodo auto-deployment has a slight delay after git push
- Must verify actual container environment after deployment
- Database configuration changes take effect immediately on outpost restart
-
Debugging Methodology
- Check container logs first for immediate error messages
- Verify environment variables inside running containers (
docker exec) - Query the Authentik API to see database configuration
- Test network connectivity from inside containers
- Distinguish between configuration issues and network issues
What Went Well
-
Systematic Troubleshooting
- Methodical progression from symptoms to root cause
- Each hypothesis was tested with verification steps
- Logs and API responses provided clear evidence
-
Infrastructure Observability
- Container logs accessible and informative
- API endpoints available for configuration introspection
- Docker network inspection tools worked reliably
-
GitOps Workflow
- Changes tracked in version control
- Automated deployment reduced manual errors
- Rollback capability available if needed
What Could Be Improved
-
Documentation Gaps
- Need better documentation of Authentik configuration precedence
- Should document the relationship between environment variables and database config
- Create runbook for Authentik outpost troubleshooting
-
Initial Configuration
- Should have used internal URLs from the start
- Better planning for Docker network topology
- More thorough testing during initial setup
-
Monitoring and Alerting
- No automated alerts when outposts fail to connect
- No health checks monitoring outpost status
- Could benefit from Grafana dashboard showing outpost health
-
Testing Procedures
- Should have tested outpost connectivity before production use
- Need integration tests for Authentik configuration changes
- Should validate both internal and external access paths
Prevention Measures
Immediate Actions Taken
-
✅ Documented Working Configuration
- This RCA serves as reference for future troubleshooting
- Configuration examples included in this document
-
✅ Verified All Outposts
- Confirmed prowlarr_outpost, radarr_outpost, sonarr_outpost, sabnzbd_outpost all functioning
- Validated logs show successful authentication and proxying
-
✅ Updated Compose Files
- All outpost compose files now use correct internal configuration
- Changes committed to version control
Recommended Future Actions
-
Create KBA Document
- Knowledge Base Article for Authentik outpost troubleshooting
- Include configuration precedence explanation
- Step-by-step diagnostic procedures
-
Create SOP for Authentik Outpost Deployment
- Standard Operating Procedure for adding new outposts
- Configuration checklist:
- Set
authentik_hostin admin panel to internal URL - Set
authentik_host_insecure=truefor HTTP - Leave
authentik_host_browserempty or set to external URL - Set Integration to "No integration active"
- Match environment variables to admin panel config
- Verify logs show "Loaded application" after deployment
- Test external access through Traefik
- Set
-
Implement Health Monitoring
- Add Prometheus metrics export from Authentik
- Create Grafana dashboard for outpost status
- Set up alerting for outpost connection failures
- Monitor API endpoint
/api/v3/outposts/instances/health
-
Enhance Network Configuration
- Consider implementing internal DNS (Pi-hole or similar)
- Resolve
*.castaldifamily.comto10.0.0.151internally - Eliminates hairpin NAT issues for internal clients
-
Automate Configuration Validation
- Script to verify compose file and admin panel config match
- Pre-deployment checks for Authentik outposts
- Automated testing of outpost connectivity
-
Documentation Improvements
- Update homelab documentation with Authentik architecture
- Document Docker network topology
- Create troubleshooting flowchart for authentication issues
References
Related Documentation
External Resources
Git Commits Related to This Incident
f770331- Initial outpost environment variable updates (HTTPS, insecure flag)f10155a- Changed AUTHENTIK_HOST to HTTP port 90007b250b9- Attempted IP address configuration (reverted)
Appendix A: Error Messages
Typical 404 Error Log Entry
{
"error": "404 Not Found",
"event": "Failed to fetch outpost configuration, retrying in 3 seconds",
"level": "error",
"logger": "authentik.outpost.ak-api-controller",
"timestamp": "2026-06-14T13:05:57Z"
}
Successful Connection Log Entry
{
"event": "Loaded application",
"host": "prowlarr.castaldifamily.com",
"level": "info",
"logger": "authentik.outpost.proxyv2",
"name": "Provider for Prowlarr",
"timestamp": "2026-06-14T13:22:05Z"
}
Appendix B: Diagnostic Commands
Check Outpost Container Logs
ssh chester@10.0.0.151 'docker logs prowlarr_outpost 2>&1 | tail -25'
Verify Container Environment Variables
ssh chester@10.0.0.151 'docker exec prowlarr_outpost env | grep AUTHENTIK'
Query Authentik API Configuration
curl -k -s \
-H "Authorization: Bearer {AUTHENTIK_TOKEN}" \
https://10.0.0.151:9443/api/v3/outposts/instances/ | jq
Test Connectivity from Inside Container
ssh chester@10.0.0.151 'docker exec prowlarr_outpost wget -O- \
--header="Authorization: Bearer {AUTHENTIK_TOKEN}" \
http://authentik_server:9000/api/v3/outposts/instances/ 2>&1'
Check Docker Network Details
ssh chester@10.0.0.151 'docker inspect authentik_server \
--format="{{json .NetworkSettings.Networks}}" | jq'
Approval and Sign-off
Prepared By: AI Assistant (Frank v6) - Homelab Operations
Date: 2026-06-14
Status: Draft
Technical Review: Pending
Management Approval: Pending
Document Version: 1.0
Last Updated: 2026-06-14
Next Review Date: 2026-07-14