From 38b03c8ff078884552ee521d7623baf0fa249fa8 Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 4 Oct 2026 09:25:00 +0800 Subject: [PATCH] Deliver Kubernetes installation identity through its file contract --- .github/workflows/deploy.yml | 6 ++++-- deploy/kubernetes/README.md | 2 +- deploy/kubernetes/prod/core-env.yaml.tpl | 2 +- deploy/kubernetes/prod/core.yaml.tpl | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 543b01f9a..a7d9e8c7f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -334,12 +334,14 @@ jobs: digest="$(printf '%s' "$OAC_CORE_KEY" | sha256sum | cut -d' ' -f1)" printf '%s' "$OAC_DATABASE_PASSWORD" > "$work/database.password" printf '%s' "$OAC_CREDENTIAL_KEY" > "$work/credential.key" + printf '%s' "$OAC_INSTALLATION_ID" > "$work/installation.id" printf '["%s"]\n' "$digest" > "$work/core-key-digests.json" printf '%s' "$OAC_CORE_KEY" > "$work/core.key" kubectl create secret generic oac-core-secrets -n "$NS" \ --from-file="database.password=$work/database.password" \ --from-file="credential.key=$work/credential.key" \ + --from-file="installation.id=$work/installation.id" \ --from-file="core-key-digests.json=$work/core-key-digests.json" \ --dry-run=client -o yaml | kubectl apply -f - kubectl create secret generic oac-web-core-key -n "$NS" \ @@ -347,7 +349,7 @@ jobs: --dry-run=client -o yaml | kubectl apply -f - # shellcheck disable=SC2016 # envsubst takes the variable list literally - envsubst '$OAC_PUBLIC_URL $OAC_INSTALLATION_ID $OAC_DATABASE_URL' \ + envsubst '$OAC_PUBLIC_URL $OAC_DATABASE_URL' \ < deploy/kubernetes/prod/core-env.yaml.tpl > "$work/core-env.yaml" for name in OAC_HARNESSES OAC_DEFAULT_HARNESS OAC_EXECUTION_CONCURRENCY \ OAC_WRITE_AUDIT_RETENTION OAC_LOG_LEVEL; do @@ -359,7 +361,7 @@ jobs: # Core and Web read their environment and secret files once at startup. # This digest enters both Pod templates, so a settings or secret change # replaces the Pods even when the images are unchanged. - digest_input="$(cat "$work/core-env.yaml"; printf '%s' "$digest$OAC_DATABASE_PASSWORD$OAC_CREDENTIAL_KEY")" + digest_input="$(cat "$work/core-env.yaml"; printf '%s' "$digest$OAC_DATABASE_PASSWORD$OAC_CREDENTIAL_KEY$OAC_INSTALLATION_ID")" printf 'digest=%s\n' "$(printf '%s' "$digest_input" | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" - name: Roll out Core diff --git a/deploy/kubernetes/README.md b/deploy/kubernetes/README.md index 0ff917c31..54ccfd467 100644 --- a/deploy/kubernetes/README.md +++ b/deploy/kubernetes/README.md @@ -56,7 +56,7 @@ Restrict the repository’s `production` GitHub Environment to deployments from | `OAC_REGISTRY_HOST` | Registry host for `docker login` and the pull Secret. Optional; the host of `OAC_REGISTRY` by default | | `OAC_PUBLIC_URL` | The canonical HTTPS origin, such as `https://core.example`, with no path, query or fragment. Core derives the daemon WebSocket address, the sandbox `core_url` and the self-hosted `remote_url` from it, and Web serves only this origin. Without it Core executes no Session | | `OAC_DATABASE_URL` | `postgres://USER@HOST:PORT/DATABASE`, with `sslmode` and any `pool_*` parameter in the query and no password | -| `OAC_INSTALLATION_ID` | A canonical lowercase UUID, generated once with `uuidgen \| tr 'A-Z' 'a-z'`. Core refuses an ID other than the one its database recorded, so it belongs to the database: keep the two together and restore them together | +| `OAC_INSTALLATION_ID` | A canonical lowercase UUID, generated once with `uuidgen \| tr 'A-Z' 'a-z'`. The workflow writes it to `installation.id` in the Core Secret; Core reads `/run/oac/installation.id` through `OAC_INSTALLATION_ID_FILE`. Core refuses an ID other than the one its database recorded, so it belongs to the database: keep the two together and restore them together | | `OAC_NAMESPACE` | Existing namespace; `openagentcore` by default | | `OAC_STORAGE_CLASS`, `OAC_STATE_SIZE` | StorageClass and size of the required Core state volume. See [the state volume](#the-state-volume). `10Gi` by default | | `OAC_CLUSTER_UID` | UID of the target cluster’s `kube-system` namespace. The workflow verifies it before applying resources | diff --git a/deploy/kubernetes/prod/core-env.yaml.tpl b/deploy/kubernetes/prod/core-env.yaml.tpl index 67ac8d208..bf9be0267 100644 --- a/deploy/kubernetes/prod/core-env.yaml.tpl +++ b/deploy/kubernetes/prod/core-env.yaml.tpl @@ -13,7 +13,7 @@ metadata: data: OAC_ADDR: ":8091" OAC_PUBLIC_URL: "${OAC_PUBLIC_URL}" - OAC_INSTALLATION_ID: "${OAC_INSTALLATION_ID}" + OAC_INSTALLATION_ID_FILE: "/run/oac/installation.id" OAC_DATABASE_URL: "${OAC_DATABASE_URL}" OAC_DATABASE_PASSWORD_FILE: "/run/oac/database.password" diff --git a/deploy/kubernetes/prod/core.yaml.tpl b/deploy/kubernetes/prod/core.yaml.tpl index f0c03712b..17ce973ae 100644 --- a/deploy/kubernetes/prod/core.yaml.tpl +++ b/deploy/kubernetes/prod/core.yaml.tpl @@ -67,7 +67,7 @@ spec: chmod 700 /state/e2b chown 65532:65532 /run/oac chmod 700 /run/oac - for name in database.password credential.key core-key-digests.json; do + for name in database.password credential.key core-key-digests.json installation.id; do install -o 65532 -g 65532 -m 0400 "/run/oac-source/$name" "/run/oac/$name" done securityContext: