Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ix-dev/community/authentik/app.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
app_version: 2025.10.3
app_version: 2025.12.0
capabilities: []
categories:
- authentication
Expand Down Expand Up @@ -41,4 +41,4 @@ sources:
- https://github.com/goauthentik/authentik
title: Authentik
train: community
version: 1.0.58
version: 1.1.0
5 changes: 5 additions & 0 deletions ix-dev/community/authentik/app_migrations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ migrations:
max_version: 1.0.45
target:
min_version: 1.0.46
- file: enable_deprecated_media
from:
max_version: 1.0.58
target:
min_version: 1.1.0
11 changes: 11 additions & 0 deletions ix-dev/community/authentik/deprecations.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- scope: "partial"

deprecated_date: "2025-12-22"
removal_date: "2026-03-22"
reason: Upstream has changed the storage structure.

partial_details:
feature: "Deprecated Media Storage"
description: "The media storage has been merged into a single data storage path."
steps:
- "See https://github.com/truenas/apps/pull/3928 for migration instructions"
3 changes: 2 additions & 1 deletion ix-dev/community/authentik/ix_values.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
images:
image:
repository: ghcr.io/goauthentik/server
tag: "2025.10.3"
tag: "2025.12.0"
container_utils_image:
repository: ixsystems/container-utils
tag: 1.0.2
Expand All @@ -22,3 +22,4 @@ consts:
postgres_container_name: postgres
db_user: authentik
db_name: authentik
data_base_path: /data
19 changes: 19 additions & 0 deletions ix-dev/community/authentik/migrations/enable_deprecated_media
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/python3

import os
import sys
import yaml


def migrate(values):
values["storage"]["uses_deprecated_media"] = True
return values


if __name__ == "__main__":
if len(sys.argv) != 2:
exit(1)

if os.path.exists(sys.argv[1]):
with open(sys.argv[1], "r") as f:
print(yaml.dump(migrate(yaml.safe_load(f.read()))))
93 changes: 87 additions & 6 deletions ix-dev/community/authentik/questions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,19 @@ questions:
schema:
type: dict
attrs:
- variable: uses_deprecated_media
label: Use Deprecated Media Storage
description: |
Cannot be used in new installs.</br>
See https://github.com/truenas/apps/pull/3928
schema:
type: boolean
default: false
- variable: media
label: Authentik Media Storage
description: The path to store Authentik Media.
label: Media Storage (DEPRECATED)
schema:
type: dict
show_if: [["uses_deprecated_media", "=", true]]
attrs:
- variable: type
label: Type
Expand Down Expand Up @@ -347,9 +355,83 @@ questions:
type: hostpath
show_if: [["acl_enable", "=", false]]
required: true
- variable: data
label: Data Storage
schema:
type: dict
attrs:
- variable: type
label: Type
description: |
ixVolume: Is dataset created automatically by the system.</br>
Host Path: Is a path that already exists on the system.
schema:
type: string
required: true
default: "ix_volume"
enum:
- value: "host_path"
description: Host Path (Path that already exists on the system)
- value: "ix_volume"
description: ixVolume (Dataset created automatically by the system)
- variable: ix_volume_config
label: ixVolume Configuration
description: The configuration for the ixVolume dataset.
schema:
type: dict
show_if: [["type", "=", "ix_volume"]]
$ref:
- "normalize/ix_volume"
attrs:
- variable: acl_enable
label: Enable ACL
description: Enable ACL for the storage.
schema:
type: boolean
default: false
- variable: dataset_name
label: Dataset Name
description: The name of the dataset to use for storage.
schema:
type: string
required: true
hidden: true
default: "data"
- variable: acl_entries
label: ACL Configuration
schema:
type: dict
show_if: [["acl_enable", "=", true]]
attrs: []
- variable: host_path_config
label: Host Path Configuration
schema:
type: dict
show_if: [["type", "=", "host_path"]]
attrs:
- variable: acl_enable
label: Enable ACL
description: Enable ACL for the storage.
schema:
type: boolean
default: false
- variable: acl
label: ACL Configuration
schema:
type: dict
show_if: [["acl_enable", "=", true]]
attrs: []
$ref:
- "normalize/acl"
- variable: path
label: Host Path
description: The host path to use for storage.
schema:
type: hostpath
show_if: [["acl_enable", "=", false]]
required: true
- variable: templates
label: Authentik Templates Storage
description: The path to store Authentik Templates.
label: Templates Storage
schema:
type: dict
attrs:
Expand Down Expand Up @@ -424,8 +506,7 @@ questions:
show_if: [["acl_enable", "=", false]]
required: true
- variable: certs
label: Authentik Certs Storage
description: The path to store Authentik Certs.
label: Certs Storage
schema:
type: dict
attrs:
Expand Down
152 changes: 74 additions & 78 deletions ix-dev/community/authentik/templates/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,108 +5,104 @@
{% set perm_container = tpl.deps.perms(values.consts.perms_container_name) %}
{% set perm_config = {"uid": values.run_as.user, "gid": values.run_as.group, "mode": "check"} %}


