From f56c6719dab4f6706c14816d936319b95f47aaa5 Mon Sep 17 00:00:00 2001 From: ahmza Date: Fri, 16 Oct 2026 16:03:02 +0000 Subject: [PATCH] Stage Authentik database and backups --- apps/authentik.yaml | 32 ++++++++ apps/authentik/Chart.yaml | 16 ++++ apps/authentik/templates/data-pvc.yaml | 18 ++++ apps/authentik/templates/postgresql.yaml | 96 ++++++++++++++++++++++ apps/authentik/templates/secrets.sops.yaml | 30 +++++++ apps/authentik/values.yaml | 11 +++ 6 files changed, 203 insertions(+) create mode 100644 apps/authentik.yaml create mode 100644 apps/authentik/Chart.yaml create mode 100644 apps/authentik/templates/data-pvc.yaml create mode 100644 apps/authentik/templates/postgresql.yaml create mode 100644 apps/authentik/templates/secrets.sops.yaml create mode 100644 apps/authentik/values.yaml diff --git a/apps/authentik.yaml b/apps/authentik.yaml new file mode 100644 index 0000000..667814c --- /dev/null +++ b/apps/authentik.yaml @@ -0,0 +1,32 @@ +# Authentik is deployed from its official Helm chart, while this repository's +# wrapper chart also owns its PostgreSQL cluster, backups, and persistent data. +# The database is created first with Authentik disabled so the existing Docker +# database can be restored before any new server or worker touches it. +# +# Deliberately NO resources-finalizer.argocd.argoproj.io here. This Application +# owns identity data, and deleting its Git entry must not cascade into deleting +# PostgreSQL or Authentik's uploaded files. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: authentik + namespace: argocd +spec: + project: default + + source: + repoURL: https://tea.ahmza.com/ahmza.com/k8s-starter-pack.git + targetRevision: main + path: apps/authentik + + destination: + server: https://kubernetes.default.svc + namespace: authentik + + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true diff --git a/apps/authentik/Chart.yaml b/apps/authentik/Chart.yaml new file mode 100644 index 0000000..72930ab --- /dev/null +++ b/apps/authentik/Chart.yaml @@ -0,0 +1,16 @@ +# The upstream Authentik chart is initially disabled. This wrapper first +# creates PostgreSQL, backup configuration, and persistent file storage so the +# existing installation can be restored before Authentik starts. +apiVersion: v2 +name: authentik-app +description: Deploys Authentik with CloudNativePG and off-cluster backups +version: 0.1.0 +type: application + +dependencies: + - name: authentik + # Match the source Docker deployment for the migration. Upgrade only after + # the restored installation has been verified in Kubernetes. + version: 2026.2.1 + repository: https://charts.goauthentik.io + condition: authentikDeployment.enabled diff --git a/apps/authentik/templates/data-pvc.yaml b/apps/authentik/templates/data-pvc.yaml new file mode 100644 index 0000000..3349224 --- /dev/null +++ b/apps/authentik/templates/data-pvc.yaml @@ -0,0 +1,18 @@ +# Authentik keeps uploaded icons and branding under /data. The PostgreSQL dump +# does not include these files, so this separate Longhorn volume is restored +# from the source VM's data/ directory before Authentik is enabled. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: authentik-data + namespace: {{ .Release.Namespace }} + annotations: + # Uploaded files are identity-service state. Never let Argo CD prune the + # volume automatically because a template was renamed or removed. + argocd.argoproj.io/sync-options: Prune=false +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/apps/authentik/templates/postgresql.yaml b/apps/authentik/templates/postgresql.yaml new file mode 100644 index 0000000..283d864 --- /dev/null +++ b/apps/authentik/templates/postgresql.yaml @@ -0,0 +1,96 @@ +# Backups live outside the cluster so a Longhorn or cluster-wide failure does +# not remove both PostgreSQL and its recovery data. Credentials are produced by +# the encrypted SopsSecret in this chart. +apiVersion: barmancloud.cnpg.io/v1 +kind: ObjectStore +metadata: + name: authentik-backups + namespace: {{ .Release.Namespace }} +spec: + retentionPolicy: 30d + configuration: + destinationPath: s3://ahmza-talos-cnpg-backups/authentik/ + endpointURL: https://s3.eu-central-003.backblazeb2.com + s3Credentials: + accessKeyId: + name: backblaze-b2-credentials + key: ACCESS_KEY_ID + secretAccessKey: + name: backblaze-b2-credentials + key: ACCESS_SECRET_KEY + region: + name: backblaze-b2-credentials + key: AWS_REGION + wal: + compression: gzip + maxParallel: 2 + data: + compression: gzip + jobs: 2 + # Backblaze implements the S3 API but does not require every optional AWS + # checksum behavior. These settings avoid incompatible optional checksums. + instanceSidecarConfiguration: + env: + - name: AWS_REQUEST_CHECKSUM_CALCULATION + value: when_required + - name: AWS_RESPONSE_CHECKSUM_VALIDATION + value: when_required +--- +# One PostgreSQL instance is enough initially: Longhorn replicates its volume +# across workers and can reattach it after a node failure. A second database +# instance can be added later if shorter failover time justifies another full +# copy of the data and WAL. +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: authentik-postgres + namespace: {{ .Release.Namespace }} + annotations: + # Argo CD may update this database but must never delete it automatically + # merely because a manifest or parent Application was removed from Git. + argocd.argoproj.io/sync-options: Prune=false +spec: + instances: 1 + imageName: >- + ghcr.io/cloudnative-pg/postgresql:16.13-202603020816-standard-trixie + + bootstrap: + initdb: + database: authentik + owner: authentik + + storage: + # The default StorageClass is Longhorn. Omitting storageClass here keeps the + # database on that established replicated storage path. + size: 10Gi + + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: "2" + memory: 2Gi + + plugins: + - name: barman-cloud.cloudnative-pg.io + isWALArchiver: true + parameters: + barmanObjectName: authentik-backups +--- +# CloudNativePG cron expressions have six fields; the leading zero is seconds. +# WAL is archived continuously, while this creates a full base backup nightly. +apiVersion: postgresql.cnpg.io/v1 +kind: ScheduledBackup +metadata: + name: authentik-postgres-daily + namespace: {{ .Release.Namespace }} +spec: + schedule: "0 0 2 * * *" + immediate: false + backupOwnerReference: self + cluster: + name: authentik-postgres + method: plugin + pluginConfiguration: + name: barman-cloud.cloudnative-pg.io diff --git a/apps/authentik/templates/secrets.sops.yaml b/apps/authentik/templates/secrets.sops.yaml new file mode 100644 index 0000000..8126162 --- /dev/null +++ b/apps/authentik/templates/secrets.sops.yaml @@ -0,0 +1,30 @@ +apiVersion: isindir.github.com/v1alpha3 +kind: SopsSecret +metadata: + name: authentik-secrets + namespace: authentik +spec: + secretTemplates: + - name: authentik-secrets + data: + AUTHENTIK_SECRET_KEY: ENC[AES256_GCM,data:xwd512Zty1VmOcc79UK2MxgLG5PaSApHhhwZRkqNz2w6HbLMSx+QvbODTfIZ0pq+HfQHxQMTY5FeX7t6TKR9toI5tG6B5202Bf85U9Lph4ssVfGC7fU/2WBsdELmtJIxxPjrzpcoQBfybOaR,iv:/J5e8Ej1KmuiEaOm8lZkikx7eStmScUA6lc0civVpdY=,tag:+gxczl/b3K4KnF8LcSkHKQ==,type:str] + - name: backblaze-b2-credentials + data: + ACCESS_KEY_ID: ENC[AES256_GCM,data:4FjHGgdeDwbA22ekQr1jv2qDn+5xxEMqgB1wWanL8nXvt8EV,iv:csE6cZ0ifFFC0bq12eMGBwSuchH0u1lqbXflywoR9FY=,tag:xMhjAvxicV1nUpfBfJAKBw==,type:str] + ACCESS_SECRET_KEY: ENC[AES256_GCM,data:XWHpbgZWbfl3REQDraRMUemcRvoACdaE2hjgkcYFgpZGkSZQ3jO7/fg4tDo=,iv:bGvTZy9N/ooxykqki0WkaUMI5qORbceSjprLnUu2k1A=,tag:67LlMIj+wvhj++Li/WtEAw==,type:str] + AWS_REGION: ENC[AES256_GCM,data:TL4IGaKv2/LD1/PTL1JY0l/J+N8=,iv:JZtM2V0nwimMJaR5o7qK9Rx1FC6jTuFbknU/2qBrwYs=,tag:tUgyYeAYjEGxTAlnky679w==,type:str] +sops: + age: + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4WDgwRkExNHhXa05hSkcy + ZVVUam44a0pVR2hTZk5oOTdWdzkvSGlWODJVCnp6REpkUWVBV2g0MXNVKzdCVG1t + aE9YQ25icitBWGJqQ3NtUjd1cCtRUk0KLS0tIHNPeFVkeFVGUlYxT3Nhd2UrVnl2 + NlhTZFV1YVRSM2JJYk1WRnRiUFppMXMKtqNp3OzKTeBKWXos0+wUmn6YGEDXubtc + UPX7lOkLI6qaKg8+3HZV3x9yKgtaT32WF9faMBQhvxFMrhRR3UTTlQ== + -----END AGE ENCRYPTED FILE----- + recipient: age1udejf5qa66rd6yvj5r8dz0fjnqfh0quf4t339c3cpqr26mkx2ydq3zel07 + encrypted_regex: ^(data|stringData)$ + lastmodified: "2026-10-16T15:59:11Z" + mac: ENC[AES256_GCM,data:bqT+3/x/1DAgRRxjIXlxwNLiXT2f0rD7WxUk6RGBikOD0sZKBvCZVh4qTEVUIf2U6siZBgue39Gqa5eBlCCzx+rq/JxbKdsNd5klythOzmuaKSlOaIimSZLR9Ye1KJMGPkZI4G7eE5CAM17WJ5MMZDkhP9CtscRPEQ/AgHbVUSg=,iv:JqtI7n6uMkQ9lKr4oGGEA6czFtvoDrG510aLmltCdmI=,tag:1LU4a4Mlrxh8btQw4MY0eQ==,type:str] + version: 3.13.3 diff --git a/apps/authentik/values.yaml b/apps/authentik/values.yaml new file mode 100644 index 0000000..ee17fbd --- /dev/null +++ b/apps/authentik/values.yaml @@ -0,0 +1,11 @@ +# Migration safety switch. The first sync provisions only PostgreSQL, backups, +# encrypted Secrets, and the /data volume. Set this to true only after the +# source database and files have been restored. +authentikDeployment: + enabled: false + +# Values below are passed to the upstream chart once the switch above is true. +authentik: + # CloudNativePG supplies PostgreSQL; do not deploy the bundled database. + postgresql: + enabled: false