Files
portainer-core/setup-new-host.md
T
jpmschweitzerandClaude Opus 4.5 9b2b32323c docs: add setup guide for SSL + Authentik protected hosts
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>
2025-12-14 12:06:05 +01:00

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