From 599bb3e28291b454109dbf6c071a40120a34ab06 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:43:03 +0100 Subject: [PATCH 1/8] feat: add ability to provision local users using blueprints --- roles/authentik/defaults/main.yml | 13 +++++++++++++ roles/authentik/tasks/main.yml | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/roles/authentik/defaults/main.yml b/roles/authentik/defaults/main.yml index 8213b4d..8ac0785 100644 --- a/roles/authentik/defaults/main.yml +++ b/roles/authentik/defaults/main.yml @@ -98,3 +98,16 @@ authentik_entra_sources: [] authentik_login_source_ids: [] # - "source-entra-entra-id" authentik_identification_stage_name: default-authentication-identification + +# Local users to provision +authentik_local_users: [] +# - username: admin +# name: "Admin User" +# email: "admin@example.com" +# password_env: AUTHENTIK_ADMIN_PASSWORD # reference env var in authentik_blueprint_env +# is_active: true +# groups: +# - authentik Admins +# attributes: +# settings: +# locale: en diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index fa5caed..49cacb7 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -77,6 +77,14 @@ mode: "0644" register: login_bp +- name: Render local users blueprint + ansible.builtin.template: + src: blueprints/blueprint-local-users.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/05-local-users.yaml" + mode: "0644" + when: authentik_local_users | length > 0 + register: local_users_bp + - name: Create docker-compose file for authentik template: src: docker-compose.yml.j2 @@ -95,5 +103,6 @@ or (outpost_bp is defined and (outpost_bp.results | selectattr('changed') | list | length > 0)) or (entra_bp is defined and (entra_bp.results | selectattr('changed') | list | length > 0)) or (login_bp is defined and login_bp.changed) + or (local_users_bp.changed | default(false)) ) | ternary('always','auto') }} From 2417d24eeafbead32720a0e7f1897f353926cff7 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:47:42 +0100 Subject: [PATCH 2/8] chore: add minimal readme --- roles/authentik/README.md | 45 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/roles/authentik/README.md b/roles/authentik/README.md index 225dd44..2fb18d1 100644 --- a/roles/authentik/README.md +++ b/roles/authentik/README.md @@ -1,38 +1,19 @@ -Role Name -========= +# Authentik -A brief description of the role goes here. +Deploys Authentik identity provider with Docker Compose. -Requirements ------------- +## Variables -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +See `defaults/main.yml` for all available variables. -Role Variables --------------- +## Blueprints -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +The role renders blueprints for: +- Local users (`authentik_local_users`) +- OIDC applications (`authentik_oidc_apps`) +- Proxy applications (`authentik_proxy_apps`) +- Proxy outposts (`authentik_proxy_outposts`) +- Entra ID sources (`authentik_entra_sources`) +- Login screen sources (`authentik_login_source_ids`) -Dependencies ------------- - -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. - -Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } - -License -------- - -BSD - -Author Information ------------------- - -An optional section for the role authors to include contact information, or a website (HTML is not allowed). +Secrets are passed via `authentik_blueprint_env` using environment variable references. \ No newline at end of file From 889c6abb9d197c00a1d80c1a7bbafb252270275c Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:51:19 +0100 Subject: [PATCH 3/8] chore: add removal of stale blueprints --- roles/authentik/tasks/main.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index 49cacb7..5a28a69 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -38,6 +38,31 @@ state: directory mode: '0755' +- name: Find existing blueprint files + find: + paths: "{{ authentik_docker_volume_dir }}/blueprints" + patterns: "*.yaml" + register: existing_blueprints + +- name: Build list of expected blueprint files + set_fact: + expected_blueprints: >- + {{ + (authentik_oidc_apps | map(attribute='slug') | map('regex_replace', '^(.*)$', '10-oidc-\1.yaml') | list) + + (authentik_proxy_apps | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-proxy-\1.yaml') | list) + + (authentik_proxy_outposts | map(attribute='name') | map('regex_replace', '^(.*)$', '30-outpost-\1.yaml') | list) + + (authentik_entra_sources | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-source-entra-\1.yaml') | list) + + ['21-login-sources.yaml'] + + ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + }} + +- name: Remove stale blueprint files + file: + path: "{{ item.path }}" + state: absent + loop: "{{ existing_blueprints.files }}" + when: item.path | basename not in expected_blueprints + - name: Render OIDC blueprints ansible.builtin.template: src: blueprints/blueprint-oidc-app.yaml.j2 From 8f02dd774f79d54be8338bb30d9b1e30109511e5 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 16:03:20 +0100 Subject: [PATCH 4/8] feat: allow deletion of ressources via blueprints --- roles/authentik/README.md | 11 ++++++++++- roles/authentik/defaults/main.yml | 11 +++++++++++ roles/authentik/tasks/main.yml | 12 +++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/roles/authentik/README.md b/roles/authentik/README.md index 2fb18d1..8311190 100644 --- a/roles/authentik/README.md +++ b/roles/authentik/README.md @@ -16,4 +16,13 @@ The role renders blueprints for: - Entra ID sources (`authentik_entra_sources`) - Login screen sources (`authentik_login_source_ids`) -Secrets are passed via `authentik_blueprint_env` using environment variable references. \ No newline at end of file +Secrets are passed via `authentik_blueprint_env` using environment variable references. + +## Removing resources + +To remove resources from Authentik, move slugs to the removal lists: +- `authentik_removed_oidc_apps` +- `authentik_removed_proxy_apps` +- `authentik_removed_local_users` + +After confirming deletion, remove the slug from the list. \ No newline at end of file diff --git a/roles/authentik/defaults/main.yml b/roles/authentik/defaults/main.yml index 8ac0785..85e8a15 100644 --- a/roles/authentik/defaults/main.yml +++ b/roles/authentik/defaults/main.yml @@ -111,3 +111,14 @@ authentik_local_users: [] # attributes: # settings: # locale: en + +# Resources to remove from Authentik (cleanup) +# Add slugs/names here when removing from the lists above +authentik_removed_oidc_apps: [] +# - grafana + +authentik_removed_proxy_apps: [] +# - whoami + +authentik_removed_local_users: [] +# - olduser diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index 5a28a69..83805ad 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -53,7 +53,8 @@ (authentik_proxy_outposts | map(attribute='name') | map('regex_replace', '^(.*)$', '30-outpost-\1.yaml') | list) + (authentik_entra_sources | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-source-entra-\1.yaml') | list) + ['21-login-sources.yaml'] + - ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + + (((authentik_removed_oidc_apps | length > 0) or (authentik_removed_proxy_apps | length > 0) or (authentik_removed_local_users | length > 0)) | ternary(['00-cleanup.yaml'], [])) }} - name: Remove stale blueprint files @@ -110,6 +111,14 @@ when: authentik_local_users | length > 0 register: local_users_bp +- name: Render cleanup blueprint + ansible.builtin.template: + src: blueprints/blueprint-cleanup.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/00-cleanup.yaml" + mode: "0644" + when: (authentik_removed_oidc_apps | length > 0) or (authentik_removed_proxy_apps | length > 0) or (authentik_removed_local_users | length > 0) + register: cleanup_bp + - name: Create docker-compose file for authentik template: src: docker-compose.yml.j2 @@ -129,5 +138,6 @@ or (entra_bp is defined and (entra_bp.results | selectattr('changed') | list | length > 0)) or (login_bp is defined and login_bp.changed) or (local_users_bp.changed | default(false)) + or (cleanup_bp.changed | default(false)) ) | ternary('always','auto') }} From d800d43c71bdafbf07611fe44561014bf31abeb1 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:43:03 +0100 Subject: [PATCH 5/8] feat: add ability to provision local users using blueprints --- roles/authentik/defaults/main.yml | 13 +++++++ roles/authentik/tasks/main.yml | 9 +++++ .../blueprints/blueprint-local-users.yaml.j2 | 34 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 roles/authentik/templates/blueprints/blueprint-local-users.yaml.j2 diff --git a/roles/authentik/defaults/main.yml b/roles/authentik/defaults/main.yml index 8213b4d..8ac0785 100644 --- a/roles/authentik/defaults/main.yml +++ b/roles/authentik/defaults/main.yml @@ -98,3 +98,16 @@ authentik_entra_sources: [] authentik_login_source_ids: [] # - "source-entra-entra-id" authentik_identification_stage_name: default-authentication-identification + +# Local users to provision +authentik_local_users: [] +# - username: admin +# name: "Admin User" +# email: "admin@example.com" +# password_env: AUTHENTIK_ADMIN_PASSWORD # reference env var in authentik_blueprint_env +# is_active: true +# groups: +# - authentik Admins +# attributes: +# settings: +# locale: en diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index fa5caed..49cacb7 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -77,6 +77,14 @@ mode: "0644" register: login_bp +- name: Render local users blueprint + ansible.builtin.template: + src: blueprints/blueprint-local-users.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/05-local-users.yaml" + mode: "0644" + when: authentik_local_users | length > 0 + register: local_users_bp + - name: Create docker-compose file for authentik template: src: docker-compose.yml.j2 @@ -95,5 +103,6 @@ or (outpost_bp is defined and (outpost_bp.results | selectattr('changed') | list | length > 0)) or (entra_bp is defined and (entra_bp.results | selectattr('changed') | list | length > 0)) or (login_bp is defined and login_bp.changed) + or (local_users_bp.changed | default(false)) ) | ternary('always','auto') }} diff --git a/roles/authentik/templates/blueprints/blueprint-local-users.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-local-users.yaml.j2 new file mode 100644 index 0000000..d40454b --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-local-users.yaml.j2 @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "local-users" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "Local user accounts" + +entries: +{% for user in authentik_local_users %} + - model: authentik_core.user + id: user-{{ user.username }} + identifiers: + username: {{ user.username }} + attrs: + username: {{ user.username }} + name: "{{ user.name | default(user.username) }}" + email: "{{ user.email | default('') }}" + is_active: {{ user.is_active | default(true) | lower }} +{% if user.password_env is defined %} + password: !Env {{ user.password_env }} +{% endif %} +{% if user.groups is defined and user.groups | length > 0 %} + groups: +{% for group in user.groups %} + - !Find [authentik_core.group, [name, {{ group }}]] +{% endfor %} +{% endif %} +{% if user.attributes is defined %} + attributes: +{{ user.attributes | to_nice_yaml(indent=2) | indent(8, first=true) }} +{% endif %} + +{% endfor %} \ No newline at end of file From 8828436adfa4a31970bff1d915ad7db730c1ff8e Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:47:42 +0100 Subject: [PATCH 6/8] chore: add minimal readme --- roles/authentik/README.md | 45 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/roles/authentik/README.md b/roles/authentik/README.md index 225dd44..2fb18d1 100644 --- a/roles/authentik/README.md +++ b/roles/authentik/README.md @@ -1,38 +1,19 @@ -Role Name -========= +# Authentik -A brief description of the role goes here. +Deploys Authentik identity provider with Docker Compose. -Requirements ------------- +## Variables -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +See `defaults/main.yml` for all available variables. -Role Variables --------------- +## Blueprints -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +The role renders blueprints for: +- Local users (`authentik_local_users`) +- OIDC applications (`authentik_oidc_apps`) +- Proxy applications (`authentik_proxy_apps`) +- Proxy outposts (`authentik_proxy_outposts`) +- Entra ID sources (`authentik_entra_sources`) +- Login screen sources (`authentik_login_source_ids`) -Dependencies ------------- - -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. - -Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } - -License -------- - -BSD - -Author Information ------------------- - -An optional section for the role authors to include contact information, or a website (HTML is not allowed). +Secrets are passed via `authentik_blueprint_env` using environment variable references. \ No newline at end of file From f8b9975ae4381c1e4ec4d637a263b3d4348cae14 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 15:51:19 +0100 Subject: [PATCH 7/8] chore: add removal of stale blueprints --- roles/authentik/tasks/main.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index 49cacb7..5a28a69 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -38,6 +38,31 @@ state: directory mode: '0755' +- name: Find existing blueprint files + find: + paths: "{{ authentik_docker_volume_dir }}/blueprints" + patterns: "*.yaml" + register: existing_blueprints + +- name: Build list of expected blueprint files + set_fact: + expected_blueprints: >- + {{ + (authentik_oidc_apps | map(attribute='slug') | map('regex_replace', '^(.*)$', '10-oidc-\1.yaml') | list) + + (authentik_proxy_apps | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-proxy-\1.yaml') | list) + + (authentik_proxy_outposts | map(attribute='name') | map('regex_replace', '^(.*)$', '30-outpost-\1.yaml') | list) + + (authentik_entra_sources | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-source-entra-\1.yaml') | list) + + ['21-login-sources.yaml'] + + ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + }} + +- name: Remove stale blueprint files + file: + path: "{{ item.path }}" + state: absent + loop: "{{ existing_blueprints.files }}" + when: item.path | basename not in expected_blueprints + - name: Render OIDC blueprints ansible.builtin.template: src: blueprints/blueprint-oidc-app.yaml.j2 From 3d3a09025aaf7480fc79ee32e8bd1c7397d751f7 Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Wed, 14 Jan 2026 16:03:20 +0100 Subject: [PATCH 8/8] feat: allow deletion of ressources via blueprints --- roles/authentik/README.md | 11 +++++- roles/authentik/defaults/main.yml | 11 ++++++ roles/authentik/tasks/main.yml | 12 +++++- .../blueprints/blueprint-cleanup.yaml.j2 | 38 +++++++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 roles/authentik/templates/blueprints/blueprint-cleanup.yaml.j2 diff --git a/roles/authentik/README.md b/roles/authentik/README.md index 2fb18d1..8311190 100644 --- a/roles/authentik/README.md +++ b/roles/authentik/README.md @@ -16,4 +16,13 @@ The role renders blueprints for: - Entra ID sources (`authentik_entra_sources`) - Login screen sources (`authentik_login_source_ids`) -Secrets are passed via `authentik_blueprint_env` using environment variable references. \ No newline at end of file +Secrets are passed via `authentik_blueprint_env` using environment variable references. + +## Removing resources + +To remove resources from Authentik, move slugs to the removal lists: +- `authentik_removed_oidc_apps` +- `authentik_removed_proxy_apps` +- `authentik_removed_local_users` + +After confirming deletion, remove the slug from the list. \ No newline at end of file diff --git a/roles/authentik/defaults/main.yml b/roles/authentik/defaults/main.yml index 8ac0785..85e8a15 100644 --- a/roles/authentik/defaults/main.yml +++ b/roles/authentik/defaults/main.yml @@ -111,3 +111,14 @@ authentik_local_users: [] # attributes: # settings: # locale: en + +# Resources to remove from Authentik (cleanup) +# Add slugs/names here when removing from the lists above +authentik_removed_oidc_apps: [] +# - grafana + +authentik_removed_proxy_apps: [] +# - whoami + +authentik_removed_local_users: [] +# - olduser diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml index 5a28a69..83805ad 100644 --- a/roles/authentik/tasks/main.yml +++ b/roles/authentik/tasks/main.yml @@ -53,7 +53,8 @@ (authentik_proxy_outposts | map(attribute='name') | map('regex_replace', '^(.*)$', '30-outpost-\1.yaml') | list) + (authentik_entra_sources | map(attribute='slug') | map('regex_replace', '^(.*)$', '20-source-entra-\1.yaml') | list) + ['21-login-sources.yaml'] + - ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + ((authentik_local_users | length > 0) | ternary(['05-local-users.yaml'], [])) + + (((authentik_removed_oidc_apps | length > 0) or (authentik_removed_proxy_apps | length > 0) or (authentik_removed_local_users | length > 0)) | ternary(['00-cleanup.yaml'], [])) }} - name: Remove stale blueprint files @@ -110,6 +111,14 @@ when: authentik_local_users | length > 0 register: local_users_bp +- name: Render cleanup blueprint + ansible.builtin.template: + src: blueprints/blueprint-cleanup.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/00-cleanup.yaml" + mode: "0644" + when: (authentik_removed_oidc_apps | length > 0) or (authentik_removed_proxy_apps | length > 0) or (authentik_removed_local_users | length > 0) + register: cleanup_bp + - name: Create docker-compose file for authentik template: src: docker-compose.yml.j2 @@ -129,5 +138,6 @@ or (entra_bp is defined and (entra_bp.results | selectattr('changed') | list | length > 0)) or (login_bp is defined and login_bp.changed) or (local_users_bp.changed | default(false)) + or (cleanup_bp.changed | default(false)) ) | ternary('always','auto') }} diff --git a/roles/authentik/templates/blueprints/blueprint-cleanup.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-cleanup.yaml.j2 new file mode 100644 index 0000000..27e2461 --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-cleanup.yaml.j2 @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "cleanup" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "Remove stale resources" + +entries: +{% for slug in authentik_removed_oidc_apps %} + # Remove OIDC app: {{ slug }} + - model: authentik_core.application + state: absent + identifiers: + slug: {{ slug }} + - model: authentik_providers_oauth2.oauth2provider + state: absent + identifiers: + name: {{ slug }} +{% endfor %} +{% for slug in authentik_removed_proxy_apps %} + # Remove proxy app: {{ slug }} + - model: authentik_core.application + state: absent + identifiers: + slug: {{ slug }} + - model: authentik_providers_proxy.proxyprovider + state: absent + identifiers: + name: {{ slug }} +{% endfor %} +{% for username in authentik_removed_local_users %} + # Remove user: {{ username }} + - model: authentik_core.user + state: absent + identifiers: + username: {{ username }} +{% endfor %} \ No newline at end of file