From 1ec6f794e6f77ec684d4b843b0962642723d2e66 Mon Sep 17 00:00:00 2001 From: Axel Lender Date: Wed, 3 Dec 2025 21:26:07 +0100 Subject: [PATCH] feat(postgresql): Add template support for existing secrets Signed-off-by: Axel Lender --- docs/existing-secrets.md | 137 ++++++++++++++++++ .../values-postgresql.yaml.gotmpl | 8 +- .../default/existing_secrets.yaml.gotmpl | 6 + 3 files changed, 150 insertions(+), 1 deletion(-) diff --git a/docs/existing-secrets.md b/docs/existing-secrets.md index 97e8022f..38b72f21 100644 --- a/docs/existing-secrets.md +++ b/docs/existing-secrets.md @@ -16,6 +16,7 @@ This document covers how to utilise existing secrets and special requirements. T * [MinIO](#minio) * [Notes](#notes) * [OpenProject](#openproject) + * [PostgreSQL](#postgresql) * [XWiki](#xwiki) @@ -206,6 +207,142 @@ stringData: OPENPROJECT_SMTP__PASSWORD: {{ .Values.secrets.postfix.opendeskSystemPassword | quote }} ``` +## PostgreSQL + +In order to initialise PostgreSQL with databases, users and credentials existing secrets are expected to contain `.sql` files. + +The expected format for the databases is as follows: + +```yaml +stringData: + init-db-keycloak.sql: | + SELECT 'CREATE DATABASE keycloak' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'keycloak')\gexec + ALTER DATABASE keycloak OWNER TO keycloak_user; + GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak_user; + init-db-keycloakExtension.sql: | + SELECT 'CREATE DATABASE keycloak_extensions' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'keycloak_extensions')\gexec + ALTER DATABASE keycloak_extensions OWNER TO keycloak_extensions_user; + GRANT ALL PRIVILEGES ON DATABASE keycloak_extensions TO keycloak_extensions_user; + init-db-notes.sql.sql: | + SELECT 'CREATE DATABASE notes' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'notes')\gexec + ALTER DATABASE notes OWNER TO notes_user; + GRANT ALL PRIVILEGES ON DATABASE notes TO notes_user; + init-db-openproject.sql: | + SELECT 'CREATE DATABASE openproject' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'openproject')\gexec + ALTER DATABASE openproject OWNER TO openproject_user; + GRANT ALL PRIVILEGES ON DATABASE openproject TO openproject_user; + init-db-synapse.sql: | + SELECT 'CREATE DATABASE matrix ENCODING ''UTF8'' LC_COLLATE=''C'' LC_CTYPE=''C'' template=template0' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'matrix')\gexec + ALTER DATABASE matrix OWNER TO matrix_user; + GRANT ALL PRIVILEGES ON DATABASE matrix TO matrix_user; + init-db-umsGuardianManagementApi.sql: | + SELECT 'CREATE DATABASE guardianmanagementapi' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'guardianmanagementapi')\gexec + ALTER DATABASE guardianmanagementapi OWNER TO guardianmanagementapi_user; + GRANT ALL PRIVILEGES ON DATABASE guardianmanagementapi TO guardianmanagementapi_user; + init-db-umsNotificationsApi.sql: | + SELECT 'CREATE DATABASE notificationsapi' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'notificationsapi')\gexec + ALTER DATABASE notificationsapi OWNER TO notificationsapi_user; + GRANT ALL PRIVILEGES ON DATABASE notificationsapi TO notificationsapi_user; + init-db-umsSelfservice.sql: | + SELECT 'CREATE DATABASE selfservice' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'selfservice')\gexec + ALTER DATABASE selfservice OWNER TO selfservice_user; + GRANT ALL PRIVILEGES ON DATABASE selfservice TO selfservice_user; + init-db-nextcloud.sql: | + SELECT 'CREATE DATABASE nextcloud' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'nextcloud')\gexec + ALTER DATABASE nextcloud OWNER TO nextcloud_user; + GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud_user; + init-db-xwiki.sql: | + SELECT 'CREATE DATABASE xwiki ENCODING ''UNICODE'' template=template0' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'xwiki')\gexec + ALTER DATABASE xwiki OWNER TO xwiki_user; + GRANT ALL PRIVILEGES ON DATABASE xwiki TO xwiki_user; +``` + +For the user and credentials the following format is expected: + +```yaml +stringData: + init-user-keycloak.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'keycloak_user') THEN + ALTER ROLE "keycloak_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.keycloakUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "keycloak_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.keycloakUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-notes.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'notes_user') THEN + ALTER ROLE "notes_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.notesUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "notes_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.notesUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-openproject.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'openproject_user') THEN + ALTER ROLE "openproject_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.openprojectUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "openproject_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.openprojectUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-keycloakExtension.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'keycloak_extensions_user') THEN + ALTER ROLE "keycloak_extensions_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.keycloakExtensionUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "keycloak_extensions_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.keycloakExtensionUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-synapse.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'matrix_user') THEN + ALTER ROLE "matrix_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.matrixUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "matrix_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.matrixUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-umsNotificationsApi.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'notificationsapi_user') THEN + ALTER ROLE "notificationsapi_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsNotificationsApiUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "notificationsapi_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsNotificationsApiUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-umsGuardianManagementApi.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'guardianmanagementapi_user') THEN + ALTER ROLE "guardianmanagementapi_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsGuardianManagementApiUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "guardianmanagementapi_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsGuardianManagementApiUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-umsSelfservice.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'selfservice_user') THEN + ALTER ROLE "selfservice_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsSelfserviceUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "selfservice_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.umsSelfserviceUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-nextcloud.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'nextcloud_user') THEN + ALTER ROLE "nextcloud_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.nextcloudUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "nextcloud_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.nextcloudUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ + init-user-xwiki.sql: | + DO $$BEGIN + IF EXISTS (SELECT FROM pg_user WHERE usename = 'xwiki_user') THEN + ALTER ROLE "xwiki_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.xwikiUser | squote }} CONNECTION LIMIT 100; + ELSE + CREATE ROLE "xwiki_user" WITH LOGIN ENCRYPTED PASSWORD {{ .Values.secrets.postgresql.xwikiUser | squote }} CONNECTION LIMIT 100; + END IF; + END$$ +``` + ## XWiki Properties listed in the file of the existing secret will overwrite plain values. diff --git a/helmfile/apps/services-external/values-postgresql.yaml.gotmpl b/helmfile/apps/services-external/values-postgresql.yaml.gotmpl index 447a0c7a..d694261c 100644 --- a/helmfile/apps/services-external/values-postgresql.yaml.gotmpl +++ b/helmfile/apps/services-external/values-postgresql.yaml.gotmpl @@ -80,6 +80,7 @@ job: password: {{ .Values.secrets.postgresql.xwikiUser | quote }} connectionLimit: {{ .Values.databases.xwiki.connectionLimit | default .Values.databases.defaults.userConnectionLimit }} {{ end }} + usersExistingSecret: {{ .Values.existingSecrets.postgresql.users | quote }} databases: - name: {{ .Values.databases.keycloak.name | quote }} user: {{ .Values.databases.keycloak.username | quote }} @@ -107,6 +108,7 @@ job: user: {{ .Values.databases.xwiki.username | quote }} additionalParams: "ENCODING 'UNICODE' template=template0" {{ end }} + databasesExistingSecret: {{ .Values.existingSecrets.postgresql.databases | quote }} persistence: size: {{ .Values.persistence.storages.postgresql.size | quote }} @@ -123,7 +125,11 @@ podAnnotations: postgres: user: "postgres" - password: {{ .Values.secrets.postgresql.postgresUser | quote }} + password: + value: {{ .Values.secrets.postgresql.postgresUser | quote }} + existingSecret: + name: {{ .Values.existingSecrets.postgresql.rootPassword.name | quote }} + key: {{ .Values.existingSecrets.postgresql.rootPassword.key | quote }} resources: {{ .Values.resources.postgresql | toYaml | nindent 2 }} diff --git a/helmfile/environments/default/existing_secrets.yaml.gotmpl b/helmfile/environments/default/existing_secrets.yaml.gotmpl index 93c3ee57..dec2350f 100644 --- a/helmfile/environments/default/existing_secrets.yaml.gotmpl +++ b/helmfile/environments/default/existing_secrets.yaml.gotmpl @@ -239,6 +239,12 @@ existingSecrets: migrationsMasterPassword: name: ~ key: ~ + postgresql: + rootPassword: + name: ~ + key: ~ + databases: ~ + users: ~ postfix: opendeskSystem: password: