teslamate had superuser on the shared blumeops-pg cluster (which also hosts miniflux and authentik). Downgraded to plain database owner with extension ownership (cube, earthdistance) transferred manually so it can still ALTER EXTENSION UPDATE. earthdistance is untrusted in PG so DROP+CREATE would need temporary superuser escalation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| blumeops-pg.yaml | ||
| external-secret-authentik.yaml | ||
| external-secret-borgmatic.yaml | ||
| external-secret-eblume.yaml | ||
| external-secret-immich-borgmatic.yaml | ||
| external-secret-teslamate.yaml | ||
| immich-pg.yaml | ||
| kustomization.yaml | ||
| README.md | ||
| service-immich-pg-tailscale.yaml | ||
| service-metrics-tailscale.yaml | ||
| service-tailscale.yaml | ||
Database Manifests
PostgreSQL clusters managed by CloudNativePG operator.
Clusters
| Cluster | Image | Purpose |
|---|---|---|
| blumeops-pg | cloudnative-pg/postgresql:18 | General services (miniflux, teslamate) |
| immich-pg | tensorchord/cloudnative-vectorchord:17 | Immich (requires pgvecto.rs extension) |
blumeops-pg
Single-instance PostgreSQL cluster for blumeops services.
Configuration
- Instances: 1 (single-node for minikube)
- Storage: 10Gi on
standardstorage class - Initial database:
minifluxowned byminifluxuser
Users/Roles
| User | Role | Purpose | Password Source |
|---|---|---|---|
| postgres | superuser | CNPG internal (avoid using) | blumeops-pg-superuser secret |
| miniflux | app owner | Owns miniflux database | blumeops-pg-app secret |
| eblume | superuser | Admin access (matches brew pg) | blumeops-pg-eblume secret (manual) |
| borgmatic | pg_read_all_data | Backup access for borgmatic | blumeops-pg-borgmatic secret (manual) |
Manual Secret Setup
Before deploying, create the password secrets:
# Create namespace first
kubectl create namespace databases
# Apply eblume password from 1Password
op inject -i argocd/manifests/databases/secret-eblume.yaml.tpl | kubectl apply -f -
# Apply borgmatic password from 1Password
op inject -i argocd/manifests/databases/secret-borgmatic.yaml.tpl | kubectl apply -f -
The miniflux user password is auto-generated by CloudNativePG and stored in blumeops-pg-app.
Connection Information
After the cluster is healthy:
# Connect via Tailscale (temporary hostname during migration)
psql -h k8s-pg.tail8d86e.ts.net -U eblume -W -d miniflux
# Or with password from 1Password
PGPASSWORD=$(op read "op://blumeops/guxu3j7ajhjyey6xxl2ovsl2ui/password") \
psql -h k8s-pg.tail8d86e.ts.net -U eblume -d miniflux
# Get miniflux app credentials (for applications)
kubectl -n databases get secret blumeops-pg-app -o jsonpath='{.data.uri}' | base64 -d
# Get postgres superuser credentials (emergency only)
kubectl -n databases get secret blumeops-pg-superuser -o jsonpath='{.data.password}' | base64 -d
Connecting via kubectl port-forward
Alternative if Tailscale service is unavailable:
# Terminal 1: Port-forward to the primary
kubectl -n databases port-forward svc/blumeops-pg-rw 5432:5432
# Terminal 2: Connect as eblume
PGPASSWORD=$(op read "op://blumeops/guxu3j7ajhjyey6xxl2ovsl2ui/password") \
psql -h localhost -U eblume -d miniflux
Status
# Check cluster health
kubectl -n databases get cluster blumeops-pg
# Check pods
kubectl -n databases get pods -l cnpg.io/cluster=blumeops-pg
# Check managed roles status
kubectl -n databases get cluster blumeops-pg -o jsonpath='{.status.managedRolesStatus}' | jq
# Operator logs
kubectl -n databases logs -l cnpg.io/cluster=blumeops-pg
Tailscale Exposure
Current: Temporary Service
k8s-pg.tail8d86e.ts.net - LoadBalancer service for testing during migration.
Phase 4: Production Service
After miniflux migrates to k8s, the pg.tail8d86e.ts.net Tailscale service will switch
from brew PostgreSQL (indri) to this k8s cluster. At that point:
- Delete
service-tailscale.yaml(thek8s-pgservice) - Update/create a service with
tailscale.com/hostname: "pg" - Verify the orphaned
k8s-pgdevice is removed from tailnet
immich-pg
PostgreSQL cluster for Immich with VectorChord extension for AI-powered vector search.
Configuration
- Instances: 1 (single-node for minikube)
- Storage: 10Gi on
standardstorage class - Image:
ghcr.io/tensorchord/cloudnative-vectorchord:17-0.5.0(VectorChord 0.5.0 for Immich compatibility) - Extensions:
vector,vchord,cube,earthdistance
Connection
Immich connects via immich-pg-rw.databases.svc.cluster.local:5432.
The immich user password is auto-generated by CloudNativePG and stored in immich-pg-app secret:
# Get immich app credentials
kubectl -n databases get secret immich-pg-app -o jsonpath='{.data.password}' | base64 -d
Status
# Check cluster health
kubectl -n databases get cluster immich-pg
# Check pods
kubectl -n databases get pods -l cnpg.io/cluster=immich-pg