Skip to content

Change and release runbooks

These are the canonical change procedures. Every planned change records its approval, backup point, expected exit, and rollback boundary before execution. Use the flat operations.md headings only as compatibility forwarders.

Release verification

Procedure gate

Gate Contract
Classification Read-only
Prerequisites The tagged release artifacts, approved public verification key, target platform, and the change record.
Owner Release operator or supply-chain verifier.
Approval None to verify; deployment approval is required after all checks pass.
Backup point Preserve the prior running artifact and deployment manifest before replacement.
Command or check Run the signature, checksum, version, and SBOM checks below against the exact artifact set.
Expected status and exit Every invoked verifier exits 0, and the inspected version, target, signature, checksum, and SBOM agree with the release record. No deployment starts on a failed or mismatched check.
Stop condition Stop on a missing signature, unexpected signer, checksum mismatch, wrong tag, wrong target, or SBOM mismatch.
Recovery Quarantine the artifact set, retain the verification output, and obtain a fresh signed set from the release owner.
Rollback Keep the current deployment unchanged. Roll back only to the last independently verified artifact.
Escalation Escalate signature or provenance failures to security and release engineering.

Re-verify what will run. For highest assurance, rebuild from the tagged commit and compare the binary checksum with the published checksum.

Preflight verification signatures

Procedure gate

Gate Contract
Classification Read-only
Prerequisites cosign, the release public key, checksum file, checksum signature, and artifact directory.
Owner Supply-chain verifier.
Approval None for verification.
Backup point Preserve the downloaded checksum and signature before replacing them.
Command or check cosign verify-blob --key <release-public-key> --signature <checksums-signature> <checksums-file> followed by sha256sum -c <checksums-file>.
Expected status and exit Both commands exit 0. The second command reports every listed artifact as OK.
Stop condition Stop on any non-zero exit, missing artifact, or signer mismatch.
Recovery Delete or quarantine the set and redownload from the approved release channel.
Rollback N/A; no running service was changed.
Escalation Release security owner.

Bind the verification key to release tooling rather than a developer's local key. A checksum match without an authenticated checksum file is not release verification.

Reproducing the build

Procedure gate

Gate Contract
Classification Planned change
Prerequisites The exact tagged source revision, locked dependencies, pinned toolchain, target, and the release script.
Owner Release engineering.
Approval Change approval before using the rebuilt artifact for deployment.
Backup point Preserve the published artifact and its verification record.
Command or check Check out the exact tag in an isolated checkout and run ./scripts/release.sh; compare its generated checksum with the signed published checksum.
Expected status and exit The script exits 0; the rebuilt binary and published checksum match byte-for-byte for the same target.
Stop condition Stop on source, dependency, toolchain, target, path-remap, or checksum drift.
Recovery Recreate the isolated checkout from the tag and record the toolchain and environment difference.
Rollback Deploy the prior independently verified artifact, not an unmatched local rebuild.
Escalation Release engineering and supply-chain security.

The release recipe uses the pinned toolchain selected by CI, sets SOURCE_DATE_EPOCH from the tagged commit, and applies path-remap flags before producing the binary, checksums, and SBOM. The recipe does not promise a fixed timezone, locale, or unrelated container image.

SBOM

Procedure gate

Gate Contract
Classification Read-only
Prerequisites The signed CycloneDX SBOM, release version, and verified target-specific binary.
Owner Supply-chain verifier.
Approval None for inspection; approval is required before accepting a mismatch as an exception.
Backup point Preserve the SBOM with the artifact verification record.
Command or check jq -e '.metadata.component.name, .metadata.component.version, (.components | length)' <release-sbom>.cdx.json; compare the component name and version with the release record.
Expected status and exit jq -e exits 0, the component is gdsgate at the release version, and the component list is non-empty. A malformed or mismatched SBOM is a release failure.
Stop condition Stop deployment on a malformed, missing, or mismatched SBOM.
Recovery Obtain the SBOM paired with the signed artifact set.
Rollback Keep the current artifact until a matching SBOM is available.
Escalation Supply-chain owner.

The SBOM filename is versioned but not target-specific. Verify the target from the signed binary filename and release record; do not infer a target from the SBOM metadata.

Surviving a redeploy

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A verified replacement artifact, persistent store, node identity directories, CA trust, audit keys, and a maintenance window.
Owner Service owner and deployment operator.
Approval Change approval and backup confirmation before stopping the service.
Backup point Back up the store, external audit keys, node state_dir, and deployment manifest immediately before replacement.
Command or check Run gdsgate --config <config> doctor, then use the replacement's explicit service command, such as gdsgate --config <connector-config> connector.
Expected status and exit Doctor exits 0; the replacement stays active, preserves the identity, and later passes the verification procedure. A startup failure exits non-zero.
Stop condition Stop if the store is in-memory or unreachable, identity material is missing, schema is incompatible, or readiness does not become 200 after the role sets it.
Recovery Keep the old artifact and state, restore the previous process, and investigate without spending a new enrollment token.
Rollback Restart the last verified artifact against the unchanged persistent store and state directories. Do not downgrade a store schema that is ahead of the binary.
Escalation Service owner for identity or readiness, database owner for store, security for key loss.

