Step-by-step instructions for adding new subdomains with: - Let's Encrypt SSL via NPM - Authentik forward authentication - Troubleshooting common issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.3 KiB
Setting Up a New SSL-Secured, Authentik-Protected Host
This guide documents how to add a new public-facing subdomain with SSL (Let's Encrypt) and Authentik forward authentication through Nginx Proxy Manager (NPM).
Prerequisites
Before starting, ensure:
- DNS A Record: Create an A record for
<subdomain>.schweitz.netpointing to your public IP - Container Running: The target service container is running and accessible
- Network: Container is on
docker-dataplanenetwork (or accessible from NPM) - Authentik Running: Both Authentik server and outpost(s) are operational
Step 1: Authentik Configuration
1.1 Create a Proxy Provider
- Go to Authentik Admin → Applications → Providers
- Click Create → Select Proxy Provider
- Configure:
| Setting | Value |
|---|---|
| Name | <subdomain>.schweitz.net proxy |
| Authorization flow | default-provider-authorization-implicit-consent |
| Forward auth (single application) | Selected |
| External host | https://<subdomain>.schweitz.net |
Leave other settings as defaults (token validity 24 hours is fine).
1.2 Create an Application
- Go to Applications → Applications
- Click Create
- Configure:
| Setting | Value |
|---|---|
| Name | <Descriptive Name> (e.g., "Library Wiki") |
| Slug | <subdomain>-schweitz-net |
| Provider | Select the proxy provider created above |
| Launch URL | https://<subdomain>.schweitz.net |
1.3 Add Application to Outpost
- Go to Applications → Outposts
- Edit the standalone outpost (authentik-proxy on port 9443/9445)
- In Applications, add your new application to the selected list
- Click Update
Note
: If using both embedded and standalone outposts, add the application to whichever outpost your forward auth config points to (standalone at
localhost:9445in our setup).
Step 2: NPM Configuration
2.1 Create Proxy Host
In NPM Admin (port 8000 or via API):
Details Tab:
| Setting | Value |
|---|---|
| Domain Names | <subdomain>.schweitz.net |
| Scheme | http (usually) |
| Forward Hostname/IP | Container name or IP (e.g., wiki or 192.168.86.149) |
| Forward Port | Container's internal port (e.g., 3000) |
| Cache Assets | Off (unless needed) |
| Block Common Exploits | On |
| Websockets Support | On |
SSL Tab:
| Setting | Value |
|---|---|
| SSL Certificate | Request a new SSL Certificate |
| Force SSL | On |
| HTTP/2 Support | On |
| HSTS Enabled | On |
| Email for Let's Encrypt | jpmschweitzer@gmail.com |
| Agree to TOS | Yes |
Advanced Tab:
Paste the following configuration:
# Increase buffer size for large headers from Authentik
proxy_buffers 8 16k;
proxy_buffer_size 32k;
# Forward authentication via standalone outpost
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
# Capture auth response headers
auth_request_set $auth_cookie $upstream_http_set_cookie;
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;
# Forward auth headers to application
add_header Set-Cookie $auth_cookie;
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;
# Outpost proxy location
location /outpost.goauthentik.io {
proxy_pass https://localhost:9445/outpost.goauthentik.io;
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
# Signin redirect handler - MUST use relative path, not absolute URL
location @goauthentik_proxy_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
}
Critical: The redirect in
@goauthentik_proxy_signinMUST use a relative path (/outpost.goauthentik.io/start), NOT an absolute URL. Usinghttps://auth.schweitz.net/outpost.goauthentik.io/startwill cause a 404 error due to host header mismatch.
2.2 Save and Verify
- Click Save
- Verify nginx status shows online (no errors)
- If errors occur, check the Advanced config syntax
Step 3: Testing
3.1 Initial Test
- Open an incognito/private browser window
- Navigate to
https://<subdomain>.schweitz.net - You should be redirected to Authentik login (Google OAuth or local)
- After login, you should see your application
3.2 SSO Cookie Test
If already logged into another .schweitz.net service:
- Open a new tab (same browser, not incognito)
- Navigate to the new subdomain
- You should access the application without re-authenticating (SSO cookie shared across
.schweitz.net)
Troubleshooting
Authentik 404 "Not Found" Error
Symptom: Redirected to auth.schweitz.net/outpost.goauthentik.io/start?rd=... but see 404
Causes & Fixes:
-
Absolute URL in redirect (most common)
- Fix: Change
return 302 https://auth.schweitz.net/outpost.goauthentik.io/start...toreturn 302 /outpost.goauthentik.io/start...
- Fix: Change
-
Application not added to outpost
- Fix: Go to Authentik → Outposts → Edit standalone outpost → Add application
-
Provider not linked to application
- Fix: Edit application → Select the correct proxy provider
Nginx Config Error / nginx_online: false
Symptom: NPM shows nginx error when saving
Causes & Fixes:
-
Undefined variable
$connection_upgrade- Fix: Remove WebSocket lines (
proxy_http_version,Upgrade,Connectionheaders) from advanced config. NPM handles WebSockets via the "Websockets Support" toggle.
- Fix: Remove WebSocket lines (
-
Syntax error in advanced config
- Fix: Verify all brackets are closed, semicolons present
502 Bad Gateway
Symptom: Auth works but application shows 502
Causes & Fixes:
-
Wrong forward host/port
- Fix: Verify container name and port in NPM proxy host settings
- Test:
curl http://<forward_host>:<forward_port>from NPM container
-
Container not on correct network
- Fix: Ensure container is on
docker-dataplanenetwork
- Fix: Ensure container is on
-
Outpost not running
- Check:
docker ps | grep authentik-proxy - Check logs:
docker logs authentik-proxy
- Check:
SSL Certificate Not Provisioning
Symptom: Certificate request fails
Causes & Fixes:
-
DNS not propagated
- Fix: Wait for DNS propagation, verify with
dig <subdomain>.schweitz.net
- Fix: Wait for DNS propagation, verify with
-
Port 80 blocked
- Fix: Ensure port 80 is open for Let's Encrypt HTTP-01 challenge
Redirect Loop
Symptom: Browser shows "too many redirects"
Causes & Fixes:
-
Auth domain has forward auth enabled
- Fix:
auth.schweitz.netmust NOT have forward auth (would create loop)
- Fix:
-
Cookie domain mismatch
- Fix: Verify Authentik cookie domain is
.schweitz.net
- Fix: Verify Authentik cookie domain is
Reference Files
| File | Purpose |
|---|---|
stacks/authentik.yml |
Authentik server, worker, and standalone outpost |
stacks/wiki.yml |
Example: Wiki.js container configuration |
npm-configs/organizr-forward-auth.conf |
Legacy reference (has bugs, do not use directly) |
Architecture Overview
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ User Browser │────▶│ NPM (port 80/ │────▶│ Target Service │
│ │ │ 443) │ │ (e.g., Wiki.js)│
└─────────────────┘ └────────┬────────┘ └─────────────────┘
│
│ auth_request
▼
┌─────────────────┐ ┌─────────────────┐
│ Authentik │────▶│ Authentik │
│ Standalone │ │ Server │
│ Outpost (9445) │ │ (auth.schweitz │
└─────────────────┘ │ .net) │
└─────────────────┘
Flow:
- User requests
https://<subdomain>.schweitz.net - NPM's
auth_requestdirective checks with Authentik outpost - If not authenticated: redirect to Authentik login
- User authenticates (Google OAuth, etc.)
- Authentik sets session cookie for
.schweitz.net - User redirected back,
auth_requestsucceeds - NPM proxies request to target service
Last Updated: 2025-12-13 Based on: library.schweitz.net setup session