{{- if .Values.postgres.enabled }} apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ include "the-other-dude.fullname" . }}-postgres labels: {{- include "the-other-dude.postgresLabels" . | nindent 4 }} spec: serviceName: {{ include "the-other-dude.fullname" . }}-postgres replicas: 1 selector: matchLabels: {{- include "the-other-dude.postgresSelectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "the-other-dude.postgresSelectorLabels" . | nindent 8 }} spec: containers: - name: postgres image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}" imagePullPolicy: {{ .Values.postgres.image.pullPolicy }} ports: - name: postgres containerPort: 5432 protocol: TCP env: - name: POSTGRES_DB value: {{ .Values.postgres.auth.database | quote }} - name: POSTGRES_USER value: {{ .Values.postgres.auth.username | quote }} - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: {{ include "the-other-dude.fullname" . }}-secrets key: DB_PASSWORD - name: APP_USER value: {{ .Values.postgres.auth.appUsername | quote }} - name: APP_USER_PASSWORD valueFrom: secretKeyRef: name: {{ include "the-other-dude.fullname" . }}-secrets key: DB_APP_PASSWORD volumeMounts: - name: postgres-data mountPath: /var/lib/postgresql/data - name: init-scripts mountPath: /docker-entrypoint-initdb.d readOnly: true resources: {{- toYaml .Values.postgres.resources | nindent 12 }} livenessProbe: exec: command: - pg_isready - -U - {{ .Values.postgres.auth.username | quote }} - -d - {{ .Values.postgres.auth.database | quote }} initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 5 readinessProbe: exec: command: - pg_isready - -U - {{ .Values.postgres.auth.username | quote }} - -d - {{ .Values.postgres.auth.database | quote }} initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3 volumes: - name: init-scripts configMap: name: {{ include "the-other-dude.fullname" . }}-postgres-init volumeClaimTemplates: - metadata: name: postgres-data spec: accessModes: ["ReadWriteOnce"] {{- if .Values.postgres.storageClass }} storageClassName: {{ .Values.postgres.storageClass | quote }} {{- end }} resources: requests: storage: {{ .Values.postgres.storage }} --- apiVersion: v1 kind: Service metadata: name: {{ include "the-other-dude.fullname" . }}-postgres labels: {{- include "the-other-dude.postgresLabels" . | nindent 4 }} spec: type: ClusterIP clusterIP: None ports: - port: {{ .Values.postgres.service.port }} targetPort: postgres protocol: TCP name: postgres selector: {{- include "the-other-dude.postgresSelectorLabels" . | nindent 4 }} --- apiVersion: v1 kind: ConfigMap metadata: name: {{ include "the-other-dude.fullname" . }}-postgres-init labels: {{- include "the-other-dude.postgresLabels" . | nindent 4 }} data: init.sql: | -- Create non-superuser app_user role for RLS enforcement -- This runs on first container start via docker-entrypoint-initdb.d DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{{ .Values.postgres.auth.appUsername }}') THEN CREATE ROLE {{ .Values.postgres.auth.appUsername }} WITH LOGIN PASSWORD '{{ .Values.secrets.dbAppPassword }}'; END IF; END $$; -- Grant connection and usage permissions GRANT CONNECT ON DATABASE {{ .Values.postgres.auth.database }} TO {{ .Values.postgres.auth.appUsername }}; GRANT USAGE ON SCHEMA public TO {{ .Values.postgres.auth.appUsername }}; -- Grant DML permissions (INSERT, SELECT, UPDATE, DELETE — no DDL) GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {{ .Values.postgres.auth.appUsername }}; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO {{ .Values.postgres.auth.appUsername }}; -- Set default privileges so future tables are also accessible ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {{ .Values.postgres.auth.appUsername }}; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO {{ .Values.postgres.auth.appUsername }}; {{- end }}