{% if values.storage.uses_deprecated_media %}
{% set is_install = values.get("ix_context", {}).get("is_install", False) %}
{% if is_install %}
{% do tpl.funcs.fail("Cannot use deprecated media storage in new installs. Please disable it and try again.") %}
{% endif %}

{% do tpl.notes.add_deprecation("Using the deprecated media storage, see https://github.com/truenas/apps/pull/3928 for migration instructions") %}
{% endif %}

{% set pg_config = {
"user": values.consts.db_user,
"password": values.authentik.db_password,
"database": values.consts.db_name,
"volume": values.storage.postgres_data,
} %}
{% set postgres = tpl.deps.postgres(
values.consts.postgres_container_name,
values.authentik.postgres_image_selector,
pg_config, perm_container
) %}

{% do server.set_command(["server"]) %}
{% do worker.set_command(["worker"]) %}

{% do server.set_user(values.run_as.user, values.run_as.group) %}
{% do worker.set_user(values.run_as.user, values.run_as.group) %}

{% do server.healthcheck.set_custom_test("/lifecycle/ak healthcheck") %}
{% do worker.healthcheck.set_custom_test("/lifecycle/ak healthcheck") %}

{% do server.depends.add_dependency(values.consts.postgres_container_name, "service_healthy") %}
{% do worker.depends.add_dependency(values.consts.postgres_container_name, "service_healthy") %}

{% do server.environment.add_env("AUTHENTIK_LISTEN__HTTP", "0.0.0.0:%d"|format(values.network.http_port.port_number)) %}
{% do server.environment.add_env("AUTHENTIK_LISTEN__HTTPS", "0.0.0.0:%d"|format(values.network.https_port.port_number)) %}

{% do server.environment.add_env("AUTHENTIK_POSTGRESQL__HOST", values.consts.postgres_container_name) %}
{% do worker.environment.add_env("AUTHENTIK_POSTGRESQL__HOST", values.consts.postgres_container_name) %}

{% do server.environment.add_env("AUTHENTIK_POSTGRESQL__PORT", 5432) %}
{% do worker.environment.add_env("AUTHENTIK_POSTGRESQL__PORT", 5432) %}

{% do server.environment.add_env("AUTHENTIK_POSTGRESQL__NAME", values.consts.db_name) %}
{% do worker.environment.add_env("AUTHENTIK_POSTGRESQL__NAME", values.consts.db_name) %}

{% do server.environment.add_env("AUTHENTIK_POSTGRESQL__USER", values.consts.db_user) %}
{% do worker.environment.add_env("AUTHENTIK_POSTGRESQL__USER", values.consts.db_user) %}

{% do server.environment.add_env("AUTHENTIK_POSTGRESQL__PASSWORD", values.authentik.db_password) %}
{% do worker.environment.add_env("AUTHENTIK_POSTGRESQL__PASSWORD", values.authentik.db_password) %}

{% do server.environment.add_env("AUTHENTIK_SECRET_KEY", values.authentik.secret_key) %}
{% do worker.environment.add_env("AUTHENTIK_SECRET_KEY", values.authentik.secret_key) %}

