Files
rick-infra/roles/authentik
Joakim b42ee2a22b Fix: Complete authentik Quadlet implementation with networking solution
Resolves authentik deployment issues by implementing proper Podman Quadlet
configuration and fixing networking for external access through Caddy.

Core Fixes:
• Add missing [Install] sections to container Quadlet files for systemd service generation
• Fix pod references from 'systemd-authentik' to 'authentik.pod' for proper Quadlet linking
• Remove problematic --userns=host to use proper rootless user namespaces
• Configure subuid/subgid ranges for authentik user (200000:65536)
• Update networking to bind 0.0.0.0:9000 only (remove unnecessary HTTPS port 9443)
• Add AUTHENTIK_LISTEN__HTTP=0.0.0.0:9000 environment configuration
• Fix Caddy reverse proxy to use HTTP backend instead of HTTPS

Infrastructure Updates:
• Enhance PostgreSQL role with Unix socket configuration and user management
• Improve Valkey role with proper systemd integration and socket permissions
• Add comprehensive service integration documentation
• Update deployment playbooks with backup and restore capabilities

Security Improvements:
• Secure network isolation with Caddy SSL termination
• Reduced attack surface by removing direct HTTPS container exposure
• Proper rootless container configuration with user namespace mapping

Result: authentik now fully operational with external HTTPS access via auth.jnss.me
All systemd services (authentik-pod, authentik-server, authentik-worker) running correctly.
2025-12-04 19:42:31 +01:00
..

Authentik Role

Self-contained Authentik authentication server deployment using Podman and Unix sockets.

Overview

This role deploys Authentik as a containerized authentication service with:

  • Unix socket IPC for PostgreSQL and Valkey
  • Rootless Podman with systemd integration via Quadlet
  • Self-contained permissions management
  • Caddy reverse proxy configuration

Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Caddy Proxy   │    │  Authentik Pod  │    │  Infrastructure │
│                 │    │                 │    │                 │
│ auth.jnss.me    │───▶│ ┌─────────────┐ │    │ PostgreSQL      │
│ :443            │    │ │   Server    │ │◄──▶│ (Unix Socket)   │
│                 │    │ │   :9443     │ │    │                 │
│                 │    │ └─────────────┘ │    │ Valkey          │
│                 │    │ ┌─────────────┐ │◄──▶│ (Unix Socket)   │
│                 │    │ │   Worker    │ │    │                 │
│                 │    │ └─────────────┘ │    │                 │
└─────────────────┘    └─────────────────┘    └─────────────────┘

Dependencies

  • postgresql role (provides Unix socket infrastructure)
  • valkey role (provides Unix socket infrastructure)
  • podman role (provides container runtime)
  • caddy role (provides reverse proxy infrastructure)

Configuration

Required Variables

# Domain configuration
authentik_domain: "auth.jnss.me"

# Database credentials
authentik_db_password: "{{ vault_authentik_db_password }}"
authentik_secret_key: "{{ vault_authentik_secret_key }}"
authentik_default_admin_password: "{{ vault_authentik_admin_password }}"

# Infrastructure socket enablement
postgresql_unix_socket_enabled: true
valkey_unix_socket_enabled: true

Optional Variables

# Service configuration
authentik_service_enabled: true
authentik_service_state: "started"

# Container version
authentik_version: "latest"

# Email configuration
authentik_email_enabled: false
authentik_email_host: "smtp.example.com"

Vault Variables Required

# Database password
vault_authentik_db_password: "secure_db_password"

# Authentik secret key (generate with: openssl rand -base64 32)
vault_authentik_secret_key: "long_random_secret_key"

# Admin user password
vault_authentik_admin_password: "secure_admin_password"

# Existing infrastructure passwords
vault_valkey_password: "valkey_password"

Usage

Basic Deployment

- hosts: auth_servers
  roles:
    - postgresql
    - valkey
    - podman
    - caddy
    - authentik

With Tags

# Deploy only database setup
ansible-playbook site.yml -t database

# Deploy only containers
ansible-playbook site.yml -t containers

# Deploy only Caddy config
ansible-playbook site.yml -t caddy

File Structure

authentik/
├── defaults/main.yml          # Default variables
├── handlers/main.yml         # Service handlers
├── meta/main.yml            # Role dependencies
├── tasks/
│   ├── main.yml            # Main orchestration
│   ├── database.yml        # Database setup
│   └── cache.yml          # Cache setup
├── templates/
│   ├── authentik.env.j2    # Environment variables
│   ├── authentik.caddy.j2  # Caddy configuration
│   ├── authentik-pod.container      # Pod Quadlet file
│   ├── authentik-server.container   # Server Quadlet file
│   └── authentik-worker.container   # Worker Quadlet file
└── README.md

Systemd Services

The role creates the following systemd services:

  • authentik-pod.service - Main pod container
  • authentik-server.service - Web server container
  • authentik-worker.service - Background worker container

