RAILIANCE-WP-0011-T04: smoke checks unsigned 401, signed no-op 200, ESO Ready, and /v1/federated; point operator docs at platform rotation runbook.
215 lines
7.8 KiB
Markdown
215 lines
7.8 KiB
Markdown
# reuse-surface on railiance01
|
|
|
|
Federation service deployment for **`https://reuse.coulomb.social`**.
|
|
|
|
Companion workplans: **RAILIANCE-WP-0007** (Helm release), **REUSE-WP-0011**
|
|
(service + CLI).
|
|
|
|
## Hosts and DNS
|
|
|
|
| Server | IP | Role |
|
|
|---|---|---|
|
|
| **Railiance01** | **`92.205.62.239`** | Production k3s — **deploy here** |
|
|
| CoulombCore | `92.205.130.254` | Bootstrap / prerelease only |
|
|
|
|
| Record | Production target | Current public DNS (2026-06-15) |
|
|
|---|---|---|
|
|
| `reuse.coulomb.social` A | **`92.205.62.239`** | Propagated on 8.8.8.8 / 1.1.1.1; drop any AAAA/forwarding still pointing elsewhere |
|
|
| `hub.coulomb.social` A | `92.205.62.239` (future) | `92.205.130.254` (CoulombCore bootstrap OK for now) |
|
|
|
|
Let's Encrypt HTTP-01 on Railiance01 requires the public A record to reach
|
|
**`92.205.62.239`**. Service and TLS are live on the production cluster.
|
|
|
|
```bash
|
|
dig +short reuse.coulomb.social A
|
|
KUBECONFIG=~/.kube/config-hosteurope kubectl get certificate -n reuse
|
|
```
|
|
|
|
If DNS is being changed in the future, use an explicit resolve only during
|
|
propagation:
|
|
|
|
```bash
|
|
curl -k --resolve reuse.coulomb.social:443:92.205.62.239 https://reuse.coulomb.social/health
|
|
KUBECONFIG=~/.kube/config-hosteurope kubectl port-forward -n reuse svc/reuse-surface 18001:8000
|
|
export REUSE_SURFACE_URL=http://127.0.0.1:18001
|
|
```
|
|
|
|
## Release surface
|
|
|
|
| Item | Value |
|
|
|---|---|
|
|
| Namespace | `reuse` |
|
|
| Helm release | `reuse` |
|
|
| Chart | `charts/reuse-surface` |
|
|
| Values | `helm/reuse-surface-values.yaml` |
|
|
| Image | `gitea.coulomb.social/coulomb/reuse-surface:<tag>` |
|
|
| Landing image | `nginxinc/nginx-unprivileged:1.27-alpine` |
|
|
| Secret | `reuse-surface-env` (see [Runtime secrets](#runtime-secrets)) |
|
|
|
|
## Runtime secrets
|
|
|
|
Custody is OpenBao KV at
|
|
`platform/workloads/reuse/reuse-surface/runtime-secrets` on coulombcore
|
|
(`https://bao.coulomb.social`), delivered to the workload through External
|
|
Secrets (`ExternalSecret reuse/reuse-surface-runtime` → Secret `reuse-surface-env`,
|
|
`ClusterSecretStore openbao-reuse`). Lane: **CCR-2026-0005** /
|
|
**RAILIANCE-WP-0011**.
|
|
|
|
| Key | Required | Purpose |
|
|
| --- | --- | --- |
|
|
| `REUSE_SURFACE_TOKEN` | yes | Bearer token for hub write API (`POST /v1/repos`, compose, etc.) |
|
|
| `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` | for webhooks | HMAC secret for `POST /v1/webhooks/forgejo` (REUSE-WP-0019-T02) |
|
|
|
|
The chart injects both keys via `envFrom.secretRef` on the `reuse-surface`
|
|
Deployment. After patching the Secret, restart the Deployment so new values
|
|
are picked up:
|
|
|
|
```bash
|
|
kubectl --kubeconfig ~/.kube/config-hosteurope rollout restart deployment/reuse-surface -n reuse
|
|
kubectl --kubeconfig ~/.kube/config-hosteurope rollout status deployment/reuse-surface -n reuse
|
|
```
|
|
|
|
**Rotation** (never commit or paste values into chat):
|
|
|
|
Full procedure: `railiance-platform/docs/reuse-surface-runtime-secrets-rotation-runbook.md`
|
|
|
|
```bash
|
|
# After updating field(s) in OpenBao — force ESO sync, roll hub, reconcile webhook if needed
|
|
kubectl --kubeconfig ~/.kube/config-hosteurope annotate externalsecret \
|
|
reuse-surface-runtime -n reuse force-sync="$(date +%s)" --overwrite
|
|
make reuse-runtime-es-status
|
|
kubectl --kubeconfig ~/.kube/config-hosteurope rollout restart deployment/reuse-surface -n reuse
|
|
make reuse-forgejo-webhook # required when REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET changed
|
|
make reuse-webhook-smoke
|
|
```
|
|
|
|
One-time lane bootstrap (CCR-2026-0005):
|
|
|
|
```bash
|
|
make reuse-openbao-eso-token-apply
|
|
make reuse-runtime-es-deploy
|
|
make reuse-runtime-es-status
|
|
```
|
|
|
|
**Export for a shell session** (streams to your terminal only):
|
|
|
|
```bash
|
|
export REUSE_SURFACE_TOKEN=$(
|
|
bao kv get -field=REUSE_SURFACE_TOKEN \
|
|
platform/workloads/reuse/reuse-surface/runtime-secrets
|
|
)
|
|
```
|
|
|
|
Or proxy via ops-warden: `warden access reuse-surface-hub-write-token --fetch`.
|
|
|
|
**Break-glass** (OpenBao unreachable): read materialized Secret `reuse-surface-env`
|
|
via kubectl — see `ops-warden/wiki/playbooks/reuse-surface-hub-write-token.md`.
|
|
|
|
## Forgejo org webhook
|
|
|
|
Org-level push webhook on Forgejo (`coulomb`) triggers hub recompose when any
|
|
repo changes paths under `registry/indexes/`. The HMAC secret must match
|
|
`REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` in `reuse-surface-env`.
|
|
|
|
Requires a Forgejo admin API token at `/tmp/forgejo-tegwick-api-token` (or
|
|
`FORGEJO_ADMIN_TOKEN`). Idempotent setup:
|
|
|
|
```bash
|
|
make reuse-forgejo-webhook
|
|
```
|
|
|
|
Smoke (unsigned `401`, signed no-op `200`, ESO Ready, `/v1/federated`):
|
|
|
|
```bash
|
|
make reuse-webhook-smoke
|
|
```
|
|
|
|
Live status (2026-07-07): org webhook id `1` on `coulomb` →
|
|
`https://reuse.coulomb.social/v1/webhooks/forgejo`, push events only.
|
|
|
|
## Browser landing page
|
|
|
|
`https://reuse.coulomb.social/` serves a static no-login landing page from the
|
|
Helm-managed `reuse-surface-landing` Deployment and Service. It exists for
|
|
humans who open the hostname in a browser; it does not change the API service.
|
|
|
|
Ingress routing is intentionally split:
|
|
|
|
- HTTP `/` redirects permanently to `https://reuse.coulomb.social/`;
|
|
- HTTPS `/health` and `/v1/*` route to `svc/reuse-surface`;
|
|
- HTTPS `/` and other non-API browser paths route to
|
|
`svc/reuse-surface-landing`.
|
|
|
|
The rendered page includes `noindex,nofollow`, a short service description, and
|
|
links to `/health`, `/v1/federated`, and this operator runbook. It must not
|
|
include `REUSE_SURFACE_TOKEN` or any other runtime secret.
|
|
|
|
Rollback: set `landing.enabled: false` in `helm/reuse-surface-values.yaml` and
|
|
run `make reuse-deploy`; the ingress will return to routing all `/` traffic to
|
|
the API service.
|
|
|
|
## Deploy
|
|
|
|
```bash
|
|
# 1. Pin image tag in helm/reuse-surface-values.yaml
|
|
# 2. Ensure reuse-surface-env has both keys (see Runtime secrets above)
|
|
# 3. Production (Railiance01, defaults to ~/.kube/config-hosteurope)
|
|
make reuse-deploy
|
|
make reuse-forgejo-webhook # after webhook secret is in the cluster Secret
|
|
make reuse-status
|
|
|
|
# Restore kubeconfig from the node if missing:
|
|
# ssh tegwick@92.205.62.239 'sudo cat /etc/rancher/k3s/k3s.yaml' \
|
|
# | sed 's|127.0.0.1|92.205.62.239|' > ~/.kube/config-hosteurope
|
|
```
|
|
|
|
## Smoke checks
|
|
|
|
```bash
|
|
make reuse-smoke
|
|
curl -I http://reuse.coulomb.social/
|
|
curl -fsS https://reuse.coulomb.social/
|
|
curl -fsS https://reuse.coulomb.social/health
|
|
curl -fsS https://reuse.coulomb.social/v1/federated
|
|
|
|
export REUSE_SURFACE_TOKEN=$(kubectl --kubeconfig ~/.kube/config-hosteurope get secret reuse-surface-env -n reuse \
|
|
-o jsonpath='{.data.REUSE_SURFACE_TOKEN}' | base64 -d)
|
|
export REUSE_SURFACE_URL=https://reuse.coulomb.social
|
|
reuse-surface hub status
|
|
reuse-surface hub list
|
|
curl -fsS "$REUSE_SURFACE_URL/v1/federated" | jq '.capabilities | length'
|
|
```
|
|
|
|
Deployed image tag: see `helm/reuse-surface-values.yaml` (currently `e3ae22e`,
|
|
deployed 2026-07-07 for REUSE-WP-0019-T01/T02).
|
|
Dogfood: `reuse-surface` repo registered; federated index returns 61 capabilities.
|
|
|
|
**Known issue (found 2026-07-07, not fixed):** the public ingress serves
|
|
`GET /v1/*` correctly but 404s on the exact-path `/health` rule — Traefik
|
|
appears to shadow it with the catch-all `/` rule routed to
|
|
`reuse-surface-landing`. Confirmed NOT a pod/service problem: `/health`
|
|
works correctly via direct port-forward to `svc/reuse-surface`, and the
|
|
Deployment's own internal readiness/liveness probes (which hit `/health`
|
|
directly, bypassing ingress) pass fine — the pod is `1/1 Ready`. Only
|
|
public external monitoring against `https://reuse.coulomb.social/health`
|
|
is affected; real API clients using `/v1/*` are unaffected. Needs an
|
|
explicit Traefik router priority annotation (or a path-rule reorder) on
|
|
`charts/reuse-surface/templates/ingress.yaml` — deliberately not changed
|
|
here since it's a shared production ingress edit outside this task's scope.
|
|
|
|
## Operations
|
|
|
|
```bash
|
|
make reuse-logs
|
|
make reuse-status
|
|
```
|
|
|
|
Image promotion: build from `coulomb/reuse-surface`, push to Gitea OCI, update
|
|
`helm/reuse-surface-values.yaml` `image.tag`, then:
|
|
|
|
```bash
|
|
make reuse-deploy
|
|
```
|
|
|
|
Bootstrap copy on CoulombCore (`92.205.130.254`) was removed 2026-06-15 — use
|
|
`config-hosteurope` only.
|