stack.basicstack.de/apps/pangolin/pangolin-deployment.yaml
CTO Agent 6313b85999 chore(pangolin): bump postgres 17.5 -> 17.11 (DEV-533)
Patch bump per DEV-520 plan. Only pangolin uses postgres:17.5*;
other apps (paperclip, directus, forgejo, stalwart) are on
postgres:16-alpine and are out of scope for this ticket.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-08-23 15:07:38 +00:00

221 lines
5.6 KiB
YAML

---
# Pangolin Data PersistentVolumeClaim (retained for pangolin runtime files at /app/config)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pangolin-data
namespace: pangolin
annotations:
argocd.argoproj.io/sync-options: Delete=false
spec:
accessModes:
- ReadWriteOnce
storageClassName: hcloud-volumes-encrypted
resources:
requests:
storage: 10Gi
---
# Pangolin Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: pangolin
namespace: pangolin
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: pangolin
template:
metadata:
labels:
app: pangolin
spec:
initContainers:
- name: wait-for-postgres
image: postgres:17.11
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
- name: render-config
image: busybox:1.38.0
command:
- /bin/sh
- -c
- |
set -e
# Escape sed replacement metacharacters in the connection string
esc=$(printf '%s' "$DATABASE_URL" | sed -e 's/[\/&|]/\\&/g')
sed "s|__DATABASE_URL__|$esc|" /tmpl/config.yml.tmpl > /rendered/config.yml
echo "rendered config.yml (secrets redacted):"
sed 's|connection_string:.*|connection_string: <redacted>|' /rendered/config.yml
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: pangolin-postgres-secrets
key: connection-string
volumeMounts:
- name: config-tmpl
mountPath: /tmpl
- name: config-rendered
mountPath: /rendered
containers:
- name: pangolin
image: fosrl/pangolin:postgresql-1.21.1
ports:
- containerPort: 3000
name: api
- containerPort: 3002
name: http
env:
- name: PANGOLIN_URL
value: "https://pangolin.basicstack.de"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: pangolin-postgres-secrets
key: connection-string
# OIDC Configuration
- name: OIDC_ENABLED
value: "true"
- name: OIDC_ISSUER
value: "https://auth.basicstack.de"
- name: OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: pangolin-secrets
key: oidc-client-id
- name: OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: pangolin-secrets
key: oidc-client-secret
- name: OIDC_CALLBACK_URL
value: "https://pangolin.basicstack.de/auth/callback"
- name: OIDC_SCOPES
value: "openid profile email groups"
# Admin Credentials
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: pangolin-secrets
key: admin-password
volumeMounts:
- name: pangolin-data
mountPath: /app/config
- name: config-rendered
mountPath: /app/config/config.yml
subPath: config.yml
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /
port: 3002
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
readinessProbe:
httpGet:
path: /
port: 3002
initialDelaySeconds: 30
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: pangolin-data
persistentVolumeClaim:
claimName: pangolin-data
- name: config-tmpl
configMap:
name: pangolin-config
- name: config-rendered
emptyDir: {}
---
# Pangolin Service
apiVersion: v1
kind: Service
metadata:
name: pangolin
namespace: pangolin
spec:
type: ClusterIP
selector:
app: pangolin
ports:
- name: api
port: 3000
targetPort: 3000
protocol: TCP
# Internal API (used by pangolin-kube-controller for /api/v1/traefik-config).
# This port has no auth by design — never route it through the public Ingress.
- name: internal
port: 3001
targetPort: 3001
protocol: TCP
- name: http
port: 3002
targetPort: 3002
protocol: TCP
---
# Pangolin Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pangolin
namespace: pangolin
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-http01"
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- pangolin.basicstack.de
secretName: pangolin-tls
rules:
- host: pangolin.basicstack.de
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: pangolin
port:
number: 3000
- path: /
pathType: Prefix
backend:
service:
name: pangolin
port:
number: 3002