Networking

  • External: HTTPS via Caddy on port 443
  • Internal: Containers bind to 127.0.0.1:9000 (HTTP) and 127.0.0.1:9443 (HTTPS)
  • Database: Unix socket at /var/run/postgresql/.s.PGSQL.5432
  • Cache: Unix socket at /var/run/valkey/valkey.sock

Security Features

  • Rootless containers via Podman
  • Unix socket IPC eliminates network exposure
  • User isolation with dedicated authentik system user
  • Group-based socket access for PostgreSQL and Valkey
  • TLS termination at Caddy proxy
  • Security headers configured in Caddy

Troubleshooting

Check Service Status

systemctl status authentik-pod
systemctl status authentik-server  
systemctl status authentik-worker

Check Logs

journalctl -u authentik-server -f
journalctl -u authentik-worker -f

Check Socket Connectivity

# Test PostgreSQL socket
sudo -u authentik psql -h /var/run/postgresql -U authentik authentik

# Test Valkey socket  
sudo -u authentik redis-cli -s /var/run/valkey/valkey.sock -n 1 ping

Verify Container Status

podman --user authentik pod ps
podman --user authentik ps

Post-Deployment

  1. Access Web Interface: Navigate to https://auth.jnss.me
  2. Login: Use admin credentials from vault variables
  3. Configure Providers: Set up OAuth2/SAML providers for services
  4. Create Applications: Configure applications for SSO integration

Maintenance

Update Containers

# Update to specific version
authentik_version: "2024.2.0"

Backup Data

Important directories to backup:

  • {{ authentik_data_dir }} - Application data
  • {{ authentik_media_dir }} - Uploaded media
  • PostgreSQL database dump
  • Vault variables

Integration Examples

Protect Service with Authentik

service.example.com {
    forward_auth https://auth.jnss.me {
        uri /outpost.goauthentik.io/auth/caddy
        copy_headers Remote-User Remote-Name Remote-Email Remote-Groups
    }
    
    reverse_proxy localhost:8080
}

Technical Implementation Notes

Unix Socket Access Solution

This role implements a sophisticated solution for containerized Unix socket access:

Challenge: Containers need to access Unix sockets owned by different system services (PostgreSQL, Valkey) while maintaining security isolation.

Solution Components:

  1. User Namespace Preservation: --userns=host in pod configuration

    • Preserves host UID/GID mapping within containers
    • Allows direct access to host socket files
  2. Group Membership Preservation: Annotation=run.oci.keep_original_groups=1 in containers

    • Ensures supplementary group memberships are maintained in containers
    • Enables access to postgres and valkey groups within containers
  3. Correct Redis URL Format: AUTHENTIK_CACHE__URL=unix://...?db=N&password=...

    • Avoids Django Redis client URL parsing issues
    • Prevents incorrect port appending to Unix socket paths
  4. Host Service Integration: Authentik user added to service groups

    • Added to postgres group for PostgreSQL socket access
    • Added to valkey group for Valkey socket access

Container Architecture

┌─────────────────────────────────────────────────────────────┐
│ Authentik Pod (--userns=host)                               │
│                                                             │
│ ┌─────────────────┐  ┌─────────────────┐                   │
│ │ Server Container│  │ Worker Container│                   │
│ │ UID: 963 (host) │  │ UID: 963 (host) │                   │
│ │ Groups: 963,    │  │ Groups: 963,    │                   │
│ │   968(postgres),│  │   968(postgres),│                   │
│ │   965(valkey)   │  │   965(valkey)   │                   │
│ └─────────────────┘  └─────────────────┘                   │
│           │                    │                           │
│           └────────────────────┴─────────────┐             │
└─────────────────────────────────────────────│─────────────┘
                                              │
                              ┌───────────────▼──────────────┐
                              │ Host Unix Sockets            │
                              │                              │
                              │ /var/run/postgresql/         │
                              │ ├─ .s.PGSQL.5432             │
                              │ │  (postgres:postgres 0770)  │
                              │                              │
                              │ /var/run/valkey/             │
                              │ ├─ valkey.sock               │
                              │    (valkey:valkey 0770)      │
                              └──────────────────────────────┘

Security Implications

Maintained Security:

  • Container network isolation preserved (no --network=host)
  • Individual container user/group isolation
  • Standard Podman security features active
  • Principle of least privilege through group membership

Trade-offs:

  • Containers share host user namespace (reduced UID isolation)
  • Group membership grants broader access to service files
  • Requires careful service group management

Compatibility

This solution is:

  • Portable: Works regardless of UID assignments
  • Maintainable: No custom subuid/subgid configuration
  • Performant: Unix sockets avoid TCP overhead
  • Secure: Maintains container isolation where it matters
  • Standard: Uses documented Podman/OCI features