Three things must outlive the process:

State Source location If it is ephemeral
Authority store store_url, defaulting to the persistent file under the home state directory The CA, registry, audit chain, catalog, and request state are lost or replaced.
Node identity [enroll].state_dir The key and leaf are lost. A spent join token is not a recovery path.
Renewal path [enroll].renew_endpoint, derived from the Authority endpoint when unset A valid identity cannot renew if its control-plane route is unavailable.

The background renewal loop renews over the existing mTLS identity only. It never falls back to a spent enrollment or join token. A lost state directory requires a deliberate fresh enrollment with a newly minted token.

One-time token exhaustion

Procedure gate

Gate Contract
Classification Incident action
Prerequisites Authority access, confirmation that the old token is spent or exposed, a persistent replacement state_dir, and the intended node role.
Owner Enrollment and security operator.
Approval Incident or enrollment approval before minting a replacement token; revoke or quarantine the old identity if compromise is possible.
Backup point Preserve the old node state and registry evidence before deleting or replacing anything.
Command or check gdsgate --config <authority-config> authority create-token --role <role>; start the node once with the token, then confirm its persistent identity and authority list-nodes --health.
Expected status and exit Token creation exits 0; the newly enrolled long-running service stays active with persistent identity. Subsequent restarts use mTLS renewal and do not consume another token.
Stop condition Stop if the node has no persistent state, the role does not match, or the old identity may be compromised. Never retry a spent token against another endpoint.
Recovery Install the new token through the approved secret channel, persist the state, and verify the registry row.
Rollback Stop the new node and revoke its identity if enrollment was incorrect. Do not restore or reuse the spent token.
Escalation Security for token exposure or identity compromise; Authority owner for registry refusal.

systemd

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A systemd unit, protected configuration, persistent StateDirectory, and a bootstrap token delivered outside the unit file where possible.
Owner Host and service operator.
Approval Change approval before editing the unit or restarting the service.
Backup point Save the prior unit, config, identity directory, and journal cursor.
Command or check systemctl daemon-reload && systemctl restart gdsgate-connector && systemctl is-active --quiet gdsgate-connector; then run the verification procedure.
Expected status and exit daemon-reload, restart, and is-active exit 0; the state directory remains the same across restart.
Stop condition Stop if the unit cannot access its persistent state or config, or if readiness and tunnel checks fail.
Recovery Restore the previous unit and config, reload systemd, and restart the last verified artifact.
Rollback systemctl stop gdsgate-connector, restore the saved unit/config, systemctl daemon-reload, then systemctl start gdsgate-connector.
Escalation Host owner for permissions and systemd, service owner for identity or protocol failures.

StateDirectory=gdsgate creates a persistent directory under the system state root. Point [enroll].state_dir at the persistent node directory. A bootstrap token is single-use and should not be left in a long-lived unit file.

Containers

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A verified image, mounted configuration, persistent state volume, external store or mounted store volume, and a deployment rollback revision.
Owner Container platform and service operator.
Approval Change approval before replacing the image or volume mapping.
Backup point Snapshot the store and persistent identity volume; save the prior manifest.
Command or check docker compose up -d connector or the equivalent platform rollout command, followed by docker compose ps connector and the verification procedure.
Expected status and exit The platform reports the container running; the process keeps its identity and the role checks pass. A restart must not create a new registry identity.
Stop condition Stop if state is mounted on the writable container layer, the store is in-memory, or the connector re-enrolls unexpectedly.
Recovery Restore the prior manifest and persistent volume mapping. Quarantine any newly created identity for review.
Rollback Roll back the image and manifest while retaining the persistent state and store backup.
Escalation Platform owner for volume or rollout failure, Authority/security for a new or revoked identity.

Mount configuration and identity material read-only where possible. Persist the store and audit keys separately. Expose only listeners required by the role.

Verifying

Procedure gate

