--- # Configure Authentik flows (invitation, recovery, 2FA) via Blueprints - name: Use bootstrap token for API access set_fact: authentik_api_token: "{{ client_secrets.authentik_bootstrap_token }}" - name: Wait for Authentik API to be ready shell: | i=1 while [ $i -le 30 ]; do if docker exec authentik-server curl -sf -H "Authorization: Bearer {{ authentik_api_token }}" http://localhost:9000/api/v3/flows/instances/ > /dev/null 2>&1; then echo "Authentik API is ready" exit 0 fi echo "Waiting for Authentik API... attempt $i/30" sleep 5 i=$((i+1)) done exit 1 register: api_wait changed_when: false - name: Create blueprints directory on server file: path: "{{ authentik_config_dir }}/blueprints" state: directory mode: '0755' - name: Copy custom flows blueprint to server copy: src: custom-flows.yaml dest: "{{ authentik_config_dir }}/blueprints/custom-flows.yaml" mode: '0644' register: blueprint_copied - name: Copy blueprint into authentik-worker container shell: | docker cp "{{ authentik_config_dir }}/blueprints/custom-flows.yaml" authentik-worker:/blueprints/custom-flows.yaml changed_when: blueprint_copied.changed - name: Copy blueprint into authentik-server container shell: | docker cp "{{ authentik_config_dir }}/blueprints/custom-flows.yaml" authentik-server:/blueprints/custom-flows.yaml changed_when: blueprint_copied.changed - name: Wait for blueprint to be discovered and applied shell: | echo "Waiting for blueprint to be discovered and applied..." sleep 10 # Check if blueprint instance was created i=1 while [ $i -le 24 ]; do result=$(docker exec authentik-server curl -sf -H 'Authorization: Bearer {{ authentik_api_token }}' \ 'http://localhost:9000/api/v3/managed/blueprints/' 2>/dev/null || echo '') if echo "$result" | grep -q 'custom-flow-configuration'; then echo "Blueprint instance found" # Check if it has been applied successfully if echo "$result" | grep -A 10 'custom-flow-configuration' | grep -q 'successful'; then echo "Blueprint applied successfully" exit 0 else echo "Blueprint found but not yet applied, waiting..." fi else echo "Waiting for blueprint discovery... attempt $i/24" fi sleep 5 i=$((i+1)) done echo "Blueprint may still be applying, continuing..." exit 0 register: blueprint_wait changed_when: false - name: Verify invitation stage was created shell: | docker exec authentik-server curl -sf -H "Authorization: Bearer {{ authentik_api_token }}" \ "http://localhost:9000/api/v3/stages/all/" | \ python3 -c "import sys, json; data = json.load(sys.stdin); stages = [s for s in data['results'] if 'invitation' in s.get('name', '').lower()]; print(json.dumps({'found': len(stages) > 0, 'count': len(stages)}))" register: invitation_check changed_when: false failed_when: false - name: Verify brand recovery flow was set shell: | docker exec authentik-server curl -sf -H "Authorization: Bearer {{ authentik_api_token }}" \ "http://localhost:9000/api/v3/core/brands/" | \ python3 -c "import sys, json; data = json.load(sys.stdin); brand = data['results'][0] if data['results'] else {}; print(json.dumps({'recovery_flow_set': brand.get('flow_recovery') is not None}))" register: recovery_check changed_when: false failed_when: false - name: Display flows configuration status debug: msg: | ======================================== Authentik Flows Configuration ======================================== Configuration Method: YAML Blueprints Blueprint File: /blueprints/custom-flows.yaml ✓ Blueprint Deployed: {{ blueprint_copied.changed }} ✓ Blueprint Applied: {{ 'Yes' if 'successfully' in blueprint_wait.stdout else 'In Progress' }} Verification: {{ invitation_check.stdout | default('Invitation stage: Checking...') }} {{ recovery_check.stdout | default('Recovery flow: Checking...') }} Note: Authentik applies blueprints asynchronously. Changes should be visible within 1-2 minutes. To verify manually: - Login to https://{{ authentik_domain }} - Check Admin > Flows > Stages for invitation stage - Check Admin > System > Brands for recovery flow setting - Check default-authentication-mfa-validation stage for 2FA enforcement Email configuration is active and flows will send emails via Mailgun SMTP. ========================================