diff --git a/roles/authentik/README.md b/roles/authentik/README.md new file mode 100644 index 0000000..8311190 --- /dev/null +++ b/roles/authentik/README.md @@ -0,0 +1,28 @@ +# Authentik + +Deploys Authentik identity provider with Docker Compose. + +## Variables + +See `defaults/main.yml` for all available variables. + +## Blueprints + +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`) + +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 new file mode 100644 index 0000000..460ba2d --- /dev/null +++ b/roles/authentik/defaults/main.yml @@ -0,0 +1,130 @@ +#SPDX-License-Identifier: MIT-0 +--- +# defaults file for authentik + +# Base directory configuration (inherited from base role or defined here) +docker_compose_base_dir: /etc/docker/compose +docker_volume_base_dir: /srv/data + +# Authentik-specific configuration +authentik_service_name: authentik +authentik_docker_compose_dir: "{{ docker_compose_base_dir }}/{{ authentik_service_name }}" +authentik_docker_volume_dir: "{{ docker_volume_base_dir }}/{{ authentik_service_name }}" + +# Authentik service configuration +authentik_domain: "authentik.local.test" +authentik_image: "ghcr.io/goauthentik/server:2025.12.0" +authentik_port: 9000 +authentik_secret_key: "changeme-generate-a-random-string" + +# PostgreSQL configuration +authentik_postgres_image: "postgres:16-alpine" +authentik_postgres_db: authentik +authentik_postgres_user: authentik +authentik_postgres_password: "changeme" + +# Traefik configuration +authentik_traefik_network: "proxy" +authentik_backend_network: "backend" +authentik_use_ssl: true + +# Authentik environment settings +authentik_log_level: "info" +authentik_error_reporting_enabled: false + +# Blueprints +authentik_proxy_apps: [] +# - slug: whoami +# name: whoami +# internal_host: "http://whoami:80" +# external_host: "https://whoami.example.com" +# skip_path_regex: | +# ^/healthz$ +# flows: +# authentication_slug: default-authentication-flow +# authorization_slug: default-provider-authorization-implicit-consent +# invalidation_slug: default-provider-invalidation-flow + +authentik_proxy_outposts: [] +# - name: "proxy-main" +# type: "proxy" +# service_connection: null +# providers: +# - whoami +# - nextcloud-proxy +# config: +# authentik_host: "https://authentik.local.test/" +# authentik_host_browser: "https://authentik.local.test/" +# log_level: "info" + +authentik_oidc_apps: [] +# - slug: grafana +# name: Grafana +# client_id_env: GRAFANA_OIDC_CLIENT_ID +# client_secret_env: GRAFANA_OIDC_CLIENT_SECRET +# redirect_uris: +# - url: "https://grafana.example.com/login/generic_oauth" +# matching_mode: strict +# signing_key_name: "authentik Self-signed Certificate" +# flows: +# authorization_slug: default-provider-authorization-implicit-consent +# invalidation_slug: default-provider-invalidation-flow +# scopes: [openid, email, profile, offline_access] + +authentik_blueprint_env: [] +# GRAFANA_OIDC_CLIENT_ID: "grafana" +# GRAFANA_OIDC_CLIENT_SECRET: "{{ vault_grafana_oidc_secret }}" +# ENTRA_TENANT_ID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +# ENTRA_CLIENT_ID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +# ENTRA_CLIENT_SECRET: "{{ vault_entra_client_secret }}" + +# Oauth sources +authentik_entra_sources: [] +# - slug: entra-id +# name: "Login with Entra" +# tenant_mode: single # single | common +# tenant_id_env: ENTRA_TENANT_ID +# client_id_env: ENTRA_CLIENT_ID +# client_secret_env: ENTRA_CLIENT_SECRET +# scopes: +# - openid +# - profile +# - email +# # add only if you really need group sync on login: +# # - https://graph.microsoft.com/GroupMember.Read.All + + +# Show OAuth sources on login screen (list of source slugs): +authentik_login_sources: [] +# - slug: entra-id +authentik_identification_stage_name: default-authentication-identification + +# Local login fields to show on login screen (username, email, upn) +# Set to empty list to hide local login form entirely +authentik_login_user_fields: + - username + - email + +# 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 + +# 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/handlers/main.yml b/roles/authentik/handlers/main.yml new file mode 100644 index 0000000..fbc8aa0 --- /dev/null +++ b/roles/authentik/handlers/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# handlers file for authentik diff --git a/roles/authentik/meta/main.yml b/roles/authentik/meta/main.yml new file mode 100644 index 0000000..6f91fd3 --- /dev/null +++ b/roles/authentik/meta/main.yml @@ -0,0 +1,35 @@ +#SPDX-License-Identifier: MIT-0 +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.2 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/roles/authentik/tasks/blueprints.yml b/roles/authentik/tasks/blueprints.yml new file mode 100644 index 0000000..e40b774 --- /dev/null +++ b/roles/authentik/tasks/blueprints.yml @@ -0,0 +1,97 @@ +#SPDX-License-Identifier: MIT-0 +--- +# Blueprint rendering tasks for authentik + +- 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', '^(.*)$', '50-oidc-\1.yaml') | list) + + (authentik_proxy_apps | map(attribute='slug') | map('regex_replace', '^(.*)$', '60-proxy-\1.yaml') | list) + + (authentik_proxy_outposts | map(attribute='name') | map('regex_replace', '^(.*)$', '70-outpost-\1.yaml') | list) + + (authentik_entra_sources | map(attribute='slug') | map('regex_replace', '^(.*)$', '40-source-entra-\1.yaml') | list) + + ['45-login-sources.yaml'] + + ((authentik_local_users | length > 0) | ternary(['10-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 + 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 + dest: "{{ authentik_docker_volume_dir }}/blueprints/50-oidc-{{ item.slug }}.yaml" + mode: "0644" + loop: "{{ authentik_oidc_apps }}" + register: oidc_templates + +- name: Render Proxy blueprints + ansible.builtin.template: + src: blueprints/blueprint-proxy-app.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/60-proxy-{{ item.slug }}.yaml" + mode: "0644" + loop: "{{ authentik_proxy_apps }}" + register: proxy_templates + +- name: Render outpost blueprints + ansible.builtin.template: + src: blueprints/outpost-proxy.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/70-outpost-{{ item.name }}.yaml" + mode: "0644" + loop: "{{ authentik_proxy_outposts }}" + register: outpost_bp + +- name: Render Entra source blueprints + ansible.builtin.template: + src: blueprints/blueprint-source-entra.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/40-source-entra-{{ item.slug }}.yaml" + mode: "0644" + loop: "{{ authentik_entra_sources }}" + register: entra_bp + +- name: Render login stage sources blueprint + ansible.builtin.template: + src: blueprints/blueprint-login-sources.yaml.j2 + dest: "{{ authentik_docker_volume_dir }}/blueprints/45-login-sources.yaml" + 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/10-local-users.yaml" + mode: "0644" + 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: Set blueprints_changed fact + set_fact: + blueprints_changed: >- + {{ + (oidc_templates is defined and (oidc_templates.results | selectattr('changed') | list | length > 0)) + or (proxy_templates is defined and (proxy_templates.results | selectattr('changed') | list | length > 0)) + 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)) + or (cleanup_bp.changed | default(false)) + }} \ No newline at end of file diff --git a/roles/authentik/tasks/main.yml b/roles/authentik/tasks/main.yml new file mode 100644 index 0000000..aa14bd3 --- /dev/null +++ b/roles/authentik/tasks/main.yml @@ -0,0 +1,56 @@ +#SPDX-License-Identifier: MIT-0 +--- +# tasks file for authentik + +- name: Create docker compose directory + file: + path: "{{ authentik_docker_compose_dir }}" + state: directory + mode: '0755' + +- name: Create authentik data directory + file: + path: "{{ authentik_docker_volume_dir }}/data" + state: directory + mode: '0755' + +- name: Create authentik certs directory + file: + path: "{{ authentik_docker_volume_dir }}/certs" + state: directory + mode: '0755' + +- name: Create authentik templates directory + file: + path: "{{ authentik_docker_volume_dir }}/templates" + state: directory + mode: '0755' + +- name: Create postgres data directory + file: + path: "{{ authentik_docker_volume_dir }}/postgresql" + state: directory + mode: '0755' + +- name: Create blueprints directory + file: + path: "{{ authentik_docker_volume_dir }}/blueprints" + state: directory + mode: '0755' + +- name: Render blueprints + import_tasks: blueprints.yml + +- name: Create docker-compose file for authentik + template: + src: docker-compose.yml.j2 + dest: "{{ authentik_docker_compose_dir }}/docker-compose.yml" + mode: '0644' + +- name: Start authentik containers + community.docker.docker_compose_v2: + project_src: "{{ authentik_docker_compose_dir }}" + state: present + recreate: "{{ blueprints_changed | ternary('always', 'auto') }}" + wait: true + wait_timeout: 300 \ No newline at end of file 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 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 diff --git a/roles/authentik/templates/blueprints/blueprint-login-sources.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-login-sources.yaml.j2 new file mode 100644 index 0000000..acbb635 --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-login-sources.yaml.j2 @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "login-sources" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "Set sources and user fields on the identification stage" + +entries: + - model: authentik_stages_identification.identificationstage + identifiers: + name: "{{ authentik_identification_stage_name }}" + attrs: + # Local login fields (username, email, upn) + user_fields: +{% for field in authentik_login_user_fields %} + - {{ field }} +{% endfor %} + # OAuth/social login sources (use !Find to reference sources from other blueprints) + sources: +{% for src in authentik_login_sources %} + - !Find [authentik_sources_oauth.oauthsource, [slug, {{ src.slug }}]] +{% endfor %} diff --git a/roles/authentik/templates/blueprints/blueprint-oidc-app.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-oidc-app.yaml.j2 new file mode 100644 index 0000000..7270de8 --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-oidc-app.yaml.j2 @@ -0,0 +1,43 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "oidc-{{ item.slug }}" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "OIDC provider + application for {{ item.slug }}" + +entries: + - model: authentik_providers_oauth2.oauth2provider + id: oidc-provider-{{ item.slug }} + identifiers: + name: {{ item.slug }} + attrs: + name: {{ item.slug }} + client_type: confidential + client_id: !Env {{ item.client_id_env }} + client_secret: !Env {{ item.client_secret_env }} + + redirect_uris: +{% for ru in item.redirect_uris %} + - url: "{{ ru.url }}" + matching_mode: {{ ru.matching_mode | default('strict') }} +{% endfor %} + + authorization_flow: !Find [authentik_flows.flow, [slug, {{ item.flows.authorization_slug | default('default-provider-authorization-implicit-consent') }}]] + invalidation_flow: !Find [authentik_flows.flow, [slug, {{ item.flows.invalidation_slug | default('default-provider-invalidation-flow') }}]] + + property_mappings: +{% for s in (item.scopes | default(['openid','email','profile','offline_access'])) %} + - !Find [authentik_providers_oauth2.scopemapping, [scope_name, {{ s }}]] +{% endfor %} + + signing_key: !Find [authentik_crypto.certificatekeypair, [name, {{ item.signing_key_name | default('authentik Self-signed Certificate') }}]] + + - model: authentik_core.application + id: app-{{ item.slug }} + identifiers: + slug: {{ item.slug }} + attrs: + name: "{{ item.name | default(item.slug) }}" + slug: {{ item.slug }} + provider: !KeyOf oidc-provider-{{ item.slug }} diff --git a/roles/authentik/templates/blueprints/blueprint-proxy-app.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-proxy-app.yaml.j2 new file mode 100644 index 0000000..5e29756 --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-proxy-app.yaml.j2 @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "proxy-{{ item.slug }}" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "Proxy provider + application for {{ item.slug }}" + +entries: + - model: authentik_providers_proxy.proxyprovider + id: proxy-provider-{{ item.slug }} + identifiers: + name: {{ item.slug }} + attrs: + name: {{ item.slug }} + + authentication_flow: !Find [authentik_flows.flow, [slug, {{ item.flows.authentication_slug | default('default-authentication-flow') }}]] + authorization_flow: !Find [authentik_flows.flow, [slug, {{ item.flows.authorization_slug | default('default-provider-authorization-implicit-consent') }}]] + invalidation_flow: !Find [authentik_flows.flow, [slug, {{ item.flows.invalidation_slug | default('default-provider-invalidation-flow') }}]] + + internal_host: "{{ item.internal_host }}" + external_host: "{{ item.external_host }}" + +{% if item.skip_path_regex is defined and item.skip_path_regex|length > 0 %} + skip_path_regex: | +{{ item.skip_path_regex | indent(8, true) }} +{% endif %} + + - model: authentik_core.application + id: app-{{ item.slug }} + identifiers: + slug: {{ item.slug }} + attrs: + name: "{{ item.name | default(item.slug) }}" + slug: {{ item.slug }} + provider: !KeyOf proxy-provider-{{ item.slug }} diff --git a/roles/authentik/templates/blueprints/blueprint-source-entra.yaml.j2 b/roles/authentik/templates/blueprints/blueprint-source-entra.yaml.j2 new file mode 100644 index 0000000..acab07b --- /dev/null +++ b/roles/authentik/templates/blueprints/blueprint-source-entra.yaml.j2 @@ -0,0 +1,40 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "source-entra-{{ item.slug }}" + labels: + blueprints.goauthentik.io/instantiate: "true" + blueprints.goauthentik.io/description: "Microsoft Entra ID OAuth source ({{ item.slug }})" + +entries: + - model: authentik_sources_oauth.oauthsource + id: source-entra-{{ item.slug }} + identifiers: + slug: {{ item.slug }} + attrs: + name: "{{ item.name | default('Microsoft Entra ID') }}" + slug: {{ item.slug }} + + # Authentik’s OAuth sources support vendor-specific types. + # Entra guide calls it “Entra ID OAuth Source”. + provider_type: entraid + + consumer_key: !Env {{ item.client_id_env }} + consumer_secret: !Env {{ item.client_secret_env }} + + scopes: +{% for s in (item.scopes | default(['openid','profile','email'])) %} + - {{ s }} +{% endfor %} + +{% if (item.tenant_mode | default('single')) == 'single' %} + authorization_url: !Format ["https://login.microsoftonline.com/%s/oauth2/v2.0/authorize", !Env {{ item.tenant_id_env }}] + access_token_url: !Format ["https://login.microsoftonline.com/%s/oauth2/v2.0/token", !Env {{ item.tenant_id_env }}] + profile_url: "https://graph.microsoft.com/v1.0/me" + oidc_jwks_url: !Format ["https://login.microsoftonline.com/%s/discovery/v2.0/keys", !Env {{ item.tenant_id_env }}] +{% else %} + authorization_url: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" + access_token_url: "https://login.microsoftonline.com/common/oauth2/v2.0/token" + profile_url: "https://graph.microsoft.com/v1.0/me" + oidc_jwks_url: "https://login.microsoftonline.com/common/discovery/v2.0/keys" +{% endif %} diff --git a/roles/authentik/templates/blueprints/outpost-proxy.yaml.j2 b/roles/authentik/templates/blueprints/outpost-proxy.yaml.j2 new file mode 100644 index 0000000..1aebe6c --- /dev/null +++ b/roles/authentik/templates/blueprints/outpost-proxy.yaml.j2 @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json +version: 1 +metadata: + name: "outpost-{{ item.name }}" + labels: + blueprints.goauthentik.io/instantiate: "true" + +entries: + - model: authentik_outposts.outpost + identifiers: + name: "{{ item.name }}" + attrs: + name: "{{ item.name }}" + type: {{ item.type | default('proxy') }} + service_connection: {{ item.service_connection | default('null') }} + + providers: +{% for p in item.providers %} + - !Find [authentik_providers_proxy.proxyprovider, [name, {{ p }}]] +{% endfor %} + +{% if item.config is defined %} + config: +{% for k, v in item.config.items() %} + {{ k }}: {{ v | tojson }} +{% endfor %} +{% endif %} diff --git a/roles/authentik/templates/docker-compose.yml.j2 b/roles/authentik/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..6daa2a1 --- /dev/null +++ b/roles/authentik/templates/docker-compose.yml.j2 @@ -0,0 +1,97 @@ +services: + postgres: + image: {{ authentik_postgres_image }} + restart: unless-stopped + environment: + POSTGRES_DB: {{ authentik_postgres_db }} + POSTGRES_USER: {{ authentik_postgres_user }} + POSTGRES_PASSWORD: {{ authentik_postgres_password }} + volumes: + - {{ authentik_docker_volume_dir }}/postgresql:/var/lib/postgresql/data + networks: + - {{ authentik_backend_network }} + healthcheck: + test: ["CMD-SHELL", "pg_isready -d {{ authentik_postgres_db }} -U {{ authentik_postgres_user }}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + + server: + image: {{ authentik_image }} + restart: unless-stopped + command: server + healthcheck: + test: ["CMD", "ak", "healthcheck"] + start_period: 30s + interval: 10s + retries: 5 + timeout: 5s + environment: + AUTHENTIK_SECRET_KEY: {{ authentik_secret_key }} + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__NAME: {{ authentik_postgres_db }} + AUTHENTIK_POSTGRESQL__USER: {{ authentik_postgres_user }} + AUTHENTIK_POSTGRESQL__PASSWORD: {{ authentik_postgres_password }} + AUTHENTIK_LOG_LEVEL: {{ authentik_log_level }} + AUTHENTIK_ERROR_REPORTING__ENABLED: "{{ authentik_error_reporting_enabled | lower }}" +{% if authentik_blueprint_env|length > 0 %} +{% for k, v in authentik_blueprint_env.items() %} + {{ k }}: "{{ v }}" +{% endfor %} +{% endif %} + volumes: + - {{ authentik_docker_volume_dir }}/blueprints:/blueprints/custom + - {{ authentik_docker_volume_dir }}/data:/data + - {{ authentik_docker_volume_dir }}/templates:/templates + depends_on: + postgres: + condition: service_healthy + networks: + - {{ authentik_backend_network }} + - {{ authentik_traefik_network }} + labels: + - traefik.enable=true + - traefik.docker.network={{ authentik_traefik_network }} + - traefik.http.routers.{{ authentik_service_name }}.rule=Host(`{{ authentik_domain }}`) +{% if authentik_use_ssl %} + - traefik.http.routers.{{ authentik_service_name }}.entrypoints=websecure + - traefik.http.routers.{{ authentik_service_name }}.tls=true +{% else %} + - traefik.http.routers.{{ authentik_service_name }}.entrypoints=web +{% endif %} + - traefik.http.services.{{ authentik_service_name }}.loadbalancer.server.port={{ authentik_port }} + + worker: + image: {{ authentik_image }} + restart: unless-stopped + command: worker + user: root + environment: + AUTHENTIK_SECRET_KEY: {{ authentik_secret_key }} + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__NAME: {{ authentik_postgres_db }} + AUTHENTIK_POSTGRESQL__USER: {{ authentik_postgres_user }} + AUTHENTIK_POSTGRESQL__PASSWORD: {{ authentik_postgres_password }} + AUTHENTIK_LOG_LEVEL: {{ authentik_log_level }} + AUTHENTIK_ERROR_REPORTING__ENABLED: "{{ authentik_error_reporting_enabled | lower }}" +{% if authentik_blueprint_env|length > 0 %} +{% for k, v in authentik_blueprint_env.items() %} + {{ k }}: "{{ v }}" +{% endfor %} +{% endif %} + volumes: + - {{ authentik_docker_volume_dir }}/data:/data + - {{ authentik_docker_volume_dir }}/certs:/certs + - {{ authentik_docker_volume_dir }}/templates:/templates + - {{ authentik_docker_volume_dir }}/blueprints:/blueprints/custom + depends_on: + postgres: + condition: service_healthy + networks: + - {{ authentik_backend_network }} + +networks: + {{ authentik_backend_network }}: + {{ authentik_traefik_network }}: + external: true diff --git a/roles/authentik/tests/inventory b/roles/authentik/tests/inventory new file mode 100644 index 0000000..03ca42f --- /dev/null +++ b/roles/authentik/tests/inventory @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +localhost + diff --git a/roles/authentik/tests/test.yml b/roles/authentik/tests/test.yml new file mode 100644 index 0000000..862cecd --- /dev/null +++ b/roles/authentik/tests/test.yml @@ -0,0 +1,6 @@ +#SPDX-License-Identifier: MIT-0 +--- +- hosts: localhost + remote_user: root + roles: + - authentik diff --git a/roles/authentik/vars/main.yml b/roles/authentik/vars/main.yml new file mode 100644 index 0000000..498262f --- /dev/null +++ b/roles/authentik/vars/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# vars file for authentik diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index 6a6eabb..57910d9 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -6,6 +6,7 @@ ansible.builtin.apt: update_cache: true cache_valid_time: 3600 + lock_timeout: 180 when: ansible_facts["os_family"] == "Debian" - name: Install required packages for Docker @@ -20,7 +21,6 @@ state: present when: ansible_facts["os_family"] == "Debian" - - name: Install convenience packages ansible.builtin.apt: name: