bcs-website/docs/adr/0008-private-package-external-secrets-pull.md
Brad Rodgers fc64909f3d
All checks were successful
CI / ci (push) Successful in 1m56s
docs: reconcile to as-built (ADR-0008, deploy runbook); clean text hero on detail pages
- ADR-0008: private package, External-Secrets pull over public HTTPS (no k3s restart);
  CI auth via CI_TOKEN PAT; Playwright dropped from CI. Marks ADR-0007 partially superseded.
- gitops-deployment-strategy + deployment.md updated to as-built flow + operate/troubleshoot runbook
- content-deviations: detail-page heroes are text-only (no image)
- service/focus detail pages: clean text hero (drop shared photo/icon)
2026-07-20 08:27:35 -04:00

3.2 KiB

ADR-0008: Private package, External-Secrets pull over public HTTPS (no k3s restart)

Status: Accepted — 2026-07-17 · Supersedes the registry-visibility, image-pull, CI-auth, and pipeline specifics of ADR-0007. (ADR-0007's core — CI on Gitea Actions, images in Gitea Packages — still stands; only the details below changed once we actually built and debugged it.)

Context

ADR-0007 proposed a public package pulled by k3s from the internal HTTP registry (10.66.15.22:3000), which required registries.yaml on every node + a k3s restart, and CI auth via the runner's automatic token. In practice:

  • The automatic Gitea Actions token lacked reliable package-write scopedocker login returned unauthorized.
  • k3s trusting an HTTP registry means a rolling cluster restart — unacceptable disruption for a static site, and the user wanted zero risk to the (still-live) old site and other workloads.
  • The user chose a private package (least exposure) managed via the existing External Secrets + OpenBao stack.
  • Testing showed a cluster pod can reach the registry over public HTTPS (git.7tl-homelab.com, valid cert) — so no node-level registry config is needed at all.

Decision

  • Package is PRIVATE. (Gitea user packages are private by default; no public/anon pull.)
  • Split push/pull, same Gitea package, two access paths:
    • CI pushes to the internal endpoint 10.66.15.22:3000/bmr_bluecap/bcs-website (HTTP, fast, no edge). The runner host's dockerd trusts it via insecure-registries (managed in the gitea Ansible role + SIGHUP live-reload — no container restart).
    • k3s pulls the public HTTPS endpoint git.7tl-homelab.com/bmr_bluecap/bcs-website (valid TLS) → no registries.yaml, no node insecure config, no k3s restart.
    • .gitea/workflows/ci.yml uses PUSH_IMAGE (internal) and DEPLOY_IMAGE (public); the tag bump / k8s image ref use DEPLOY_IMAGE.
  • Pull auth via External Secrets: k8s/externalsecret-registry.yaml (ClusterSecretStore openbao-cluster, OpenBao KV v2 mount cluster, path bluecap-registry → fields username/password) materializes a kubernetes.io/dockerconfigjson secret gitea-registry; the Deployment references it via imagePullSecrets. No static secret in Git.
  • CI auth via a dedicated PAT CI_TOKEN (repo Actions secret; scopes write:package + write:repository) for both the registry push and the tag-bump commit-back — not the auto token.
  • Playwright e2e removed from CI (heaviest step, headless Chrome, unneeded for a static site). CI runs npm ci → build (typecheck) → seo:lint. Run e2e locally: npm run test:e2e.

Consequences

  • No cluster restart, no per-node registry config — deploys never disturb k3s.
  • Two tokens by role (least privilege): CI_TOKEN (write) as a repo secret; a separate read:package PAT in OpenBao for cluster pulls.
  • The internal-push insecure-registry trust is the one host-level bit (gitea role), needed only on the runner host, applied by live-reload.
  • Verified 2026-07-17: full loop green, 2/2 pods pulling the private image over HTTPS and serving.