Gate Contract
Classification Read-only
Prerequisites The replacement service is running, its config path, metrics address if enabled, and a controlled test resource.
Owner Service operator.
Approval None for health and controlled-session checks; approval is required before using a production resource for the test.
Backup point Preserve the pre-change doctor report, version, metrics snapshot, and audit cursor.
Command or check gdsgate --config <config> doctor; curl -sS -o /dev/null -w '%{http_code}\n' "http://${METRICS_ADDR}/healthz"; the same for /readyz; then gdsgate --config <operator-config> authority list-nodes --health.
Expected status and exit Doctor exits 0, liveness is 200, readiness is 200 only after the role sets it, and the node report shows the expected state. A controlled session opens and closes with an audit event.
Stop condition Stop traffic if doctor fails, readiness remains 503, node health is stale, or the controlled session does not produce the expected audit evidence.
Recovery Keep the replacement isolated, compare logs and configuration with the saved pre-change report, and restore the prior service if needed.
Rollback Use the surviving-redeploy rollback with the old artifact and unchanged persistent state.
Escalation Service, Authority, or database owner according to the failed check.

doctor is a read-only checklist. It can report an in-memory store, an ephemeral state directory, missing CA generation, schema drift, or an expired identity. It exits 2 for a failed check. The HTTP liveness and readiness endpoints are separate from the node health board.

Proxy restart behavior

Procedure gate

Gate Contract
Classification Incident action
Prerequisites Proxy logs and metrics, Connector fleet inventory, and a controlled session owner.
Owner Proxy operator during the restart incident.
Approval Incident authority before a deliberate restart; none for observing an unplanned restart.
Backup point Preserve the Proxy logs and metric snapshot before restart or failover.
Command or check Inspect gdsgate_active_connector_tunnels, reconnect, refusal, and duration metrics; run the controlled-session check after the Proxy is ready.
Expected status and exit Existing Proxy sessions end. Connectors redial with backoff and full jitter; the active tunnel gauge returns to the expected fleet and a new controlled session succeeds.
Stop condition Stop admission if tunnels remain absent, refusals rise, or the controlled session cannot open.
Recovery Wait for the reconnect loop within its bounded backoff, then inspect refusal reasons and Authority reachability.
Rollback Do not attempt session handover. Roll back the Proxy artifact or configuration only after capturing the incident evidence.
Escalation Proxy/network owner for relay failures; Connector owner for registration failures; Authority owner for authorization failures.

Proxy session state is in memory. No session handover occurs between Proxy processes. Connector control-plane tunnels reconnect automatically; a tunnel that stays up for at least 20 seconds resets its backoff schedule. The gauges and logs are the implemented signals; readiness alone does not prove a tunnel.

Renewing a listener certificate

Procedure gate

Gate Contract
Classification Planned change
Prerequisites The listener's configured certificate and key file pair, a validated replacement pair, filesystem permissions, and a rollback copy of the old pair.
Owner TLS or service operator.
Approval Change approval from the TLS owner before replacing a public or enrollment pair.
Backup point Keep the prior certificate and key pair together until the new pair is verified.
Command or check Atomically install the new pair, then systemctl reload gdsgate-proxy or kill -HUP <gdsgate-pid>; perform a new TLS client handshake against the listener.
Expected status and exit Reload exits 0 when the service manager accepts it. The next handshake presents the new pair; established sessions are not renegotiated.
Stop condition Stop if the pair cannot be parsed, the key does not match the certificate, or the listener logs listener certificate not reloaded.
Recovery Leave the previous pair in force, restore file ownership and permissions, and validate the pair offline.
Rollback Replace the certificate and key together with the saved prior pair, send SIGHUP, and repeat the handshake check.
Escalation TLS owner for material errors, service owner for listener failure, security for key exposure.

The file-backed listener pairs are:

Listener Pair
Proxy client-facing [proxy].public_cert_file and public_key_file
Proxy browser origin [proxy].web_cert_file and web_key_file
Proxy clientless browser [proxy].webapps_cert_file and webapps_key_file
Authority registration [authority].enroll_cert_file and enroll_key_file

The listener rereads a certificate and key as a pair. A malformed or mismatched pair leaves the previous working pair in force. SIGHUP rereads listener pairs only. It does not reload the TOML configuration, policy, listen addresses, transport identity, or trust bundle.

The clientless browser entry behind a front

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A front that sends PROXY protocol, an approved [proxy].webapps_proxy_protocol_from list, the browser certificate pair, and a controlled browser test.
Owner Proxy and front operator.
Approval Change approval from both front and service owners before enabling the list.
Backup point Save the prior proxy config and front routing configuration.
Command or check Validate the front configuration, restart or reload the front as approved, then open the browser entry from a listed and an unlisted source and inspect the Proxy log.
Expected status and exit A listed source with a valid header is served. A listed source without a header, or an unlisted source with or without a header, is closed.
Stop condition Stop before exposing the route if the front list is wrong, the header is missing, or an unlisted source is accepted.
Recovery Restore the prior list and front configuration, then retest direct and fronted paths.
Rollback Disable the setting and front together; do not leave only one half enabled on a live listener.
Escalation Front/network owner for header routing, Proxy owner for parsing, security for unexpected admission.

