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>
264 lines
9.3 KiB
Markdown
264 lines
9.3 KiB
Markdown
# 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:
|
|
|
|
1. **DNS A Record**: Create an A record for `<subdomain>.schweitz.net` pointing to your public IP
|
|
2. **Container Running**: The target service container is running and accessible
|
|
3. **Network**: Container is on `docker-dataplane` network (or accessible from NPM)
|
|
4. **Authentik Running**: Both Authentik server and outpost(s) are operational
|
|
|
|
## Step 1: Authentik Configuration
|
|
|
|
### 1.1 Create a Proxy Provider
|
|
|
|
1. Go to **Authentik Admin** → **Applications** → **Providers**
|
|
2. Click **Create** → Select **Proxy Provider**
|
|
3. 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
|
|
|
|
1. Go to **Applications** → **Applications**
|
|
2. Click **Create**
|
|
3. 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
|
|
|
|
1. Go to **Applications** → **Outposts**
|
|
2. Edit the **standalone outpost** (authentik-proxy on port 9443/9445)
|
|
3. In **Applications**, add your new application to the selected list
|
|
4. 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:9445` in 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:
|
|
|
|
```nginx
|
|
# 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_signin` MUST use a relative path (`/outpost.goauthentik.io/start`), NOT an absolute URL. Using `https://auth.schweitz.net/outpost.goauthentik.io/start` will cause a 404 error due to host header mismatch.
|
|
|
|
### 2.2 Save and Verify
|
|
|
|
1. Click **Save**
|
|
2. Verify nginx status shows online (no errors)
|
|
3. If errors occur, check the Advanced config syntax
|
|
|
|
## Step 3: Testing
|
|
|
|
### 3.1 Initial Test
|
|
|
|
1. Open an **incognito/private browser window**
|
|
2. Navigate to `https://<subdomain>.schweitz.net`
|
|
3. You should be redirected to Authentik login (Google OAuth or local)
|
|
4. After login, you should see your application
|
|
|
|
### 3.2 SSO Cookie Test
|
|
|
|
If already logged into another `.schweitz.net` service:
|
|
1. Open a new tab (same browser, not incognito)
|
|
2. Navigate to the new subdomain
|
|
3. 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**:
|
|
|
|
1. **Absolute URL in redirect** (most common)
|
|
- Fix: Change `return 302 https://auth.schweitz.net/outpost.goauthentik.io/start...` to `return 302 /outpost.goauthentik.io/start...`
|
|
|
|
2. **Application not added to outpost**
|
|
- Fix: Go to Authentik → Outposts → Edit standalone outpost → Add application
|
|
|
|
3. **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**:
|
|
|
|
1. **Undefined variable `$connection_upgrade`**
|
|
- Fix: Remove WebSocket lines (`proxy_http_version`, `Upgrade`, `Connection` headers) from advanced config. NPM handles WebSockets via the "Websockets Support" toggle.
|
|
|
|
2. **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**:
|
|
|
|
1. **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
|
|
|
|
2. **Container not on correct network**
|
|
- Fix: Ensure container is on `docker-dataplane` network
|
|
|
|
3. **Outpost not running**
|
|
- Check: `docker ps | grep authentik-proxy`
|
|
- Check logs: `docker logs authentik-proxy`
|
|
|
|
### SSL Certificate Not Provisioning
|
|
|
|
**Symptom**: Certificate request fails
|
|
|
|
**Causes & Fixes**:
|
|
|
|
1. **DNS not propagated**
|
|
- Fix: Wait for DNS propagation, verify with `dig <subdomain>.schweitz.net`
|
|
|
|
2. **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**:
|
|
|
|
1. **Auth domain has forward auth enabled**
|
|
- Fix: `auth.schweitz.net` must NOT have forward auth (would create loop)
|
|
|
|
2. **Cookie domain mismatch**
|
|
- Fix: Verify Authentik cookie domain is `.schweitz.net`
|
|
|
|
## 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**:
|
|
1. User requests `https://<subdomain>.schweitz.net`
|
|
2. NPM's `auth_request` directive checks with Authentik outpost
|
|
3. If not authenticated: redirect to Authentik login
|
|
4. User authenticates (Google OAuth, etc.)
|
|
5. Authentik sets session cookie for `.schweitz.net`
|
|
6. User redirected back, `auth_request` succeeds
|
|
7. NPM proxies request to target service
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-13
|
|
**Based on**: library.schweitz.net setup session
|