diff --git a/apps/pangolin/pangolin-config.yaml b/apps/pangolin/pangolin-config.yaml index 251910b..94293c8 100644 --- a/apps/pangolin/pangolin-config.yaml +++ b/apps/pangolin/pangolin-config.yaml @@ -29,9 +29,6 @@ data: signup: true verification: false - database: - path: "/data/pangolin.db" - oidc: enabled: true issuer: "https://auth.basicstack.de" diff --git a/apps/pangolin/pangolin-deployment.yaml b/apps/pangolin/pangolin-deployment.yaml index 15b03e9..bbb042b 100644 --- a/apps/pangolin/pangolin-deployment.yaml +++ b/apps/pangolin/pangolin-deployment.yaml @@ -1,5 +1,5 @@ --- -# Pangolin Data PersistentVolumeClaim +# Pangolin Data PersistentVolumeClaim (retained for pangolin runtime files at /app/config) apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -33,9 +33,33 @@ spec: labels: app: pangolin spec: + initContainers: + - name: wait-for-postgres + image: postgres:17.5 + command: + - /bin/sh + - -c + - | + set -e + until pg_isready -h pangolin-postgres.pangolin.svc.cluster.local -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB"; do + echo "waiting for postgres..." + sleep 2 + done + echo "postgres is ready" + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: postgres-user + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: postgres-db containers: - name: pangolin - image: fosrl/pangolin:1.21.1 + image: fosrl/pangolin:postgresql-1.21.1 ports: - containerPort: 3000 name: api @@ -44,8 +68,12 @@ spec: env: - name: PANGOLIN_URL value: "https://pangolin.basicstack.de" - - name: DATABASE_PATH - value: "/data/pangolin.db" + # PostgreSQL database URL (Pangolin PostgreSQL variant reads this at startup) + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: connection-string # OIDC Configuration - name: OIDC_ENABLED value: "true" @@ -73,7 +101,7 @@ spec: key: admin-password volumeMounts: - name: pangolin-data - mountPath: /data + mountPath: /app/config - name: config mountPath: /app/config/config.yml subPath: config.yml diff --git a/apps/pangolin/pangolin-postgres-secrets-sealed.yaml b/apps/pangolin/pangolin-postgres-secrets-sealed.yaml new file mode 100644 index 0000000..b61affa --- /dev/null +++ b/apps/pangolin/pangolin-postgres-secrets-sealed.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: pangolin-postgres-secrets + namespace: pangolin +spec: + encryptedData: + connection-string: AgBxITAqIcO4rqdcbJSRdVJv5TO2teg4tjgXsXeB7hSLxcFTLST/4wQPigaf1flrxMlWejbsmP7n2VXy6KOqwskcCHF/KR+7usGD4xAeIsM1LZDi1NLcFt7RVnR+vhoUcU6+F8xm5Tc6QCZnwfJBEoP2yVeZSIj9XwTUYeluoZF32FD54lQatMphPl4nD7AjLC2SD6i9pB46f5h+zWfYUrtoMk0uNrnxPLpM8YnOXZHl8cLOcXAuGu7iWhQMRfCYv7Nt2/HnDNVVjoZ7qcfTRPF4snjOePBYsxVynmZojtHroGosaFGY/FUWkMEB8j7BCQiV4hlVAAuHpGwSZs37+kDOJY4z1MOriXIqbbQoLvhf8rxArly0TJK+lzuhsu1MsJUPuk/wahcgXI/aN4G98RuJUpxxiUk3EZZ8/IN0E2Kswx59zFhmOjmdxw4eh2oam/Oukc/gaRUs2+Y+/j10JaNQ9yNBCQjCfumw56gNifb1ub6ALC80c2jKGhRaDu8tiG2hWW57VaHFMOuZNQj1a4gcsJNqzTu/oDk1505SiowfQbqJYC21AH9kj/OAEcu0nMAlhSlMpM5tWF/m+VmodSPxq1g3b5/bSJdzXKdQ5WN0PE3LvuneESP3B1YBp58Bb4A4buV3kxpSDAdgmd86uN9g24ZdwxlDWsrFZRYaZh1JnnR84bqqyWwHuElDRpDvO14gpjlD4lNTQfScgJ2z+hmnGddjT7u3atCQu4pFEIzcbg2JVi38Pz5JlwzR1crZfP9tQh/CWrIVOQJI+EQE+MZTczBanlN/o8zf6Q2plqnV0QEDqAVtRwLh5OqsRMPuEXDZ/jJei+N/K0KUhTO26DhDXg== + postgres-db: AgAeCwjNgP6NXncaN7CNMDuI7R6f00qalC08uhy4Kxsc+4twWp+K8x7JGiVosNdirNVRLSrGXaf53Onn2f/uDkgWU8tJETIS/qae1QcxSL3DDtC35XxdymYOPlS+97YBw3Lud0mTVda25v6vnfB5aPiNwXL4u4Nct/eYw15bpVmv2zTb7bNbbdNyu5MSiaA14Wlc/9jMXHnJTeGLEno4FEwzaUBFwEmQRyOE7XQ/z2Fb/47xTXnkn29roe2yHX+25lqC7OWx3F9hVVhUon34u/Y4ybuuUwJix7mx3DB2ObKYV8FC939nqEfNw5vraO6B4ICXPTi/hRXT3kWfRZCQ3XHFoUWU5uD4Skp2d10YarsxGxpLq0ZP/CMD51Pr7jbAYQ9WwbLvhwYHv0CjuqrZrI8ln7Y+CT/5l9zREhbqDSBLkPIUfsJXNEmnN3IYM5yi2LkUTSswgRmJD3ouSZTEMHpo7sFoDCm4xzD8o+H5ImIL3k4mBHjgQvbHD8p0NfP8jeLb3PlVgoF3qUD0l5Ekg/5MdA49LdD6UK0ma5kT/wEzfXiWPOa/xwvv7yhV3qQru62/lFMaYs/S1o0gJrE7MzXvM/0i6JnLehrtP0w7LWieV7vx6/n7DAKt1HV4quXRURXrfihDK+fJSbaLkJveAdqW63eB+wA3fnE5j2pWNN7cjj1tFOHdL1x2WOhO2XVt5bZbL0jji1D4Wg== + postgres-password: AgCBmdJimG15nZc6fTW06PbUgxUzOgaWc53hxXVbkewSX+/of+RGdkwGbB95f5ShVSnApgvptPHiFsi+LD6w3nsI37Yl4/uFbwmeIL9iL2wFQsB8lHpFAq8xg1lUK0bsmNvAfyXVhTwlPXLNk4nSPQbLTekE/hdZmtDo9AtBphZW13OSNl6exEKeYEw7gEDSRu/M7c0OG2cxY4GmPqXNMKkbNh1YVcFnRhOt9pXtMbDlwWj66ua/GNRMEltAfGWiJiuKKXwbyTip0C8SCwsMad411B88oJDneLpccwFxq7v8WKTSYLy8hZJEIphhC11sOs+wXOnuGhWv/QpK3GU3HLrPst2eSBwc9B+7mDhHJI6JrngBNBO/356HuGA2A/AxNeRxMW42jU+I60iQjGiDE/IwpdAtOH/Mu0o48tUn3COhwbf/cyC06gvUirWgSZKE5lsuO73VCn/CE0FvxA78dnSs0otw01mkXnHzRZrcMlglkL+BX+7vNamhaZxuG+ggYlgGscYHXMrhxfWqpBmO9ENYweHDNeHfeY9FlD3jt5GDSF8eKDz5JY3qoB2CLkblyEcPEE1YHfMGPFLPlF7t1C3FTASlp+Iw2UP00vJ9Yg3s9qO3CmMkokWsBzG0hGWETQhU8J90y48xtH+m9rd8rH+IxH5z9z3KlPa4KQ5FpjrsQ7YJ1i9TCCGeu8HR5/9m1Fq7j+uKgqE+UmfK6MFLTcm3hI9Q1SJgtucp9yJpQVNhdg== + postgres-user: AgCIy54/EVmkpFqGSu95+l7wKYLwRALNCh5SC0dC6q6Q1VzVyZSP8ioUmKRyJT8+vuFwke9veXcTWm1fy0N4x64/s+yJO6eHOvJ2wSsKKiqv+m2AjdX2K72lB7CGHfrfYAH/8mHN0PdkF2loJRLCgcbeRoNEoWNiiP1qS2xzPNBMIH5Dpl5nlA7/wr4sZAWUfITl4Cb1sGksxQqFcy9Ua4HxDSBuIYMEx4CI7oifbVOwFXxm1oIWFqO4ANgO61OI5uKZNGLnpXifnuiITaulaCa+48gm8rg+fhvw1XTQLVnP80DfdsaU1rWu6wxZj3+Vs/S/szuLMx3OmR3HsgdYxj1mY70ZfV/r+qe/Fu+FFFc/GFNF01ZQTWrF+IaaNWUolPhm7NtLKxDy6FmF/Vwvt23Q6fA11pduxqnZlS+0kh+TGmX6s9dtNYcyuaEXfG3/5bPE/DvYEKRR8tAyoQxQTVgKs8SttSuwf+g5y1KkhwlkJqYhu+BPTG7fVVbL+UEceF6EeNc+LVZQTcx0SzLFxEIyUFPZktUAnLIft+S9n3jZCetvzch53DC7Cm5epKvovGisaeCNZ6wGisCL6UKxLa3g3YRCT/tgJsL8SyLE6g+AQsdVnyLJ58VdwqSrD7tLge9aYtJZ4YGHJzV9oN7zWEp15j3fLaQjNLKptzRoPf/VFgdYs0+PTXDDl2Y0WGCoXy6ynyr73KleMg== + template: + metadata: + creationTimestamp: null + name: pangolin-postgres-secrets + namespace: pangolin diff --git a/apps/pangolin/postgres.yaml b/apps/pangolin/postgres.yaml new file mode 100644 index 0000000..19432b9 --- /dev/null +++ b/apps/pangolin/postgres.yaml @@ -0,0 +1,116 @@ +--- +# PostgreSQL PersistentVolumeClaim +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pangolin-postgres-data + namespace: pangolin + annotations: + argocd.argoproj.io/sync-options: Delete=false +spec: + accessModes: + - ReadWriteOnce + storageClassName: hcloud-volumes-encrypted + resources: + requests: + storage: 10Gi +--- +# PostgreSQL Service (headless-friendly ClusterIP) +apiVersion: v1 +kind: Service +metadata: + name: pangolin-postgres + namespace: pangolin + labels: + app: pangolin-postgres +spec: + type: ClusterIP + selector: + app: pangolin-postgres + ports: + - name: postgres + port: 5432 + targetPort: 5432 + protocol: TCP +--- +# PostgreSQL Deployment (single-replica; PVC is RWO) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pangolin-postgres + namespace: pangolin + labels: + app: pangolin-postgres +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: pangolin-postgres + template: + metadata: + labels: + app: pangolin-postgres + spec: + securityContext: + fsGroup: 999 + containers: + - name: postgres + image: postgres:17.5 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5432 + name: postgres + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: postgres-user + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: postgres-password + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: pangolin-postgres-secrets + key: postgres-db + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: data + mountPath: /var/lib/postgresql/data + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "1000m" + readinessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 6 + livenessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + volumes: + - name: data + persistentVolumeClaim: + claimName: pangolin-postgres-data