From 22f418d0dc30051db422a7d3e76a7eeb5ada84f6 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 15 Feb 2026 07:42:01 -0800 Subject: [PATCH] Doc review: connect-to-postgres, create-release-artifact-workflow, deploy-k8s-service (#191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Review session covering 3 docs, plus a codebase-wide cleanup: ### Docs reviewed - **connect-to-postgres** — verified end-to-end (psql connection tested), stamped - **create-release-artifact-workflow** — clarified that `build-blumeops.yaml` is only a version bump example (not a packages API example) - **deploy-k8s-service** — fixed stale repoURL (`indri:2200` → `forge.ops.eblu.me:2222`), wrong Caddy config keys (`upstream` → `backend`, added missing `host`), updated Homepage group to "Services", added Tailscale tag documentation ### Codebase cleanup - Migrated all remaining `op item get --fields` calls to `op read` URI syntax across 7 files (docs, READMEs, YAML comments) - Simplified the `op read` vs `op item get` guidance in CLAUDE.md ## Side findings (not addressed) - New `immich-pg` CNPG cluster not yet documented in the postgresql reference card ## Test plan - [x] `psql` connection to `pg.ops.eblu.me` verified - [x] All pre-commit hooks pass - [x] `docs-check-links`, `docs-check-index`, `docs-check-frontmatter` pass Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/191 --- CLAUDE.md | 2 +- argocd/apps/teslamate.yaml | 4 ++-- argocd/manifests/databases/README.md | 4 ++-- argocd/manifests/teslamate/README.md | 4 ++-- .../docs-doc-review-feb-15-2026.doc.md | 1 + docs/how-to/connect-to-postgres.md | 3 ++- .../create-release-artifact-workflow.md | 5 ++-- docs/how-to/deploy-k8s-service.md | 16 +++++++++---- docs/how-to/gandi-operations.md | 2 +- docs/how-to/troubleshooting.md | 2 +- docs/reference/services/postgresql.md | 23 ++++++++++++------- pulumi/gandi/README.md | 2 +- 12 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 docs/changelog.d/docs-doc-review-feb-15-2026.doc.md diff --git a/CLAUDE.md b/CLAUDE.md index 9390944..6f255b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -96,4 +96,4 @@ mise run blumeops-tasks # fetch from Todoist, sorted by priority Root store is 1Password. Never grab directly - use existing patterns (ansible pre_tasks, external-secrets, scripts with `op` CLI). Warn user before any credential access. -**`op read` vs `op item get`:** Always use `op read "op://vault/item/field"` to retrieve secret values. `op item get --fields` wraps multi-line values in quotes, corrupting them. Use `op item get` only for listing item metadata (title, vault, field names), never for reading actual secret values in scripts or IaC. Look for existing uses of `op item get --fields` in Ansible/scripts and suggest replacing with `op read`. +Prefer `op read "op://vault/item/field"` over `op item get --fields` to avoid quoting issues with multi-line values. diff --git a/argocd/apps/teslamate.yaml b/argocd/apps/teslamate.yaml index 6165b8e..60247da 100644 --- a/argocd/apps/teslamate.yaml +++ b/argocd/apps/teslamate.yaml @@ -8,8 +8,8 @@ # op inject -i argocd/manifests/teslamate/secret-db.yaml.tpl | kubectl apply -f - # # Then create the database: -# PGPASSWORD=$(op --vault blumeops item get --fields password --reveal) \ -# psql -h pg.tail8d86e.ts.net -U eblume -c "CREATE DATABASE teslamate OWNER teslamate;" +# PGPASSWORD=$(op read "op://blumeops/postgres/password") \ +# psql -h pg.ops.eblu.me -U eblume -c "CREATE DATABASE teslamate OWNER teslamate;" # # After syncing, access the TeslaMate UI at https://tesla.tail8d86e.ts.net to complete # Tesla API authentication via OAuth flow. diff --git a/argocd/manifests/databases/README.md b/argocd/manifests/databases/README.md index b5794d2..be7fc2e 100644 --- a/argocd/manifests/databases/README.md +++ b/argocd/manifests/databases/README.md @@ -54,7 +54,7 @@ After the cluster is healthy: 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) \ +PGPASSWORD=$(op read "op://blumeops/guxu3j7ajhjyey6xxl2ovsl2ui/password") \ psql -h k8s-pg.tail8d86e.ts.net -U eblume -d miniflux # Get miniflux app credentials (for applications) @@ -73,7 +73,7 @@ Alternative if Tailscale service is unavailable: 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) \ +PGPASSWORD=$(op read "op://blumeops/guxu3j7ajhjyey6xxl2ovsl2ui/password") \ psql -h localhost -U eblume -d miniflux ``` diff --git a/argocd/manifests/teslamate/README.md b/argocd/manifests/teslamate/README.md index 65875e4..7e1f9fc 100644 --- a/argocd/manifests/teslamate/README.md +++ b/argocd/manifests/teslamate/README.md @@ -36,8 +36,8 @@ op inject -i argocd/manifests/teslamate/secret-db.yaml.tpl | kubectl apply -f - After the teslamate user exists in PostgreSQL (sync blumeops-pg first): ```bash -PGPASSWORD=$(op --vault blumeops item get --fields password --reveal) \ - psql -h pg.tail8d86e.ts.net -U eblume -c "CREATE DATABASE teslamate OWNER teslamate;" +PGPASSWORD=$(op read "op://blumeops/postgres/password") \ + psql -h pg.ops.eblu.me -U eblume -c "CREATE DATABASE teslamate OWNER teslamate;" ``` ## Deployment diff --git a/docs/changelog.d/docs-doc-review-feb-15-2026.doc.md b/docs/changelog.d/docs-doc-review-feb-15-2026.doc.md new file mode 100644 index 0000000..f4ead88 --- /dev/null +++ b/docs/changelog.d/docs-doc-review-feb-15-2026.doc.md @@ -0,0 +1 @@ +Review connect-to-postgres, create-release-artifact-workflow, and deploy-k8s-service docs. Fix stale repoURL, incorrect Caddy config keys, add Tailscale tag documentation, and migrate remaining `op item get` calls to `op read`. diff --git a/docs/how-to/connect-to-postgres.md b/docs/how-to/connect-to-postgres.md index fb3ae86..d6b01f7 100644 --- a/docs/how-to/connect-to-postgres.md +++ b/docs/how-to/connect-to-postgres.md @@ -1,6 +1,7 @@ --- title: Connect to Postgres -modified: 2026-02-14 +modified: 2026-02-15 +last-reviewed: 2026-02-15 tags: - how-to - database diff --git a/docs/how-to/create-release-artifact-workflow.md b/docs/how-to/create-release-artifact-workflow.md index 829ff3e..80e0308 100644 --- a/docs/how-to/create-release-artifact-workflow.md +++ b/docs/how-to/create-release-artifact-workflow.md @@ -1,6 +1,7 @@ --- title: Create Release Artifact Workflow -modified: 2026-02-12 +modified: 2026-02-15 +last-reviewed: 2026-02-15 tags: - how-to - forgejo @@ -34,7 +35,7 @@ This is required because Forgejo's built-in `GITHUB_TOKEN` does not have permiss ## 2. Create the workflow -Create `.forgejo/workflows/-release.yaml` with `workflow_dispatch` and a version input. Use the semver bump pattern (see `cv-release.yaml` or `build-blumeops.yaml` for examples). +Create `.forgejo/workflows/-release.yaml` with `workflow_dispatch` and a version input. Use the semver bump pattern (see `cv-release.yaml` for the full upload flow, or `build-blumeops.yaml` for the version bump logic only — it uploads to Forgejo releases, not generic packages). The upload step uses `FORGE_TOKEN`: diff --git a/docs/how-to/deploy-k8s-service.md b/docs/how-to/deploy-k8s-service.md index ed42912..e54fd7a 100644 --- a/docs/how-to/deploy-k8s-service.md +++ b/docs/how-to/deploy-k8s-service.md @@ -1,6 +1,7 @@ --- title: Deploy K8s Service -modified: 2026-02-11 +modified: 2026-02-15 +last-reviewed: 2026-02-15 tags: - how-to - kubernetes @@ -34,7 +35,7 @@ metadata: spec: project: default source: - repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git + repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git targetRevision: main path: argocd/manifests/ destination: @@ -60,7 +61,7 @@ metadata: tailscale.com/proxy-group: "ingress" gethomepage.dev/enabled: "true" gethomepage.dev/name: "Service Name" - gethomepage.dev/group: "Apps" + gethomepage.dev/group: "Services" gethomepage.dev/icon: ".png" gethomepage.dev/href: "https://.ops.eblu.me" gethomepage.dev/pod-selector: "app=" @@ -80,6 +81,12 @@ Key points: - **`proxy-group: "ingress"`** routes through the shared ProxyGroup instead of spawning a per-ingress proxy - **Do not use `rules:` with `host:`** — the ProxyGroup proxy receives the FQDN as Host header (e.g. `.tail8d86e.ts.net`), so a short `host: ` won't match. Use `defaultBackend` instead. - **`tls.hosts`** sets the MagicDNS hostname (becomes `.tail8d86e.ts.net`) +- **`gethomepage.dev/group`** — use one of the existing groups: "Services", "Content", or "Infrastructure" +- **`tailscale.com/tags`** is not needed in the default case — the ProxyGroup already applies `tag:k8s`. Only add this annotation when the service needs public internet access via the [[flyio-proxy]]. When you do, you must include both tags (setting tags overrides the ProxyGroup default): + ```yaml + tailscale.com/tags: "tag:k8s,tag:flyio-target" + ``` + Then add a Caddy route and Fly.io proxy config per [[expose-service-publicly]]. ## Add Caddy Route (if needed) @@ -88,7 +95,8 @@ If other pods need to access the service, add to `ansible/roles/caddy/defaults/m ```yaml caddy_services: - name: - upstream: "https://.tail8d86e.ts.net" + host: ".{{ caddy_domain }}" + backend: "https://.tail8d86e.ts.net" ``` Then: `mise run provision-indri -- --tags caddy` diff --git a/docs/how-to/gandi-operations.md b/docs/how-to/gandi-operations.md index 138eed2..83b4bd4 100644 --- a/docs/how-to/gandi-operations.md +++ b/docs/how-to/gandi-operations.md @@ -32,7 +32,7 @@ Both tasks fetch the Gandi PAT from 1Password automatically. To run Pulumi directly: ```bash -export GANDI_PERSONAL_ACCESS_TOKEN=$(op item get mco6ka3dc3rmw7zkg2dhia5d2m --field pat --reveal --vault vg6xf6vvfmoh5hqjjhlhbeoaie) +export GANDI_PERSONAL_ACCESS_TOKEN=$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/mco6ka3dc3rmw7zkg2dhia5d2m/pat") cd pulumi/gandi pulumi preview pulumi up --yes diff --git a/docs/how-to/troubleshooting.md b/docs/how-to/troubleshooting.md index 24bc1e7..567b9e7 100644 --- a/docs/how-to/troubleshooting.md +++ b/docs/how-to/troubleshooting.md @@ -69,7 +69,7 @@ kubectl --context=minikube-indri -n get pods --field-selector=status **ArgoCD login expired:** ```bash -argocd login argocd.ops.eblu.me --username admin --password "$(op --vault vg6xf6vvfmoh5hqjjhlhbeoaie item get srogeebssulhtb6tnqd7ls6qey --fields password --reveal)" +argocd login argocd.ops.eblu.me --username admin --password "$(op read 'op://vg6xf6vvfmoh5hqjjhlhbeoaie/srogeebssulhtb6tnqd7ls6qey/password')" ``` ### kubectl connection refused diff --git a/docs/reference/services/postgresql.md b/docs/reference/services/postgresql.md index efa3b8b..9d08d08 100644 --- a/docs/reference/services/postgresql.md +++ b/docs/reference/services/postgresql.md @@ -1,6 +1,6 @@ --- title: PostgreSQL -modified: 2026-02-07 +modified: 2026-02-15 tags: - service - database @@ -8,7 +8,7 @@ tags: # PostgreSQL -Database cluster via CloudNativePG operator. +Database clusters via CloudNativePG operator. ## Quick Reference @@ -17,15 +17,18 @@ Database cluster via CloudNativePG operator. | **URL** | `tcp://pg.ops.eblu.me:5432` | | **Metrics** | `http://cnpg-metrics.tail8d86e.ts.net:9187/metrics` | | **Namespace** | `databases` | -| **Cluster** | `blumeops-pg` | +| **Clusters** | `blumeops-pg`, `immich-pg` | | **Operator** | CloudNativePG | ## Databases -| Database | Owner | Purpose | -|----------|-------|---------| -| miniflux | miniflux | [[miniflux]] feed data | -| teslamate | teslamate | [[teslamate]] vehicle data | +| Database | Cluster | Owner | Purpose | +|----------|---------|-------|---------| +| miniflux | blumeops-pg | miniflux | [[miniflux]] feed data | +| teslamate | blumeops-pg | teslamate | [[teslamate]] vehicle data | +| immich | immich-pg | immich | [[immich]] photo management | + +The `immich-pg` cluster uses a custom image (`cloudnative-vectorchord`) with vector search extensions (vector, vchord, cube, earthdistance). ## Users @@ -47,15 +50,19 @@ Backed up via [[borgmatic]] `postgresql_databases` hook. Streams `pg_dump` direc - `guxu3j7ajhjyey6xxl2ovsl2ui` - eblume password - `mw2bv5we7woicjza7hc6s44yvy` - borgmatic password -**CNPG-managed secrets:** +**CNPG-managed secrets (blumeops-pg):** - `blumeops-pg-app` - miniflux user - `blumeops-pg-eblume` - eblume superuser - `blumeops-pg-borgmatic` - borgmatic backup user - `blumeops-pg-teslamate` - teslamate user +**CNPG-managed secrets (immich-pg):** +- `immich-pg-app` - immich user + ## Related - [[connect-to-postgres]] - How to connect via psql - [[miniflux]] - Feed reader database - [[teslamate]] - Vehicle data database +- [[immich]] - Photo management database - [[borgmatic]] - Database backup diff --git a/pulumi/gandi/README.md b/pulumi/gandi/README.md index d8d30d9..9d7b7aa 100644 --- a/pulumi/gandi/README.md +++ b/pulumi/gandi/README.md @@ -70,7 +70,7 @@ mise run dns-preview # Preview only Or manually: ```bash -export GANDI_PERSONAL_ACCESS_TOKEN=$(op item get mco6ka3dc3rmw7zkg2dhia5d2m --field pat --reveal --vault vg6xf6vvfmoh5hqjjhlhbeoaie) +export GANDI_PERSONAL_ACCESS_TOKEN=$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/mco6ka3dc3rmw7zkg2dhia5d2m/pat") pulumi up ```