## 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
140 lines
4.4 KiB
Markdown
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
|
|
```
|