--- # Configure Authentik flows (invitation, 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 flow blueprints to server copy: src: "{{ item }}" dest: "{{ authentik_config_dir }}/blueprints/{{ item }}" mode: '0644' loop: - custom-flows.yaml - enrollment-flow.yaml register: blueprints_copied - name: Copy blueprints into authentik-worker container shell: | docker cp "{{ authentik_config_dir }}/blueprints/{{ item }}" authentik-worker:/blueprints/{{ item }} loop: - custom-flows.yaml - enrollment-flow.yaml when: blueprints_copied.changed - name: Copy blueprints into authentik-server container shell: | docker cp "{{ authentik_config_dir }}/blueprints/{{ item }}" authentik-server:/blueprints/{{ item }} loop: - custom-flows.yaml - enrollment-flow.yaml when: blueprints_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: Display flows configuration status debug: msg: | ======================================== Authentik Flows Configuration ======================================== Configuration Method: YAML Blueprints Blueprints Deployed: - /blueprints/custom-flows.yaml (2FA enforcement) - /blueprints/enrollment-flow.yaml (invitation-only registration) ✓ Blueprints Deployed: {{ blueprints_copied.changed }} ✓ Blueprints Applied: {{ 'Yes' if 'successfully' in blueprint_wait.stdout else 'In Progress' }} Verification: {{ invitation_check.stdout | default('Invitation stage: Checking...') }} Note: Authentik applies blueprints asynchronously. Changes should be visible within 1-2 minutes. Recovery flows must be configured manually in Authentik admin UI. Flow URLs: - Enrollment: https://{{ authentik_domain }}/if/flow/default-enrollment-flow/ Email configuration is active - emails sent via Mailgun SMTP. ========================================