{% if values.authentik.setup_email %}
{% do server.environment.add_env("AUTHENTIK_EMAIL__HOST", values.authentik.email.host) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__HOST", values.authentik.email.host) %}

{% do server.environment.add_env("AUTHENTIK_EMAIL__PORT", values.authentik.email.port) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__PORT", values.authentik.email.port) %}

{% do server.environment.add_env("AUTHENTIK_EMAIL__FROM", values.authentik.email.from) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__FROM", values.authentik.email.from) %}

{% do server.environment.add_env("AUTHENTIK_EMAIL__USERNAME", values.authentik.email.username) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__USERNAME", values.authentik.email.username) %}
{% set postgres = tpl.deps.postgres(values.consts.postgres_container_name, values.authentik.postgres_image_selector, pg_config, perm_container) %}

{% set containers = [server, worker] %}
{% for c in containers %}
{% do c.set_user(values.run_as.user, values.run_as.group) %}
{% do c.healthcheck.set_custom_test(["CMD", "/lifecycle/ak", "healthcheck"]) %}
{% do c.depends.add_dependency(values.consts.postgres_container_name, "service_healthy") %}

{% do c.environment.add_env("AUTHENTIK_POSTGRESQL__HOST", values.consts.postgres_container_name) %}
{% do c.environment.add_env("AUTHENTIK_POSTGRESQL__PORT", 5432) %}
{% do c.environment.add_env("AUTHENTIK_POSTGRESQL__NAME", values.consts.db_name) %}
{% do c.environment.add_env("AUTHENTIK_POSTGRESQL__USER", values.consts.db_user) %}
{% do c.environment.add_env("AUTHENTIK_POSTGRESQL__PASSWORD", values.authentik.db_password) %}
{% do c.environment.add_env("AUTHENTIK_SECRET_KEY", values.authentik.secret_key) %}

{% do c.environment.add_env("AUTHENTIK_STORAGE__BACKEND", "file") %}
{% do c.environment.add_env("AUTHENTIK_STORAGE__MEDIA__BACKEND", "file") %}
{% do c.environment.add_env("AUTHENTIK_STORAGE__REPORTS__BACKEND", "file") %}

{% do c.environment.add_env("AUTHENTIK_STORAGE__FILE__PATH", values.consts.data_base_path) %}
{% do c.environment.add_env("AUTHENTIK_STORAGE__FILE__MEDIA__PATH", "%s/media"|format(values.consts.data_base_path)) %}
{% do c.environment.add_env("AUTHENTIK_STORAGE__FILE__REPORTS__PATH", "%s/reports"|format(values.consts.data_base_path)) %}

{% if values.authentik.setup_email %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__HOST", values.authentik.email.host) %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__PORT", values.authentik.email.port) %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__FROM", values.authentik.email.from) %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__USERNAME", values.authentik.email.username) %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__PASSWORD", values.authentik.email.password) %}

{% if values.authentik.email.security == "ssl" %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__USE_SSL", true) %}
{% elif values.authentik.email.security == "tls" %}
{% do c.environment.add_env("AUTHENTIK_EMAIL__USE_TLS", true) %}
{% endif %}
{% endif %}

{% do server.environment.add_env("AUTHENTIK_EMAIL__PASSWORD", values.authentik.email.password) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__PASSWORD", values.authentik.email.password) %}
{% do c.environment.add_user_envs(values.authentik.additional_envs) %}

{% if values.authentik.email.security == "ssl" %}
{% do server.environment.add_env("AUTHENTIK_EMAIL__USE_SSL", true) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__USE_SSL", true) %}
{% elif values.authentik.email.security == "tls" %}
{% do server.environment.add_env("AUTHENTIK_EMAIL__USE_TLS", true) %}
{% do worker.environment.add_env("AUTHENTIK_EMAIL__USE_TLS", true) %}
{% do c.add_storage(values.consts.data_base_path, values.storage.data) %}
{% do c.add_storage("/templates", values.storage.templates) %}
{% do c.add_storage("/certs", values.storage.certs) %}
{% if values.storage.uses_deprecated_media %}
{# FIXME: Deprecated, to be removed in a future release #}
{% do c.add_storage("%s/media"|format(values.consts.data_base_path), values.storage.media) %}
{% endif %}
{% endif %}

{% do server.environment.add_user_envs(values.authentik.additional_envs) %}
{% do worker.environment.add_user_envs(values.authentik.additional_envs) %}

{% do server.add_port(values.network.http_port) %}
{% do server.add_port(values.network.https_port) %}
{% for store in values.storage.additional_storage %}
{% do c.add_storage(store.mount_path, store) %}
{% endfor %}
{% endfor %}

{# Worker #}
{% do worker.set_command(["worker"]) %}
{% if values.authentik.mount_docker_socket %}
{% do worker.add_docker_socket(read_only=False) %}
{% endif %}

{% do server.add_storage("/media", values.storage.media) %}
{% do worker.add_storage("/media", values.storage.media) %}
{% do perm_container.add_or_skip_action("media", values.storage.media, perm_config) %}
{# Server #}
{% do server.set_command(["server"]) %}
{% do server.environment.add_env("AUTHENTIK_LISTEN__HTTP", "0.0.0.0:%d"|format(values.network.http_port.port_number)) %}
{% do server.environment.add_env("AUTHENTIK_LISTEN__HTTPS", "0.0.0.0:%d"|format(values.network.https_port.port_number)) %}
{% do server.add_port(values.network.http_port) %}
{% do server.add_port(values.network.https_port) %}

{% do server.add_storage("/templates", values.storage.templates) %}
{% do worker.add_storage("/templates", values.storage.templates) %}
{# Permissions #}
{% do perm_container.add_or_skip_action("data", values.storage.data, perm_config) %}
{% do perm_container.add_or_skip_action("templates", values.storage.templates, perm_config) %}

{% do server.add_storage("/certs", values.storage.certs) %}
{% do worker.add_storage("/certs", values.storage.certs) %}
{% do perm_container.add_or_skip_action("certs", values.storage.certs, perm_config) %}

{% if values.storage.uses_deprecated_media %}
{# FIXME: Deprecated, to be removed in a future release #}
{% do perm_container.add_or_skip_action("media", values.storage.media, perm_config) %}
{% endif %}
{% for store in values.storage.additional_storage %}
{% do server.add_storage(store.mount_path, store) %}
{% do worker.add_storage(store.mount_path, store) %}
{% do perm_container.add_or_skip_action(store.mount_path, store, perm_config) %}
{% endfor %}

{% if perm_container.has_actions() %}
{% do perm_container.activate() %}
{% do server.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% do worker.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% for c in containers %}
{% do c.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% endfor %}
{% do postgres.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% endif %}

Expand Down
Loading
Loading