- 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.
433 lines
14 KiB
Markdown
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\"'"
|
|
```
|
|
|