Set the front addresses in webapps_proxy_protocol_from. The observed source address binds the browser ticket and becomes context.src_ip. The default nobody is correct for a directly reached entry. An unreadable list stops startup rather than silently shortening the policy.

The public listener behind a front

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A front with PROXY protocol enabled, an approved [proxy].public_proxy_protocol_from list, a valid public listener pair, and a controlled external client.
Owner Proxy and front operator.
Approval Change approval from the network and service owners.
Backup point Save both front and Proxy configurations before changing either.
Command or check Validate the front's proxy_protocol on setting, apply the paired change, then run a TLS handshake and controlled login from the fronted path.
Expected status and exit Only a listed source carrying a valid header is served. single_port applies the same source rule to client and Connector tunnel traffic.
Stop condition Stop if either switch is enabled without the other, if a no-header path is accepted, or if context.src_ip is not the intended front address.
Recovery Restore the previous pair of configurations and close the public route until both sides agree.
Rollback Roll back the front and Proxy changes as one change.
Escalation Network owner for front behavior, Proxy/security owner for source-IP policy effects.

The public listener's source address affects certificate source-IP pinning, context.src_ip, audit src_ip, and anonymous rate-limit buckets. The join relay and connector-facing listeners are separate and are not covered by this front setting.

Store schema

Procedure gate

Gate Contract
Classification Planned change
Prerequisites A verified binary, store backup, exclusive change window, and a configuration with store_auto_migrate chosen deliberately.
Owner Database and Authority operator.
Approval Change and database approval before schema migration.
Backup point Take a paired store backup immediately before migration and record the binary version.
Command or check Set store_auto_migrate = false, run gdsgate --config <authority-config> authority migrate --check, then run gdsgate --config <authority-config> authority migrate once for the cluster.
Expected status and exit migrate --check exits 0 when current and 1 when migrations are pending. migrate exits 0 after applying pending migrations or doing nothing when current. Connectivity, lock, or unknown-applied failures are non-zero.
Stop condition Stop on an unknown-applied migration, a pending migration outside the window, a failed backup, or a migration error. Pending and unknown-applied are different stop states.
Recovery For pending state, run the matching migration command in the approved window. For unknown-applied state, use the newer binary or restore the pre-upgrade backup.
Rollback Migrations are forward-only. Roll back the binary only with a store backup whose schema is not ahead of it. Never delete migration rows.
Escalation Database owner for store or lock errors, release owner for binary/schema mismatch, Authority owner for service startup.

Each build carries its migrations. With automatic migration on, startup applies pending work after checking for unknown versions. With it off, startup refuses pending work and reports the command. The direct migration command does not require a running Authority and uses the same top-level store_url.

Concurrent migration runs

Procedure gate

Gate Contract
Classification Incident action
Prerequisites The active migration owner, PostgreSQL store access, and the pre-migration backup.
Owner Database operator.
Approval Incident or change authority before killing an active writer or retrying after a timeout.
Backup point Preserve the store state and migration logs before intervention.
Command or check Run gdsgate --config <authority-config> authority migrate --check; inspect the migration process and PostgreSQL lock state if the command waits.
Expected status and exit PostgreSQL migration lock wait is bounded at 120 seconds. One winner applies the DDL; a follower waits and then sees no pending work. A timeout exits non-zero with the lock error. SQLite uses its own single-writer behavior and does not use the advisory lock.
Stop condition Stop after 120 seconds or on an unknown-applied status. Do not run concurrent manual DDL.
Recovery Identify the active writer, let it commit or roll back, then rerun the read-only check.
Rollback Do not roll back by deleting migration rows. Restore the paired pre-change backup only under database authority.
Escalation Database owner and change authority.

Store schema ahead of the binary

Procedure gate

Gate Contract
Classification Incident action
Prerequisites The binary version, MigrationStatus output, and a backup made before the newer binary migrated the store.
Owner Release and database operators.
Approval Incident authority before restore or version replacement.
Backup point Preserve the current store before any attempted recovery.
Command or check Run gdsgate --config <authority-config> authority migrate --check and gdsgate --config <authority-config> doctor; inspect the unknown_applied report.
Expected status and exit Both checks report non-zero or a failed check identifying versions this binary does not know. The binary refuses to start or migrate that store.
Stop condition Stop the older binary. Do not force migration, remove rows, or call the state current.
Recovery Deploy the newer matching binary, or restore the backup from before the newer migration.
Rollback Restore the pre-upgrade store and the previous verified binary as a pair.
Escalation Release owner for version selection, database owner for restore.

The source distinguishes pending, meaning migrations carried by this binary are absent, from unknown_applied, meaning the store contains a version this binary cannot account for. Both are stop states, but only pending work can be applied by this binary.