homelab/ansible/ansible-old/playbooks/docker/deploy_authentik.yml

186 lines
7.8 KiB
YAML

---
# playbooks/docker/deploy_authentik.yml
#
# Purpose:
# Deploy Authentik as a Swarm stack pinned to swarm-manager-1 with persistent
# bind mounts under /mnt/homelab/apps/authentik.
#
# Data protection:
# This playbook validates all required Authentik data paths before deploy.
# If paths are missing, deployment fails early to avoid creating empty data
# roots that could mask or diverge from an existing Authentik installation.
#
# Usage:
# ansible-playbook -i inventory/hosts.ini playbooks/docker/deploy_authentik.yml
#
# ansible-playbook -i inventory/hosts.ini playbooks/docker/deploy_authentik.yml \
# -e "stack_validate_only=true"
#
# ansible-playbook -i inventory/hosts.ini playbooks/docker/deploy_authentik.yml \
# -e "authentik_deploy_state=absent"
- name: Deploy Authentik Swarm stack
hosts: swarm_managers
become: true
gather_facts: false
vars_files:
- ../../group_vars/all.yml
vars:
authentik_deploy_target: "{{ edge_routing.swarm.stack_deploy_target | default(groups['swarm_managers'][0]) }}"
tasks:
# --------------------------------------------------
# STEP 0: Assert required secrets are present
# --------------------------------------------------
- name: Assert vault_authentik_secret_key is defined and non-empty
ansible.builtin.assert:
that:
- vault_authentik_secret_key is defined
- vault_authentik_secret_key | trim | length > 0
fail_msg: >-
vault_authentik_secret_key is not defined or is empty.
Encrypt and store it in group_vars/vault/all.yml with:
ansible-vault encrypt_string 'your-random-secret' --name 'vault_authentik_secret_key'
when: inventory_hostname == authentik_deploy_target
- name: Assert vault_authentik_postgres_password is defined and non-empty
ansible.builtin.assert:
that:
- vault_authentik_postgres_password is defined
- vault_authentik_postgres_password | trim | length > 0
fail_msg: >-
vault_authentik_postgres_password is not defined or is empty.
Encrypt and store it in group_vars/vault/all.yml with:
ansible-vault encrypt_string 'your-db-password' --name 'vault_authentik_postgres_password'
when: inventory_hostname == authentik_deploy_target
- name: Assert Authentik secrets are not placeholders
ansible.builtin.assert:
that:
- vault_authentik_secret_key not in ['change-me', 'changeme', 'your-random-secret']
- vault_authentik_postgres_password not in ['change-me', 'changeme', 'your-db-password']
fail_msg: "Authentik secrets still appear to be placeholders. Set real vault values before deploy."
when: inventory_hostname == authentik_deploy_target
# --------------------------------------------------
# STEP 1: Assert Swarm manager is active
# --------------------------------------------------
- name: Collect Swarm manager state
ansible.builtin.command: >
docker info --format '{{ "{{" }}.Swarm.LocalNodeState{{ "}}" }}|{{ "{{" }}.Swarm.ControlAvailable{{ "}}" }}'
register: _swarm_info
changed_when: false
when: inventory_hostname == authentik_deploy_target
- name: Assert target is an active Swarm manager
ansible.builtin.assert:
that:
- _swarm_info.stdout is search('active')
- _swarm_info.stdout is search('true')
fail_msg: >-
{{ inventory_hostname }} must be an active Swarm manager.
Current state: {{ _swarm_info.stdout | default('unknown') }}
when: inventory_hostname == authentik_deploy_target
# --------------------------------------------------
# STEP 2: Validate pre-existing persistent data paths
# --------------------------------------------------
- name: Stat required Authentik bind-mount paths
ansible.builtin.stat:
path: "{{ item }}"
register: _authentik_path_stat
loop:
- /mnt/homelab/apps/authentik
- /mnt/homelab/apps/authentik/data
- /mnt/homelab/apps/authentik/data/database
- /mnt/homelab/apps/authentik/data/redis
- /mnt/homelab/apps/authentik/data/media
- /mnt/homelab/apps/authentik/data/config
- /mnt/homelab/apps/authentik/data/blueprints
when: inventory_hostname == authentik_deploy_target
- name: Assert required Authentik paths exist before deploy
ansible.builtin.assert:
that:
- item.stat.exists
- item.stat.isdir
fail_msg: >-
Required Authentik path '{{ item.item }}' is missing on {{ inventory_hostname }}.
Create/restore this directory first to avoid accidental fresh bootstrap over existing data.
loop: "{{ _authentik_path_stat.results }}"
when: inventory_hostname == authentik_deploy_target
# --------------------------------------------------
# STEP 3: Deploy Authentik stack
# --------------------------------------------------
- name: Deploy Authentik stack
ansible.builtin.include_role:
name: swarm_stack_deploy
vars:
stack_name: "authentik"
stack_compose_src: "{{ playbook_dir }}/../../templates/stacks/authentik.stack.yml"
# authentik_placement_node resolved from group_vars (swarm-manager-2)
# Use service-specific state var to avoid self-reference recursion.
stack_state: "{{ authentik_deploy_state | default('present') }}"
stack_required_external_networks:
- proxy-net
stack_required_directories:
- /mnt/homelab/apps/authentik
- /mnt/homelab/apps/authentik/data
- /mnt/homelab/apps/authentik/data/database
- /mnt/homelab/apps/authentik/data/redis
- /mnt/homelab/apps/authentik/data/media
- /mnt/homelab/apps/authentik/data/config
- /mnt/homelab/apps/authentik/data/blueprints
when: inventory_hostname == authentik_deploy_target
# --------------------------------------------------
# STEP 4: Wait for service convergence
# --------------------------------------------------
- name: Wait for Authentik server service to converge
ansible.builtin.command: >
docker service ls --filter name=authentik_authentik-server --format '{{ "{{" }}.Replicas{{ "}}" }}'
register: _authentik_server_replicas
retries: 18
delay: 10
until: _authentik_server_replicas.stdout is search('1/1')
changed_when: false
when:
- inventory_hostname == authentik_deploy_target
- authentik_deploy_state | default('present') == 'present'
- not ansible_check_mode
tags: [verify]
- name: Wait for Authentik worker service to converge
ansible.builtin.command: >
docker service ls --filter name=authentik_authentik-worker --format '{{ "{{" }}.Replicas{{ "}}" }}'
register: _authentik_worker_replicas
retries: 18
delay: 10
until: _authentik_worker_replicas.stdout is search('1/1')
changed_when: false
when:
- inventory_hostname == authentik_deploy_target
- authentik_deploy_state | default('present') == 'present'
- not ansible_check_mode
tags: [verify]
- name: Report Authentik deployment result
ansible.builtin.debug:
msg:
- "================================================"
- "Authentik deployment complete."
- "================================================"
- "Stack : authentik"
- "Manager : {{ inventory_hostname }} ({{ ansible_host | default('') }})"
- "URL : https://sso.castaldifamily.com"
- "Data root : /mnt/homelab/apps/authentik"
- "Services : authentik-postgres, authentik-redis, authentik-server, authentik-worker"
- "================================================"
when: inventory_hostname == authentik_deploy_target
tags: [always]