blumeops/argocd/manifests/databases/README.md
Erich Blume 8621996343 Add Immich photo management + migrate forge URLs (#62)
## Summary
- Migrate all ArgoCD app repo URLs from `indri.tail8d86e.ts.net:2200` to `forge.ops.eblu.me:2222`
- Add Immich self-hosted photo management service with:
  - Helm chart deployment via ArgoCD
  - PostgreSQL cluster with pgvecto.rs for AI vector search (immich-pg)
  - NFS storage on sifaka for photo library (2Ti)
  - Tailscale Ingress + Caddy proxy for `photos.ops.eblu.me`
  - Machine learning service for face/object recognition

## Deployment and Testing
- [x] Update ArgoCD repo-creds-forge secret with new URL (one-time manual step)
- [ ] Sync `apps` to pick up new applications
- [ ] Sync all existing apps to verify new forge URL works
- [ ] Sync `blumeops-pg` to deploy immich-pg cluster
- [ ] Wait for immich-pg to be healthy
- [ ] Create immich-db secret from auto-generated password
- [ ] Sync `immich-storage` (PV, PVC, Ingress)
- [ ] Sync `immich` (Helm chart)
- [ ] Run `mise run provision-indri -- --tags caddy` to add photos.ops.eblu.me
- [ ] Verify Immich UI is accessible

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/62
2026-01-26 11:20:11 -08:00

140 lines
4.4 KiB
Markdown

# 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 `standard` storage class
- **Initial database**: `miniflux` owned by `miniflux` user
### 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:
```bash
# 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:
```bash
# 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 --vault blumeops item get guxu3j7ajhjyey6xxl2ovsl2ui --fields password --reveal) \
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:
```bash
# 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 --vault blumeops item get guxu3j7ajhjyey6xxl2ovsl2ui --fields password --reveal) \
psql -h localhost -U eblume -d miniflux
```
### Status
```bash
# 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:
1. Delete `service-tailscale.yaml` (the `k8s-pg` service)
2. Update/create a service with `tailscale.com/hostname: "pg"`
3. Verify the orphaned `k8s-pg` device 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 `standard` storage 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:
```bash
# Get immich app credentials
kubectl -n databases get secret immich-pg-app -o jsonpath='{.data.password}' | base64 -d
```
### Status
```bash
# Check cluster health
kubectl -n databases get cluster immich-pg
# Check pods
kubectl -n databases get pods -l cnpg.io/cluster=immich-pg
```