Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.46.0.
You have a candidate that serves with a local JWK signer. Move the same Evidence project to a Transit signer before it serves real callers: Vault or OpenBao holds the private key and never exports it, and Registry Evidence signs through a workload-local proxy socket. The service process receives no Vault or OpenBao token.
What you need
Section titled “What you need”- A Vault or OpenBao Transit mount administered outside the application workload, and an
authenticated operator session for it. The commands use a mount named
transit. - A copy of the release’s production example. Download the source archive of your release,
https://github.com/registrystack/registry-stack/archive/refs/tags/v<version>.tar.gz, where<version>is the versionrstack evidence --versionprints. It unpacks toregistry-stack-<version>/; copy itsproducts/evidence/reference/deployment-targets/environments/production/directory toproduction/beside your project. The copy holds the Transit policy, the proxy configuration, and the deployment targetproduction/evidence/target.yaml;<target>in the commands isproduction/evidence. - The
evidencecomponent installed forrstack, andjq.
Create the Transit key and its policy
Section titled “Create the Transit key and its policy”exportable=false and allow_plaintext_backup=false are one-way in the permissive direction: a
provider administrator can later set either to true, and Vault and OpenBao then refuse to set it
back. Registry Evidence refuses a Transit key unless both read false, so exporting the key retires
that key name for every version under it. The recovery path is a new key, never an export.
Confirm the provider’s own backup covers this mount before you create it.
Create a non-derived, non-exportable P-256 key with plaintext backup disabled:
vault write transit/keys/evidence-signing \ type=ecdsa-p256 \ derived=false \ exportable=false \ allow_plaintext_backup=falseRead its metadata to a review file and record the key version you will pin:
vault read -format=json transit/keys/evidence-signing > "<operator-review-path>/evidence-key.json"The proxy identity needs read on the key’s metadata and update on its sign endpoint, constrained to
the pinned key version and the exact JWS request shape. This is
production/transit/policies/evidence-signing.hcl, which pins key version 12:
path "transit/keys/evidence-signing" { capabilities = ["read"]}
path "transit/sign/evidence-signing/sha2-256" { capabilities = ["update"] required_parameters = ["input", "key_version", "marshaling_algorithm", "prehashed"] allowed_parameters = { "input" = [] "key_version" = ["12"] "marshaling_algorithm" = ["jws"] "prehashed" = [true] }}Registry Evidence sends key_version as a string because OpenBao matches allowed parameter values
by string. Keep the policy value quoted. The runtime also refuses a pinned key version below the
key’s min_encryption_version;
Rotate Registry Evidence signing keys uses that control. The
Vault Transit API and the
OpenBao Transit API document every other field;
use the equivalent bao commands for OpenBao.
Run the proxy with a forced token
Section titled “Run the proxy with a forced token”The proxy holds the provider credential and Registry Evidence holds only the socket. This is
production/transit/proxy-configs/evidence.hcl, without its pid_file and auto_auth method,
which you replace with your platform’s:
vault { address = "https://vault.example.org:8200" ca_cert = "/etc/registry-evidence/transit/ca.pem" retry { num_retries = -1 }}
api_proxy { use_auto_auth_token = "force"}
listener "unix" { address = "/run/registry-evidence/transit-proxy.sock" tls_disable = true socket_mode = "0660" socket_user = "vault" socket_group = "registry-evidence" require_request_header = true}Keep use_auto_auth_token = "force": the proxy replaces any token on an incoming request with its
own, so the proxy identity is the only one that reaches the provider through this socket. Under
true, a token supplied by whatever reached the socket would be used instead. num_retries = -1
makes one signing attempt one provider request, and the socket group admits only the Evidence
Gateway identity. The
Vault API proxy documentation
and the OpenBao Agent configuration describe
the rest.
Export the public JWK file
Section titled “Export the public JWK file”Convert the pinned key version’s public PEM from the review file into the target’s
public-keys/ directory:
jq -r '.data.keys["<key-version>"].public_key' "<operator-review-path>/evidence-key.json" \ | rstack evidence jwk from-pem - --output-dir "<target>/public-keys"wrote <target>/public-keys/<thumbprint>.jwk.json (kid <thumbprint>)The kid is the RFC 7638 thumbprint, and it names the public JWK file. The command refuses a
private key. Commit only the public JWK file, then delete the review file; do not commit provider
responses. Run rstack evidence jwk from-pem --help for the command reference.
Point the signer at the key version
Section titled “Point the signer at the key version”Replace the target’s signer block. This is the one in production/evidence/target.yaml:
signer: type: transit unixSocketPath: /run/registry-evidence/transit-proxy.sock mount: transit keyName: evidence-signing keyVersion: 12 attemptTimeoutMilliseconds: 2000 algorithm: ES256 publicJwkFile: public-keys/PSmhXYjoKCBO6gCOMNHqMvnnsAC3m0aaLfXZDWJLmd4.jwk.jsonkeyVersion must be the version the policy allows, and publicJwkFile the file jwk from-pem wrote.
Put no provider token or private key in the target.
Check, package, and activate
Section titled “Check, package, and activate”Check the project against the target for production:
rstack evidence check "<project>" --target "<target>/target.yaml" --productionEvidence project check: completeProject: <project>Target: <target>/target.yaml0 errors, 0 warnings in 1 filePackage the candidate. package runs the check and the fixtures again before it writes anything:
rstack evidence package "<project>" --target "<target>/target.yaml" --output "<candidate>"Package digest: sha256:<package-digest>Package: <candidate>/bundleRuntime: <candidate>/runtime.yamlAuthority: <candidate>/compiled-authority.yamlThe public JWK file goes into the bundle, and the socket, mount, key name, and key version go into
the candidate’s runtime.yaml. Install the bundle and activate the target authority as in
Build and deploy a Registry Evidence project.
Run doctor, then serve
Section titled “Run doctor, then serve”Start the proxy first. Then, on the target host, run doctor:
rstack evidence doctor --runtime-config "<candidate>/runtime.yaml"Doctor reads the key’s metadata, checks the custody fields and the key version, compares the provider’s public key with the public JWK file, and signs and verifies a self-test message. When the proxy is not answering, it refuses:
error[evidence.deployment.signing-unavailable] <candidate>/runtime.yaml runtime signing initialization failed: the Transit provider did not answer on the configured Unix socket (missing socket, refused connection, or timeout)When doctor passes, start the service with
rstack evidence runtime serve and route traffic only
after /ready reports
ready. If the provider becomes unreachable later, signing fails closed and readiness reports the
signer unavailable until a self-test succeeds. See
rstack evidence doctor --help.
Cookies on Registry Stack
We use optional cookies to understand how you use the main Registry Stack website and this documentation. If you contact us, we may link this activity to your enquiry. You can change your choice at any time. Read the privacy policy.
Your browser asks sites not to track you, so optional tracking stays off.
We could not use or save that choice. Optional tracking remains off.