From c632968e499dcdbd3de01a70d322e6ece5b6fe8a Mon Sep 17 00:00:00 2001 From: sHa Date: Wed, 18 Mar 2026 14:17:39 +0200 Subject: [PATCH] feat: Add PostgreSQL support with initialization job and configuration options --- home-assistant/Chart.yaml | 2 +- home-assistant/templates/db-init-job.yaml | 92 +++++++++++++++++++++++ home-assistant/templates/deployment.yaml | 31 ++++++++ home-assistant/values.yaml | 24 ++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 home-assistant/templates/db-init-job.yaml diff --git a/home-assistant/Chart.yaml b/home-assistant/Chart.yaml index 0fc45f6..20f3f5b 100644 --- a/home-assistant/Chart.yaml +++ b/home-assistant/Chart.yaml @@ -5,5 +5,5 @@ type: application annotations: version-source: github-release:home-assistant/core version-pattern: "s|^v||" -version: 0.1.0 +version: 0.1.1 appVersion: "2026.3.1" diff --git a/home-assistant/templates/db-init-job.yaml b/home-assistant/templates/db-init-job.yaml new file mode 100644 index 0000000..96f11b1 --- /dev/null +++ b/home-assistant/templates/db-init-job.yaml @@ -0,0 +1,92 @@ +{{- if .Values.dbInit.enabled -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "home-assistant.fullname" . }}-db-init + {{- if .Values.namespaceOverride }} + namespace: {{ .Values.namespaceOverride }} + {{- end }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation + labels: + {{- include "home-assistant.labels" . | nindent 4 }} +spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: db-init + image: {{ .Values.dbInit.image }} + command: + - /bin/sh + - -c + - | + set -ex + # Set admin user from secret or values + if [ -n "$ADMIN_USER_FROM_SECRET" ]; then + PGUSER=$ADMIN_USER_FROM_SECRET + else + PGUSER={{ .Values.postgres.adminUser | quote }} + fi + export PGUSER + + # Wait for PostgreSQL to be ready + until pg_isready -h $PGHOST -p $PGPORT -U $PGUSER; do + echo "Waiting for PostgreSQL to be ready..." + sleep 2 + done + + # Connect as admin user + export PGPASSWORD=$POSTGRES_ADMIN_PASSWORD + + # Create or update database user password + echo "Ensuring $POSTGRES_USER user exists with correct password..." + if psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='$POSTGRES_USER'" | grep -q 1; then + psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "ALTER USER \"$POSTGRES_USER\" WITH PASSWORD '${HA_PASSWORD}';" + else + psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "CREATE USER \"$POSTGRES_USER\" WITH PASSWORD '${HA_PASSWORD}';" + fi + + # Create database if it doesn't exist + echo "Creating $POSTGRES_DB database..." + psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -tc "SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB'" | grep -q 1 || \ + psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "CREATE DATABASE \"$POSTGRES_DB\" OWNER \"$POSTGRES_USER\";" + + # Grant all privileges + echo "Granting privileges..." + psql -h $PGHOST -p $PGPORT -U $PGUSER -d "$POSTGRES_DB" -c "GRANT ALL PRIVILEGES ON DATABASE \"$POSTGRES_DB\" TO \"$POSTGRES_USER\";" + psql -h $PGHOST -p $PGPORT -U $PGUSER -d "$POSTGRES_DB" -c "GRANT ALL PRIVILEGES ON SCHEMA public TO \"$POSTGRES_USER\";" + psql -h $PGHOST -p $PGPORT -U $PGUSER -d "$POSTGRES_DB" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO \"$POSTGRES_USER\";" + psql -h $PGHOST -p $PGPORT -U $PGUSER -d "$POSTGRES_DB" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO \"$POSTGRES_USER\";" + + echo "Database initialization complete." + env: + - name: PGHOST + value: {{ .Values.postgres.host | quote }} + - name: PGPORT + value: {{ .Values.postgres.port | quote }} + - name: POSTGRES_DB + value: {{ .Values.postgres.db | quote }} + - name: POSTGRES_USER + value: {{ .Values.postgres.user | quote }} + - name: POSTGRES_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.postgres.adminSecret | default .Values.postgres.existingSecret }} + key: {{ .Values.postgres.adminSecretKey }} + {{- if .Values.postgres.adminUserKey }} + - name: ADMIN_USER_FROM_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.postgres.adminSecret | default .Values.postgres.existingSecret }} + key: {{ .Values.postgres.adminUserKey }} + {{- end }} + - name: HA_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.postgres.existingSecret }} + key: {{ .Values.postgres.passwordKey }} + resources: + {{- toYaml .Values.dbInit.resources | nindent 12 }} +{{- end }} diff --git a/home-assistant/templates/deployment.yaml b/home-assistant/templates/deployment.yaml index 5dbd04d..aa162d5 100644 --- a/home-assistant/templates/deployment.yaml +++ b/home-assistant/templates/deployment.yaml @@ -25,6 +25,37 @@ spec: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet {{- end }} + {{- if .Values.postgres.enabled }} + initContainers: + - name: init-recorder + image: busybox:latest + command: + - /bin/sh + - -c + - | + # Build recorder.yaml with postgres connection string + cat > /config/recorder.yaml << EOF + recorder: + db_url: "postgresql://{{ .Values.postgres.user }}:${HA_POSTGRESQL_PASSWORD}@{{ .Values.postgres.host }}:{{ .Values.postgres.port }}/{{ .Values.postgres.db }}" + db_retry_wait: 15 + auto_purge: true + purge_keep_days: {{ .Values.postgres.purgeKeepDays | default 30 }} + EOF + # Ensure configuration.yaml includes recorder.yaml + if ! grep -q 'recorder.yaml' /config/configuration.yaml 2>/dev/null; then + echo "" >> /config/configuration.yaml + echo "recorder: !include recorder.yaml" >> /config/configuration.yaml + fi + env: + - name: HA_POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.postgres.existingSecret }} + key: {{ .Values.postgres.passwordKey }} + volumeMounts: + - name: config + mountPath: /config + {{- end }} containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" diff --git a/home-assistant/values.yaml b/home-assistant/values.yaml index 1d0e545..24f66f0 100644 --- a/home-assistant/values.yaml +++ b/home-assistant/values.yaml @@ -60,6 +60,30 @@ persistence: hostPath: /srv/data/home-assistant/media mountPath: /media +postgres: + enabled: false + host: postgres-tcp.postgres.svc.cluster.local + port: 5432 + db: homeassistant + user: ha + adminUser: postgres + existingSecret: "" + passwordKey: HA_POSTGRESQL_PASSWORD + adminSecret: "" + adminSecretKey: POSTGRES_ADMIN_PASSWORD + adminUserKey: "" + +dbInit: + enabled: false + image: postgres:16-alpine + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + backup: enabled: false schedule: "0 2 * * *"