Files
rick-infra/docs/authentik-deployment-guide.md
Joakim e8b76c6a72 Update authentication documentation to reflect OAuth/OIDC as primary method
- Update architecture-decisions.md: Change decision to OAuth/OIDC primary, forward auth fallback
  - Add comprehensive OAuth/OIDC and forward auth flow diagrams
  - Add decision matrix comparing both authentication methods
  - Include real examples: Nextcloud/Gitea OAuth configs, whoami forward auth
  - Update rationale to emphasize OAuth/OIDC security and standards benefits

- Update authentication-architecture.md: Align with new OAuth-first approach
  - Add 'Choosing the Right Pattern' section with clear decision guidance
  - Swap pattern order: OAuth/OIDC (Pattern 1), Forward Auth (Pattern 2)
  - Update Example 1: Change Gitea from forward auth to OAuth/OIDC integration
  - Add emphasis on primary vs fallback methods throughout

- Update authentik-deployment-guide.md: Reflect OAuth/OIDC preference
  - Update overview to mention OAuth2/OIDC provider and forward auth fallback
  - Add decision guidance to service integration examples
  - Reorder examples: Nextcloud OAuth (primary), forward auth (fallback)
  - Clarify forward auth should only be used for services without OAuth support

This update ensures all authentication documentation consistently reflects the
agreed architectural decision: use OAuth/OIDC when services support it
(Nextcloud, Gitea, modern apps), and only use forward auth as a fallback for
legacy applications, static sites, or simple tools without OAuth capabilities.
2025-12-15 00:25:24 +01:00

433 lines
14 KiB
Markdown

# Authentik Deployment Guide
A comprehensive guide for deploying Authentik authentication server with native database services and Unix socket IPC in the rick-infra environment.
## Overview
This guide covers the complete deployment process for Authentik, a modern authentication and authorization server, integrated with:
- **Native PostgreSQL** - High-performance database with Unix socket IPC
- **Native Valkey** - Redis-compatible cache with Unix socket IPC
- **Podman Containers** - System-level container orchestration via systemd/Quadlet
- **Caddy Reverse Proxy** - TLS termination, OAuth2/OIDC provider, and forward authentication fallback
## Architecture Summary
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐
│ Internet │ │ Caddy Proxy │ │ Authentik (systemd) │
│ │───▶│ auth.jnss.me │───▶│ /system.slice/ │
│ HTTPS/443 │ │ TLS + Forward │ │ │
└─────────────────┘ │ Auth │ │ ┌─────────────────────┐ │
└─────────────────┘ │ │ Pod + Server/Worker │ │
│ │ User: 966:966 │ │
│ │ Groups: 961,962 │ │
│ └─────────────────────┘ │
└─────────────────────────┘
┌─────────────────────────────────┼─────────────────┐
│ Host Infrastructure │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ PostgreSQL │ │ Valkey │ │
│ │ (Native) │ │ (Redis-compatible) │ │
│ │ Unix Socket │ │ Unix Socket │ │
│ │ Group: 962 │ │ Group: 961 │ │
│ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```
## Prerequisites
### Infrastructure Requirements
Before deploying Authentik, ensure the following infrastructure services are running:
```bash
# Verify required services are active
ssh root@your-vps "systemctl is-active postgresql valkey caddy podman"
```
Expected output: All services should show `active`
### Required Infrastructure Components
1. **PostgreSQL Database**
- Native systemd service with Unix socket enabled
- Socket location: `/var/run/postgresql/.s.PGSQL.5432`
2. **Valkey Cache Service**
- Native systemd service with Unix socket enabled
- Socket location: `/var/run/valkey/valkey.sock`
3. **Podman Container Runtime**
- Container runtime installed
- systemd integration (Quadlet) configured
4. **Caddy Web Server**
- TLS/SSL termination configured
- API management enabled for dynamic configuration
### DNS Configuration
Ensure DNS records are configured for your authentik domain:
```bash
# Verify DNS resolution
dig +short auth.jnss.me
# Should return your VPS IP address
```
### Network Requirements
- **Port 80/443**: Open for HTTP/HTTPS traffic
- **Internal communications**: Unix sockets (no additional ports required)
## Vault Variables Setup
### Required Vault Variables
Create or update `host_vars/arch-vps/vault.yml` with the following encrypted variables:
```yaml
---
# Authentik Database Password
vault_authentik_db_password: "secure_random_password_32_chars"
# Authentik Secret Key (generate with: openssl rand -base64 32)
vault_authentik_secret_key: "your_generated_secret_key_here"
# Authentik Admin Password
vault_authentik_admin_password: "secure_admin_password"
# Infrastructure Dependencies (should already exist)
vault_valkey_password: "valkey_password"
```
### Generate Required Secrets
```bash
# Generate Authentik secret key
openssl rand -base64 32
# Generate secure passwords
openssl rand -base64 20
```
### Encrypt Vault File
```bash
# Encrypt the vault file
ansible-vault encrypt host_vars/arch-vps/vault.yml
# Verify vault variables
ansible-vault view host_vars/arch-vps/vault.yml
```
## Pre-deployment Validation
### Infrastructure Health Check
Run the following commands to verify infrastructure readiness:
```bash
# 1. Check PostgreSQL Unix socket
ssh root@your-vps "ls -la /var/run/postgresql/"
# Should show .s.PGSQL.5432 socket file
# 2. Check Valkey Unix socket
ssh root@your-vps "ls -la /var/run/valkey/"
# Should show valkey.sock file
# 3. Test PostgreSQL connectivity
ssh root@your-vps "sudo -u postgres psql -h /var/run/postgresql -c 'SELECT version();'"
# Should return PostgreSQL version
# 4. Test Valkey connectivity
ssh root@your-vps "redis-cli -s /var/run/valkey/valkey.sock ping"
# Should return "PONG"
# 5. Verify Caddy is responsive
curl -I https://jnss.me/
# Should return HTTP/2 200
```
### Ansible Configuration Validation
```bash
# Test Ansible connectivity
ansible arch-vps -m ping
# Verify vault variables can be decrypted
ansible arch-vps -m debug -a "var=vault_authentik_secret_key" --ask-vault-pass
```
## Step-by-Step Deployment
### Step 1: Enable Authentik Role
Update `site.yml` to include the authentik role:
```yaml
- name: Deploy Core Infrastructure
hosts: arch-vps
become: true
gather_facts: true
roles:
# Infrastructure dependencies handled automatically via meta/main.yml
- role: authentik
tags: ['authentik', 'auth', 'sso']
```
### Step 2: Execute Deployment
```bash
# Full deployment with verbose output
ansible-playbook -i inventory/hosts.yml site.yml --tags authentik --ask-vault-pass -v
# Alternative: Deploy with specific components
ansible-playbook -i inventory/hosts.yml site.yml --tags authentik,database,containers --ask-vault-pass
```
### Step 3: Monitor Deployment Progress
During deployment, monitor the following:
```bash
# Monitor deployment logs in real-time (separate terminal)
ssh root@your-vps "journalctl -f"
# Watch for authentik-specific services
ssh root@your-vps "systemctl --user -M authentik@ status"
```
### Step 4: Verify Container Deployment
After deployment completion:
```bash
# Check systemd services (system scope)
ssh root@your-vps "systemctl list-units 'authentik*'"
# Verify service location
ssh root@your-vps "systemctl status authentik-server | grep CGroup"
# Expected: /system.slice/authentik-server.service
# Verify containers are running
ssh root@your-vps "podman ps"
# Check pod status
ssh root@your-vps "podman pod ps"
```
### Step 5: Health Check Verification
```bash
# Test internal HTTP endpoint
ssh root@your-vps "curl -I http://127.0.0.1:9000/"
# Expected: HTTP/1.1 302 Found (redirect to login)
# Test external HTTPS endpoint
curl -I https://auth.jnss.me/
# Expected: HTTP/2 200 or 302
# Test authentik API endpoint
curl -s https://auth.jnss.me/api/v3/admin/version/
# Expected: JSON response with authentication error (proves API is responsive)
```
## Post-deployment Configuration
### Initial Admin Access
1. **Access Web Interface**:
```bash
# Open in browser
https://auth.jnss.me/
```
2. **Admin Login**:
- **Username**: `admin@auth.jnss.me` (or configured admin email)
- **Password**: Value from `vault_authentik_admin_password`
3. **Verify Admin Access**:
- Navigate to `/if/admin/`
- Confirm admin interface loads successfully
- Check system status in admin dashboard
### Essential Configuration Tasks
#### 1. Configure OAuth2 Provider
```bash
# Navigate to Applications → Providers → Create
# Provider Type: OAuth2/OpenID Provider
# Name: "Default OAuth2 Provider"
# Client Type: Confidential
# Authorization Grant Type: Authorization Code
# Redirect URIs: Add your application callback URLs
```
#### 2. Create Application
```bash
# Navigate to Applications → Applications → Create
# Name: "Your Application Name"
# Slug: "your-app"
# Provider: Select OAuth2 provider created above
# Launch URL: Your application URL
```
#### 3. Configure Forward Auth (for services without OAuth support)
**Note**: Only use Forward Auth for services that don't support OAuth2/OIDC integration. For services like Nextcloud, Gitea, or Grafana, use OAuth2 providers (see step 1 above) instead.
```bash
# Navigate to Applications → Providers → Create
# Provider Type: Proxy Provider
# Name: "Forward Auth Provider"
# External Host: https://your-service.jnss.me
# Internal Host: http://localhost:8080 (your service backend)
# Use this only for: static sites, legacy apps, simple tools without OAuth support
```
## Service Integration Examples
### Choosing the Right Integration Method
**Primary Method - OAuth2/OIDC** (Use when service supports it):
- ✅ **Nextcloud**: Native OIDC support
- ✅ **Gitea**: Native OAuth2 support
- ✅ **Grafana**: Native OAuth2 support
- ✅ **Custom applications**: Applications with OAuth2 client libraries
**Fallback Method - Forward Auth** (Use when service doesn't support OAuth):
- ⚠️ **Static sites**: No authentication capabilities
- ⚠️ **Legacy applications**: Cannot be modified
- ⚠️ **Simple tools**: whoami, monitoring dashboards without auth
---
### Example 1: OAuth2/OIDC Integration (Nextcloud)
**Recommended for services with native OAuth support**
For applications that can handle OAuth2/OIDC directly (like Nextcloud, Gitea):
```yaml
# Nextcloud OIDC configuration (config.php)
'oidc_login_provider_url' => 'https://auth.jnss.me/application/o/nextcloud/',
'oidc_login_client_id' => 'nextcloud-client-id',
'oidc_login_client_secret' => 'your_client_secret',
'oidc_login_auto_redirect' => true,
'oidc_login_end_session_redirect' => true,
'oidc_login_button_text' => 'Login with SSO',
'oidc_login_hide_password_form' => true,
'oidc_login_use_id_token' => true,
'oidc_login_attributes' => [
'id' => 'preferred_username',
'name' => 'name',
'mail' => 'email',
'groups' => 'groups',
],
'oidc_login_default_group' => 'users',
'oidc_login_scope' => 'openid profile email groups',
'oidc_login_tls_verify' => true,
```
**Caddy configuration** (no forward auth needed):
```caddyfile
# In /etc/caddy/sites-enabled/nextcloud.caddy
cloud.jnss.me {
reverse_proxy localhost:8080
}
```
---
### Example 2: Forward Auth for Services Without OAuth Support
**Use only when OAuth2/OIDC is not available**
Add to your service's Caddy configuration:
```caddyfile
# In /etc/caddy/sites-enabled/whoami.caddy
whoami.jnss.me {
# Forward authentication to authentik
forward_auth https://auth.jnss.me {
uri /outpost.goauthentik.io/auth/caddy
copy_headers Remote-User Remote-Name Remote-Email Remote-Groups
}
# Your service backend
reverse_proxy localhost:8080
}
```
### Log Analysis
#### Key Log Locations
Authentik uses **journald** for centralized logging. Both `journalctl` and `podman logs` provide access to the same log stream:
```bash
# View Authentik logs via journalctl (system-wide logging)
ssh root@your-vps "journalctl -u authentik-server -f"
ssh root@your-vps "journalctl -u authentik-worker -f"
# View Authentik logs via podman (container-specific)
ssh root@your-vps "podman logs -f authentik-server"
ssh root@your-vps "podman logs -f authentik-worker"
# View recent logs with timestamp (last 50 lines)
ssh root@your-vps "journalctl -u authentik-server --lines 50 --no-pager"
# Filter logs by time
ssh root@your-vps "journalctl -u authentik-server --since '10 minutes ago'"
ssh root@your-vps "journalctl -u authentik-server --since '2025-12-14 16:00:00'"
# Search logs for specific patterns
ssh root@your-vps "journalctl -u authentik-server | grep ERROR"
ssh root@your-vps "journalctl -u authentik-worker | grep 'database connection'"
# Caddy logs for reverse proxy issues
ssh root@your-vps "journalctl -u caddy -f"
```
**Note**: Logs are in JSON format with structured fields (timestamp, level, logger, event, etc.).
#### Common Log Patterns
Authentik logs are in **JSON format** for structured analysis. Here are common patterns:
**Successful API request**:
```json
{"auth_via": "secret_key", "domain_url": "0.0.0.0", "event": "/api/v3/outposts/proxy/",
"level": "info", "logger": "authentik.asgi", "method": "GET", "status": 200,
"timestamp": "2025-12-14T16:13:17.269312"}
```
**Startup and initialization**:
```json
{"event": "updating brand certificates", "level": "info",
"logger": "authentik.router.brand_tls", "timestamp": "2025-12-14T16:13:17Z"}
```
**Warning patterns**:
```json
{"event": "No providers assigned to this outpost, check outpost configuration",
"level": "warning", "logger": "authentik.outpost.proxyv2"}
```
**Filtering JSON logs by level**:
```bash
# Filter by error level
ssh root@your-vps "journalctl -u authentik-server --since today | grep '\"level\":\"error\"'"
# Filter by specific event
ssh root@your-vps "journalctl -u authentik-server | grep '\"event\":\"database connection\"'"
```