Add Authentik SSO service and refactor Valkey configuration to use native tools and consolidated systemd service
This commit is contained in:
119
roles/authentik/README.md
Normal file
119
roles/authentik/README.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# Authentik Authentication Service Role
|
||||||
|
|
||||||
|
Containerized Authentik authentication service for rick-infra using Podman quadlets and following established architectural patterns.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ✅ **Containerized deployment**: Uses Podman with systemd quadlets
|
||||||
|
- ✅ **Self-contained**: Manages its own database and configuration
|
||||||
|
- ✅ **Service-specific user**: Runs as dedicated `authentik` user with subuid/subgid
|
||||||
|
- ✅ **Infrastructure integration**: PostgreSQL database, Valkey cache, Caddy proxy
|
||||||
|
- ✅ **Bridge networking**: Container-to-host communication via host.containers.internal
|
||||||
|
- ✅ **Security hardened**: Rootless containers with proper isolation
|
||||||
|
- ✅ **Production ready**: HTTPS, proper health checks, restart policies
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **Dependencies**: PostgreSQL, Valkey, Podman, Caddy infrastructure roles
|
||||||
|
- **Database**: Self-managed authentik database and user in PostgreSQL
|
||||||
|
- **Cache**: Uses Valkey database 1 for session/cache storage
|
||||||
|
- **Containers**: 2-container pod (server + worker) deployed via quadlets
|
||||||
|
- **Network**: Custom bridge network with host gateway access
|
||||||
|
- **Web access**: https://auth.domain.com (via Caddy reverse proxy)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Key variables (defaults in `defaults/main.yml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Service
|
||||||
|
authentik_service_enabled: true
|
||||||
|
authentik_http_port: 9000
|
||||||
|
authentik_https_port: 9443
|
||||||
|
|
||||||
|
# Domain
|
||||||
|
authentik_subdomain: "auth"
|
||||||
|
authentik_domain: "{{ caddy_domain }}"
|
||||||
|
|
||||||
|
# Container
|
||||||
|
authentik_image_server: "ghcr.io/goauthentik/server"
|
||||||
|
authentik_image_tag: "2024.8.3"
|
||||||
|
authentik_user: "authentik"
|
||||||
|
|
||||||
|
# Database (self-managed)
|
||||||
|
authentik_db_name: "authentik"
|
||||||
|
authentik_db_user: "authentik"
|
||||||
|
authentik_db_password: "{{ vault_authentik_db_password }}"
|
||||||
|
|
||||||
|
# Cache (Valkey)
|
||||||
|
authentik_redis_host: "host.containers.internal"
|
||||||
|
authentik_redis_db: 1
|
||||||
|
|
||||||
|
# Security
|
||||||
|
authentik_secret_key: "{{ vault_authentik_secret_key }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Container Architecture
|
||||||
|
|
||||||
|
### Pod Structure
|
||||||
|
```
|
||||||
|
authentik-pod
|
||||||
|
├── authentik-server (web interface, API)
|
||||||
|
└── authentik-worker (background tasks)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
- **Bridge network**: `authentik-net` with DNS resolution
|
||||||
|
- **Host gateway**: `host.containers.internal` → host system
|
||||||
|
- **Port mapping**: 9000:9000 (HTTP), 9443:9443 (HTTPS)
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
- **Config**: `~authentik/.config/containers/` (quadlets, env)
|
||||||
|
- **Data**: `~authentik/data/` (persistent application data)
|
||||||
|
- **Media**: `~authentik/media/` (uploaded files)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. **Add vault secrets**: Set required vault variables in host_vars:
|
||||||
|
```yaml
|
||||||
|
vault_authentik_db_password: "secure_db_password"
|
||||||
|
vault_authentik_secret_key: "long_random_secret_key"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy**: `ansible-playbook site.yml --tags authentik`
|
||||||
|
|
||||||
|
3. **Access**: Visit https://auth.yourdomain.com/if/flow/initial-setup/
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- PostgreSQL infrastructure role (database)
|
||||||
|
- Valkey infrastructure role (cache)
|
||||||
|
- Podman infrastructure role (containers)
|
||||||
|
- Caddy web server (HTTPS reverse proxy)
|
||||||
|
- Vault secrets: `vault_authentik_db_password`, `vault_authentik_secret_key`
|
||||||
|
|
||||||
|
## Containerized Service Pattern
|
||||||
|
|
||||||
|
This role establishes rick-infra's containerized service pattern:
|
||||||
|
|
||||||
|
### User Management
|
||||||
|
- Service-specific user (`authentik`) with dedicated home directory
|
||||||
|
- Subuid/subgid ranges (100000-165535) for rootless containers
|
||||||
|
- Systemd user session with lingering enabled
|
||||||
|
|
||||||
|
### Container Integration
|
||||||
|
- Podman quadlets for native systemd integration
|
||||||
|
- Custom bridge networks with host gateway access
|
||||||
|
- Container-to-host connectivity via `host.containers.internal`
|
||||||
|
- Persistent storage mounted from user home directory
|
||||||
|
|
||||||
|
### Infrastructure Integration
|
||||||
|
- Self-managed database creation via PostgreSQL role
|
||||||
|
- Cache integration with Valkey infrastructure
|
||||||
|
- Reverse proxy deployment via Caddy sites-enabled
|
||||||
|
- Follows rick-infra self-contained service patterns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Rick-Infra Authentik Service**
|
||||||
|
SSO authentication and authorization platform for modern applications.
|
||||||
107
roles/authentik/defaults/main.yml
Normal file
107
roles/authentik/defaults/main.yml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
# =================================================================
|
||||||
|
# Authentik Authentication Service Role - Container Configuration
|
||||||
|
# =================================================================
|
||||||
|
# Containerized Authentik deployment using Podman quadlets
|
||||||
|
# Follows rick-infra patterns for pragmatic service deployment
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Service Configuration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Service Management
|
||||||
|
authentik_service_enabled: true
|
||||||
|
authentik_service_state: "started"
|
||||||
|
|
||||||
|
# User and Container Configuration
|
||||||
|
authentik_user: "authentik"
|
||||||
|
authentik_group: "authentik"
|
||||||
|
authentik_home: "/var/lib/authentik"
|
||||||
|
authentik_subuid_start: 100000
|
||||||
|
authentik_subgid_start: 100000
|
||||||
|
authentik_subuid_size: 65536
|
||||||
|
authentik_subgid_size: 65536
|
||||||
|
|
||||||
|
# Container Configuration
|
||||||
|
authentik_image_server: "ghcr.io/goauthentik/server"
|
||||||
|
authentik_image_tag: "2024.8.3"
|
||||||
|
authentik_pod_name: "authentik"
|
||||||
|
authentik_network_name: "authentik-net"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Domain and Caddy Integration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Domain setup (follows rick-infra pattern)
|
||||||
|
authentik_subdomain: "auth"
|
||||||
|
authentik_domain: "{{ caddy_domain | default('localhost') }}"
|
||||||
|
authentik_full_domain: "{{ authentik_subdomain }}.{{ authentik_domain }}"
|
||||||
|
|
||||||
|
# Caddy integration
|
||||||
|
caddy_sites_enabled_dir: "/etc/caddy/sites-enabled"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Database Configuration (Self-Contained)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Authentik manages its own database
|
||||||
|
authentik_db_engine: "postgresql"
|
||||||
|
authentik_db_host: "host.containers.internal"
|
||||||
|
authentik_db_port: 5432
|
||||||
|
authentik_db_name: "authentik"
|
||||||
|
authentik_db_user: "authentik"
|
||||||
|
authentik_db_password: "{{ vault_authentik_db_password }}"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Cache Configuration (Valkey/Redis)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Valkey/Redis cache configuration
|
||||||
|
authentik_redis_host: "host.containers.internal"
|
||||||
|
authentik_redis_port: 6379
|
||||||
|
authentik_redis_db: 1
|
||||||
|
authentik_redis_password: "" # Valkey has no auth by default
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Application Settings
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Authentik core configuration
|
||||||
|
authentik_secret_key: "{{ vault_authentik_secret_key }}"
|
||||||
|
authentik_error_reporting_enabled: false
|
||||||
|
authentik_disable_update_check: true
|
||||||
|
authentik_disable_startup_analytics: true
|
||||||
|
|
||||||
|
# Email configuration (disabled by default)
|
||||||
|
authentik_email_host: ""
|
||||||
|
authentik_email_port: 587
|
||||||
|
authentik_email_username: ""
|
||||||
|
authentik_email_password: ""
|
||||||
|
authentik_email_use_tls: true
|
||||||
|
authentik_email_from: "authentik@{{ authentik_domain }}"
|
||||||
|
|
||||||
|
# Worker configuration
|
||||||
|
authentik_worker_concurrency: 2
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Container Networking
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Port mappings
|
||||||
|
authentik_http_port: 9000
|
||||||
|
authentik_https_port: 9443
|
||||||
|
|
||||||
|
# Network configuration
|
||||||
|
authentik_bridge_network: true
|
||||||
|
authentik_enable_host_gateway: true
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Rick-Infra Integration Notes
|
||||||
|
# =================================================================
|
||||||
|
# This role:
|
||||||
|
# - Depends on PostgreSQL, Valkey, Podman, and Caddy infrastructure roles
|
||||||
|
# - Creates its own database and user in PostgreSQL
|
||||||
|
# - Uses Valkey database 1 for caching
|
||||||
|
# - Deploys Caddy configuration to sites-enabled
|
||||||
|
# - Uses Podman quadlets for systemd integration
|
||||||
|
# - Follows containerized service pattern with service-specific user
|
||||||
28
roles/authentik/handlers/main.yml
Normal file
28
roles/authentik/handlers/main.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# Authentik Role Handlers
|
||||||
|
|
||||||
|
- name: reload systemd
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: reload user systemd for authentik
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
scope: user
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
|
||||||
|
- name: restart authentik pod
|
||||||
|
systemd:
|
||||||
|
name: "{{ authentik_pod_name }}"
|
||||||
|
state: restarted
|
||||||
|
scope: user
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
when: authentik_service_state == "started"
|
||||||
|
|
||||||
|
- name: reload caddy
|
||||||
|
systemd:
|
||||||
|
name: caddy
|
||||||
|
state: reloaded
|
||||||
|
when: caddy_service_enabled | default(false)
|
||||||
37
roles/authentik/meta/main.yml
Normal file
37
roles/authentik/meta/main.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: Rick's Infrastructure Team
|
||||||
|
description: Containerized Authentik authentication service for rick-infra
|
||||||
|
company: Personal Infrastructure
|
||||||
|
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
min_ansible_version: "2.9"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: ArchLinux
|
||||||
|
versions:
|
||||||
|
- all
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- authentication
|
||||||
|
- authentik
|
||||||
|
- containers
|
||||||
|
- podman
|
||||||
|
- archlinux
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- role: postgresql
|
||||||
|
tags: ['postgresql', 'infrastructure']
|
||||||
|
- role: valkey
|
||||||
|
tags: ['valkey', 'infrastructure']
|
||||||
|
- role: podman
|
||||||
|
tags: ['podman', 'infrastructure']
|
||||||
|
- role: caddy
|
||||||
|
tags: ['caddy']
|
||||||
|
|
||||||
|
# Containerized Authentik authentication service
|
||||||
|
# - Creates its own database using PostgreSQL infrastructure
|
||||||
|
# - Uses Valkey for caching (database 1)
|
||||||
|
# - Deployed via Podman quadlets with service-specific user
|
||||||
|
# - Integrated with Caddy reverse proxy
|
||||||
69
roles/authentik/tasks/containers.yml
Normal file
69
roles/authentik/tasks/containers.yml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
# Authentik Container Deployment - Podman Quadlets
|
||||||
|
|
||||||
|
- name: Deploy authentik environment file
|
||||||
|
template:
|
||||||
|
src: authentik.env.j2
|
||||||
|
dest: "{{ authentik_home }}/.config/containers/authentik.env"
|
||||||
|
owner: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
mode: '0600'
|
||||||
|
notify: restart authentik pod
|
||||||
|
|
||||||
|
- name: Deploy authentik pod quadlet
|
||||||
|
template:
|
||||||
|
src: authentik.pod.j2
|
||||||
|
dest: "{{ authentik_home }}/.config/containers/systemd/{{ authentik_pod_name }}.pod"
|
||||||
|
owner: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- reload user systemd for authentik
|
||||||
|
- restart authentik pod
|
||||||
|
|
||||||
|
- name: Deploy authentik server container quadlet
|
||||||
|
template:
|
||||||
|
src: authentik-server.container.j2
|
||||||
|
dest: "{{ authentik_home }}/.config/containers/systemd/authentik-server.container"
|
||||||
|
owner: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- reload user systemd for authentik
|
||||||
|
- restart authentik pod
|
||||||
|
|
||||||
|
- name: Deploy authentik worker container quadlet
|
||||||
|
template:
|
||||||
|
src: authentik-worker.container.j2
|
||||||
|
dest: "{{ authentik_home }}/.config/containers/systemd/authentik-worker.container"
|
||||||
|
owner: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- reload user systemd for authentik
|
||||||
|
- restart authentik pod
|
||||||
|
|
||||||
|
- name: Reload user systemd to recognize quadlets
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
scope: user
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
|
||||||
|
- name: Enable and start authentik pod
|
||||||
|
systemd:
|
||||||
|
name: "{{ authentik_pod_name }}-pod"
|
||||||
|
enabled: "{{ authentik_service_enabled }}"
|
||||||
|
state: "{{ authentik_service_state }}"
|
||||||
|
scope: user
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
|
||||||
|
- name: Wait for Authentik to be ready
|
||||||
|
uri:
|
||||||
|
url: "http://127.0.0.1:{{ authentik_http_port }}/if/flow/initial-setup/"
|
||||||
|
method: GET
|
||||||
|
status_code: [200, 302]
|
||||||
|
retries: 30
|
||||||
|
delay: 2
|
||||||
|
when: authentik_service_state == "started"
|
||||||
28
roles/authentik/tasks/database.yml
Normal file
28
roles/authentik/tasks/database.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# Authentik Database Management - Self-Contained Database Setup
|
||||||
|
|
||||||
|
- name: Create Authentik database user
|
||||||
|
postgresql_user:
|
||||||
|
name: "{{ authentik_db_user }}"
|
||||||
|
password: "{{ authentik_db_password }}"
|
||||||
|
encrypted: yes
|
||||||
|
become: yes
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
- name: Create Authentik database
|
||||||
|
postgresql_db:
|
||||||
|
name: "{{ authentik_db_name }}"
|
||||||
|
owner: "{{ authentik_db_user }}"
|
||||||
|
encoding: UTF8
|
||||||
|
template: template0
|
||||||
|
become: yes
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
- name: Grant all privileges on Authentik database to user
|
||||||
|
postgresql_privs:
|
||||||
|
db: "{{ authentik_db_name }}"
|
||||||
|
privs: ALL
|
||||||
|
type: database
|
||||||
|
role: "{{ authentik_db_user }}"
|
||||||
|
become: yes
|
||||||
|
become_user: postgres
|
||||||
36
roles/authentik/tasks/main.yml
Normal file
36
roles/authentik/tasks/main.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
# Authentik Authentication Service Role - Containerized Implementation
|
||||||
|
# Manages Authentik using Podman with self-contained database
|
||||||
|
|
||||||
|
- name: Create authentik user and configure subuid/subgid
|
||||||
|
include_tasks: user.yml
|
||||||
|
|
||||||
|
- name: Set up authentik database
|
||||||
|
include_tasks: database.yml
|
||||||
|
|
||||||
|
- name: Configure container networking
|
||||||
|
include_tasks: networking.yml
|
||||||
|
|
||||||
|
- name: Deploy authentik containers via quadlets
|
||||||
|
include_tasks: containers.yml
|
||||||
|
|
||||||
|
- name: Deploy Caddy configuration for Authentik
|
||||||
|
template:
|
||||||
|
src: authentik.caddy.j2
|
||||||
|
dest: "{{ caddy_sites_enabled_dir }}/authentik.caddy"
|
||||||
|
mode: '0644'
|
||||||
|
notify: reload caddy
|
||||||
|
when: caddy_sites_enabled_dir is defined
|
||||||
|
|
||||||
|
- name: Display Authentik service status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
✅ Authentik authentication service deployed successfully!
|
||||||
|
|
||||||
|
🌐 Web Interface: https://{{ authentik_full_domain }}
|
||||||
|
🔐 Admin Interface: https://{{ authentik_full_domain }}/if/admin/
|
||||||
|
📦 Local HTTP: http://127.0.0.1:{{ authentik_http_port }}
|
||||||
|
🗄️ Database: {{ authentik_db_name }} (self-managed)
|
||||||
|
🚀 Cache: Valkey database {{ authentik_redis_db }}
|
||||||
|
|
||||||
|
🏗️ Authentication service ready for SSO integration!
|
||||||
23
roles/authentik/tasks/networking.yml
Normal file
23
roles/authentik/tasks/networking.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
# Authentik Container Networking - Bridge Network Setup
|
||||||
|
|
||||||
|
- name: Create authentik bridge network
|
||||||
|
containers.podman.podman_network:
|
||||||
|
name: "{{ authentik_network_name }}"
|
||||||
|
driver: bridge
|
||||||
|
internal: false
|
||||||
|
state: present
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
|
||||||
|
- name: Check if authentik network exists
|
||||||
|
command: podman network ls --format json
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
|
register: network_list
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Ensure host gateway is available in network
|
||||||
|
debug:
|
||||||
|
msg: "Network {{ authentik_network_name }} configured for host.containers.internal access"
|
||||||
|
when: authentik_enable_host_gateway | default(true)
|
||||||
60
roles/authentik/tasks/user.yml
Normal file
60
roles/authentik/tasks/user.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
# Authentik User Management - Service-Specific User Setup
|
||||||
|
|
||||||
|
- name: Create authentik group
|
||||||
|
group:
|
||||||
|
name: "{{ authentik_group }}"
|
||||||
|
system: yes
|
||||||
|
|
||||||
|
- name: Create authentik user
|
||||||
|
user:
|
||||||
|
name: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
system: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
home: "{{ authentik_home }}"
|
||||||
|
create_home: yes
|
||||||
|
comment: "Authentik authentication service"
|
||||||
|
|
||||||
|
- name: Set up subuid for authentik user
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/subuid
|
||||||
|
line: "{{ authentik_user }}:{{ authentik_subuid_start }}:{{ authentik_subuid_size }}"
|
||||||
|
create: yes
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Set up subgid for authentik user
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/subgid
|
||||||
|
line: "{{ authentik_user }}:{{ authentik_subgid_start }}:{{ authentik_subgid_size }}"
|
||||||
|
create: yes
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Create authentik directories
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ authentik_user }}"
|
||||||
|
group: "{{ authentik_group }}"
|
||||||
|
mode: '0755'
|
||||||
|
loop:
|
||||||
|
- "{{ authentik_home }}"
|
||||||
|
- "{{ authentik_home }}/.config"
|
||||||
|
- "{{ authentik_home }}/.config/systemd"
|
||||||
|
- "{{ authentik_home }}/.config/systemd/user"
|
||||||
|
- "{{ authentik_home }}/.config/containers"
|
||||||
|
- "{{ authentik_home }}/.config/containers/systemd"
|
||||||
|
- "{{ authentik_home }}/data"
|
||||||
|
- "{{ authentik_home }}/media"
|
||||||
|
|
||||||
|
- name: Enable lingering for authentik user
|
||||||
|
command: loginctl enable-linger {{ authentik_user }}
|
||||||
|
args:
|
||||||
|
creates: "/var/lib/systemd/linger/{{ authentik_user }}"
|
||||||
|
|
||||||
|
- name: Initialize user systemd for authentik
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
scope: user
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ authentik_user }}"
|
||||||
37
roles/authentik/templates/authentik-server.container.j2
Normal file
37
roles/authentik/templates/authentik-server.container.j2
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Authentik Server Container Quadlet
|
||||||
|
# Generated by rick-infra Ansible role
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Authentik Server Container
|
||||||
|
Requires={{ authentik_pod_name }}-pod.service
|
||||||
|
After={{ authentik_pod_name }}-pod.service
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=authentik-server
|
||||||
|
Image={{ authentik_image_server }}:{{ authentik_image_tag }}
|
||||||
|
Pod={{ authentik_pod_name }}.pod
|
||||||
|
|
||||||
|
# Environment configuration
|
||||||
|
EnvironmentFile={{ authentik_home }}/.config/containers/authentik.env
|
||||||
|
Environment=AUTHENTIK_LISTEN__HTTP=0.0.0.0:9000
|
||||||
|
Environment=AUTHENTIK_LISTEN__HTTPS=0.0.0.0:9443
|
||||||
|
|
||||||
|
# Server command
|
||||||
|
Exec=server
|
||||||
|
|
||||||
|
# Volumes for persistent data
|
||||||
|
Volume={{ authentik_home }}/data:/data:Z
|
||||||
|
Volume={{ authentik_home }}/media:/media:Z
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HealthCmd=ak healthcheck
|
||||||
|
HealthInterval=30s
|
||||||
|
HealthTimeout=10s
|
||||||
|
HealthRetries=3
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
35
roles/authentik/templates/authentik-worker.container.j2
Normal file
35
roles/authentik/templates/authentik-worker.container.j2
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Authentik Worker Container Quadlet
|
||||||
|
# Generated by rick-infra Ansible role
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Authentik Worker Container
|
||||||
|
Requires={{ authentik_pod_name }}-pod.service authentik-server.service
|
||||||
|
After={{ authentik_pod_name }}-pod.service authentik-server.service
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=authentik-worker
|
||||||
|
Image={{ authentik_image_server }}:{{ authentik_image_tag }}
|
||||||
|
Pod={{ authentik_pod_name }}.pod
|
||||||
|
|
||||||
|
# Environment configuration
|
||||||
|
EnvironmentFile={{ authentik_home }}/.config/containers/authentik.env
|
||||||
|
|
||||||
|
# Worker command
|
||||||
|
Exec=worker
|
||||||
|
|
||||||
|
# Volumes for persistent data
|
||||||
|
Volume={{ authentik_home }}/data:/data:Z
|
||||||
|
Volume={{ authentik_home }}/media:/media:Z
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HealthCmd=ak healthcheck
|
||||||
|
HealthInterval=30s
|
||||||
|
HealthTimeout=10s
|
||||||
|
HealthRetries=3
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
34
roles/authentik/templates/authentik.caddy.j2
Normal file
34
roles/authentik/templates/authentik.caddy.j2
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Authentik Caddy Configuration - Rick-Infra
|
||||||
|
# Generated by Ansible Authentik role
|
||||||
|
# Deployed to {{ caddy_sites_enabled_dir }}/authentik.caddy
|
||||||
|
|
||||||
|
{{ authentik_full_domain }} {
|
||||||
|
# Reverse proxy to Authentik
|
||||||
|
reverse_proxy 127.0.0.1:{{ authentik_http_port }}
|
||||||
|
|
||||||
|
# Security headers for authentication service
|
||||||
|
header {
|
||||||
|
# Enable HSTS
|
||||||
|
Strict-Transport-Security max-age=31536000;
|
||||||
|
# Prevent embedding in frames
|
||||||
|
X-Frame-Options DENY
|
||||||
|
# Prevent content type sniffing
|
||||||
|
X-Content-Type-Options nosniff
|
||||||
|
# XSS protection
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
# Referrer policy for privacy
|
||||||
|
Referrer-Policy strict-origin-when-cross-origin
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log {
|
||||||
|
output file /var/log/caddy/authentik_access.log
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: Custom error pages
|
||||||
|
handle_errors {
|
||||||
|
respond "Authentication service temporarily unavailable" 503
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rick-Infra: Containerized Authentik authentication service with Caddy reverse proxy
|
||||||
39
roles/authentik/templates/authentik.env.j2
Normal file
39
roles/authentik/templates/authentik.env.j2
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Authentik Environment Configuration
|
||||||
|
# Generated by rick-infra Ansible role
|
||||||
|
|
||||||
|
# Database Configuration
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST={{ authentik_db_host }}
|
||||||
|
AUTHENTIK_POSTGRESQL__PORT={{ authentik_db_port }}
|
||||||
|
AUTHENTIK_POSTGRESQL__NAME={{ authentik_db_name }}
|
||||||
|
AUTHENTIK_POSTGRESQL__USER={{ authentik_db_user }}
|
||||||
|
AUTHENTIK_POSTGRESQL__PASSWORD={{ authentik_db_password }}
|
||||||
|
|
||||||
|
# Cache Configuration (Valkey/Redis)
|
||||||
|
AUTHENTIK_REDIS__HOST={{ authentik_redis_host }}
|
||||||
|
AUTHENTIK_REDIS__PORT={{ authentik_redis_port }}
|
||||||
|
AUTHENTIK_REDIS__DB={{ authentik_redis_db }}
|
||||||
|
{% if authentik_redis_password %}
|
||||||
|
AUTHENTIK_REDIS__PASSWORD={{ authentik_redis_password }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Core Configuration
|
||||||
|
AUTHENTIK_SECRET_KEY={{ authentik_secret_key }}
|
||||||
|
AUTHENTIK_ERROR_REPORTING__ENABLED={{ authentik_error_reporting_enabled | lower }}
|
||||||
|
AUTHENTIK_DISABLE_UPDATE_CHECK={{ authentik_disable_update_check | lower }}
|
||||||
|
AUTHENTIK_DISABLE_STARTUP_ANALYTICS={{ authentik_disable_startup_analytics | lower }}
|
||||||
|
|
||||||
|
# Worker Configuration
|
||||||
|
AUTHENTIK_WORKER__CONCURRENCY={{ authentik_worker_concurrency }}
|
||||||
|
|
||||||
|
# Email Configuration
|
||||||
|
{% if authentik_email_host %}
|
||||||
|
AUTHENTIK_EMAIL__HOST={{ authentik_email_host }}
|
||||||
|
AUTHENTIK_EMAIL__PORT={{ authentik_email_port }}
|
||||||
|
AUTHENTIK_EMAIL__USERNAME={{ authentik_email_username }}
|
||||||
|
AUTHENTIK_EMAIL__PASSWORD={{ authentik_email_password }}
|
||||||
|
AUTHENTIK_EMAIL__USE_TLS={{ authentik_email_use_tls | lower }}
|
||||||
|
AUTHENTIK_EMAIL__FROM={{ authentik_email_from }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Trust reverse proxy headers
|
||||||
|
AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS=127.0.0.1/32,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||||
21
roles/authentik/templates/authentik.pod.j2
Normal file
21
roles/authentik/templates/authentik.pod.j2
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Authentik Pod Quadlet
|
||||||
|
# Generated by rick-infra Ansible role
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Authentik Authentication Service Pod
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Pod]
|
||||||
|
PodName={{ authentik_pod_name }}
|
||||||
|
Network={{ authentik_network_name }}
|
||||||
|
{% if authentik_enable_host_gateway | default(true) %}
|
||||||
|
AddHost=host.containers.internal:host-gateway
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Published ports for web access
|
||||||
|
PublishPort={{ authentik_http_port }}:9000
|
||||||
|
PublishPort={{ authentik_https_port }}:9443
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
@@ -20,8 +20,7 @@ NoNewPrivileges=true
|
|||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectHome=true
|
ProtectHome=true
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ReadWritePaths={{ gitea_home }}
|
ReadWritePaths={{ gitea_home }} /etc/gitea
|
||||||
ReadWritePaths=/etc/gitea
|
|
||||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||||
|
|
||||||
# Process limits
|
# Process limits
|
||||||
@@ -30,4 +29,4 @@ LimitNOFILE=65536
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
# Rick-Infra: Self-contained Gitea service with security hardening
|
# Rick-Infra: Self-contained Gitea service with security hardening
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ valkey_port: 6379
|
|||||||
valkey_protected_mode: true
|
valkey_protected_mode: true
|
||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
valkey_requirepass: "{{ vault_valkey_password }}"
|
valkey_password: "{{ vault_valkey_password }}"
|
||||||
|
|
||||||
# =================================================================
|
# =================================================================
|
||||||
# Performance Settings (Conservative Defaults)
|
# Performance Settings (Conservative Defaults)
|
||||||
@@ -45,8 +45,7 @@ valkey_appendonly: false # RDB only for simplicity
|
|||||||
# Security Configuration
|
# Security Configuration
|
||||||
# =================================================================
|
# =================================================================
|
||||||
|
|
||||||
# Systemd security hardening
|
# Security hardening is now built into the custom service file
|
||||||
valkey_systemd_security: true
|
|
||||||
|
|
||||||
# Valkey security settings
|
# Valkey security settings
|
||||||
valkey_timeout: 300
|
valkey_timeout: 300
|
||||||
@@ -85,4 +84,4 @@ valkey_syslog_ident: "valkey"
|
|||||||
# - VALKEY_DB: "1" (or 2, 3, etc. - unique per application)
|
# - VALKEY_DB: "1" (or 2, 3, etc. - unique per application)
|
||||||
#
|
#
|
||||||
# Note: Applications can also use REDIS_* environment variables
|
# Note: Applications can also use REDIS_* environment variables
|
||||||
# for compatibility since Valkey is fully Redis-compatible
|
# for compatibility since Valkey is fully Redis-compatible
|
||||||
|
|||||||
@@ -38,19 +38,12 @@
|
|||||||
backup: yes
|
backup: yes
|
||||||
notify: restart valkey
|
notify: restart valkey
|
||||||
|
|
||||||
- name: Create systemd override directory for Valkey security
|
- name: Deploy custom Valkey service file
|
||||||
file:
|
|
||||||
path: /etc/systemd/system/valkey.service.d
|
|
||||||
state: directory
|
|
||||||
mode: '0755'
|
|
||||||
when: valkey_systemd_security
|
|
||||||
|
|
||||||
- name: Deploy Valkey systemd security override
|
|
||||||
template:
|
template:
|
||||||
src: systemd-override.conf.j2
|
src: valkey.service.j2
|
||||||
dest: /etc/systemd/system/valkey.service.d/override.conf
|
dest: /etc/systemd/system/valkey.service
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
when: valkey_systemd_security
|
backup: yes
|
||||||
notify:
|
notify:
|
||||||
- reload systemd
|
- reload systemd
|
||||||
- restart valkey
|
- restart valkey
|
||||||
@@ -70,7 +63,7 @@
|
|||||||
when: valkey_service_state == "started"
|
when: valkey_service_state == "started"
|
||||||
|
|
||||||
- name: Test Valkey connectivity
|
- name: Test Valkey connectivity
|
||||||
command: redis-cli -h {{ valkey_bind }} -p {{ valkey_port }} -a {{ valkey_requirepass }} ping
|
command: valkey-cli -h {{ valkey_bind }} -p {{ valkey_port }} -a "{{ valkey_password }}" ping
|
||||||
register: valkey_ping_result
|
register: valkey_ping_result
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: valkey_ping_result.stdout != "PONG"
|
failed_when: valkey_ping_result.stdout != "PONG"
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
# Redis Systemd Security Override
|
|
||||||
# Generated by rick-infra Redis role
|
|
||||||
#
|
|
||||||
# This file provides additional security hardening for the Redis service
|
|
||||||
# following the same security patterns as the PostgreSQL role.
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
# Security hardening
|
|
||||||
NoNewPrivileges=yes
|
|
||||||
PrivateTmp=yes
|
|
||||||
PrivateDevices=yes
|
|
||||||
ProtectSystem=strict
|
|
||||||
ProtectHome=yes
|
|
||||||
ProtectKernelTunables=yes
|
|
||||||
ProtectKernelModules=yes
|
|
||||||
ProtectControlGroups=yes
|
|
||||||
RestrictRealtime=yes
|
|
||||||
RestrictSUIDSGID=yes
|
|
||||||
|
|
||||||
# Network security
|
|
||||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
|
||||||
|
|
||||||
# Filesystem permissions
|
|
||||||
ReadWritePaths=/var/lib/valkey
|
|
||||||
ReadOnlyPaths=/etc/valkey
|
|
||||||
|
|
||||||
# System call filtering
|
|
||||||
SystemCallFilter=@system-service
|
|
||||||
SystemCallFilter=~@privileged @resources @obsolete
|
|
||||||
|
|
||||||
# Memory and resource limits
|
|
||||||
MemoryDenyWriteExecute=yes
|
|
||||||
LockPersonality=yes
|
|
||||||
|
|
||||||
# Capabilities
|
|
||||||
CapabilityBoundingSet=
|
|
||||||
AmbientCapabilities=
|
|
||||||
|
|
||||||
# User and group isolation
|
|
||||||
DynamicUser=no
|
|
||||||
User=valkey
|
|
||||||
Group=valkey
|
|
||||||
|
|
||||||
# Process isolation
|
|
||||||
PrivateUsers=yes
|
|
||||||
RemoveIPC=yes
|
|
||||||
|
|
||||||
# Additional Redis-specific security
|
|
||||||
UMask=0027
|
|
||||||
@@ -31,7 +31,7 @@ tcp-keepalive {{ valkey_tcp_keepalive }}
|
|||||||
# =================================================================
|
# =================================================================
|
||||||
|
|
||||||
# Require password for all operations
|
# Require password for all operations
|
||||||
requirepass {{ valkey_requirepass }}
|
requirepass {{ valkey_password }}
|
||||||
|
|
||||||
# =================================================================
|
# =================================================================
|
||||||
# Memory Management
|
# Memory Management
|
||||||
@@ -127,4 +127,4 @@ client-output-buffer-limit pubsub 32mb 8mb 60
|
|||||||
# - Database 3+: Future applications
|
# - Database 3+: Future applications
|
||||||
#
|
#
|
||||||
# Connection example:
|
# Connection example:
|
||||||
# redis-cli -h {{ valkey_bind }} -p {{ valkey_port }} -a {{ valkey_requirepass }} -n 1
|
# valkey-cli -h {{ valkey_bind }} -p {{ valkey_port }} -a {{ valkey_password }} -n 1
|
||||||
|
|||||||
78
roles/valkey/templates/valkey.service.j2
Normal file
78
roles/valkey/templates/valkey.service.j2
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Valkey Systemd Service
|
||||||
|
# Generated by rick-infra Valkey role
|
||||||
|
#
|
||||||
|
# This service provides a secure, hardened Valkey instance with proper configuration loading
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Valkey (Redis-compatible) Key-Value Store
|
||||||
|
Documentation=https://valkey.io/
|
||||||
|
After=network.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
User=valkey
|
||||||
|
Group=valkey
|
||||||
|
|
||||||
|
# Core service configuration - ensures config file is loaded
|
||||||
|
ExecStart=/usr/bin/valkey-server /etc/valkey/valkey.conf --supervised systemd
|
||||||
|
ExecReload=/bin/kill -USR2 $MAINPID
|
||||||
|
|
||||||
|
# Restart configuration
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
TimeoutStartSec=60
|
||||||
|
TimeoutStopSec=60
|
||||||
|
|
||||||
|
# Runtime directory
|
||||||
|
RuntimeDirectory=valkey
|
||||||
|
RuntimeDirectoryMode=755
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
LimitNOFILE=10032
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
PrivateDevices=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
ProtectKernelTunables=yes
|
||||||
|
ProtectKernelModules=yes
|
||||||
|
ProtectControlGroups=yes
|
||||||
|
RestrictRealtime=yes
|
||||||
|
RestrictSUIDSGID=yes
|
||||||
|
|
||||||
|
# Network security
|
||||||
|
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||||
|
|
||||||
|
# Filesystem permissions
|
||||||
|
ReadWritePaths=/var/lib/valkey
|
||||||
|
ReadOnlyPaths=/etc/valkey
|
||||||
|
|
||||||
|
# System call filtering
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
SystemCallFilter=~@privileged @resources @obsolete
|
||||||
|
|
||||||
|
# Memory and resource limits
|
||||||
|
MemoryDenyWriteExecute=yes
|
||||||
|
LockPersonality=yes
|
||||||
|
|
||||||
|
# Capabilities (remove all unnecessary capabilities)
|
||||||
|
CapabilityBoundingSet=
|
||||||
|
AmbientCapabilities=
|
||||||
|
|
||||||
|
# Process isolation
|
||||||
|
PrivateUsers=yes
|
||||||
|
RemoveIPC=yes
|
||||||
|
|
||||||
|
# Additional security
|
||||||
|
UMask=0027
|
||||||
|
|
||||||
|
# Ensure service stops cleanly
|
||||||
|
KillMode=mixed
|
||||||
|
KillSignal=SIGTERM
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=redis.service
|
||||||
10
site.yml
10
site.yml
@@ -13,13 +13,15 @@
|
|||||||
# tags: ['postgresql', 'infrastructure', 'database']
|
# tags: ['postgresql', 'infrastructure', 'database']
|
||||||
# - role: valkey
|
# - role: valkey
|
||||||
# tags: ['valkey', 'redis', 'infrastructure', 'cache']
|
# tags: ['valkey', 'redis', 'infrastructure', 'cache']
|
||||||
- role: podman
|
# - role: podman
|
||||||
tags: ['podman', 'containers', 'infrastructure']
|
# tags: ['podman', 'containers', 'infrastructure']
|
||||||
# - role: caddy
|
# - role: caddy
|
||||||
# tags: ['caddy', 'infrastructure', 'web']
|
# tags: ['caddy', 'infrastructure', 'web']
|
||||||
|
|
||||||
# Application services
|
# Application services
|
||||||
# - role: gitea
|
- role: authentik
|
||||||
# tags: ['gitea', 'git', 'development']
|
tags: ['authentik', 'auth', 'sso', 'containers']
|
||||||
|
- role: gitea
|
||||||
|
tags: ['gitea', 'git', 'development']
|
||||||
# - role: sigvild-gallery
|
# - role: sigvild-gallery
|
||||||
# tags: ['sigvild', 'gallery', 'wedding']
|
# tags: ['sigvild', 'gallery', 'wedding']
|
||||||
|
|||||||
Reference in New Issue
Block a user