Verifying a release
This page covers the customer-local bundle and the signed manifest that comes with it. The open source server has none of this: it is a public repository you clone and build, with nothing to verify and no credential to hold.
The point of the exercise is ordering. You verify the release before you hold a registry credential and before you extract anything of ours, so the check does not depend on anything we gave you except a signature you can trace to a public workflow run.
What a release is made of
Section titled “What a release is made of”Four files, published together in a per-version directory under /releases/.
| File | What it is |
|---|---|
metergraph-customer-local-<version>.tar.gz | The bundle: bin/, docker-compose.yml, .env.example. No images, no data, no credential |
metergraph-byoc-release.json | The manifest. It records the bundle’s SHA-256, both image repositories and their exact digests, and the platforms published for this release |
metergraph-byoc-release.json.sig | The detached signature over the manifest |
metergraph-byoc-release.json.pem | The certificate the signature was made with |
No account or credential is needed to fetch any of them, which is the whole design: the value is in the private images, so the thing that proves what the images are can be public.
Verify, then extract
Section titled “Verify, then extract”-
Install cosign
Section titled “Install cosign”Sigstore’s installation guide covers every platform. On macOS:
brew install cosign -
Download all four files
Section titled “Download all four files”base=https://www.metergraph.dev/releases/<version>curl -fsSLO "$base/metergraph-customer-local-<version>.tar.gz"for f in metergraph-byoc-release.json{,.sig,.pem}; do curl -fsSLO "$base/$f"; done -
Verify the manifest signature
Section titled “Verify the manifest signature”cosign verify-blob \--certificate metergraph-byoc-release.json.pem \--signature metergraph-byoc-release.json.sig \--certificate-oidc-issuer https://token.actions.githubusercontent.com \--certificate-identity-regexp '^https://github\.com/PioneerSquareLabs/metergraph-internal/\.github/workflows/byoc-release\.yml@refs/(heads/main|tags/v.+)$' \metergraph-byoc-release.jsonThis is keyless signing, so there is no public key to distribute and trust. What is pinned instead is the identity: the repository, the exact workflow file
byoc-release.yml, and GitHub’s OIDC issuer. Only the git ref is matched loosely, because a published release runs the workflow on its tag while the same workflow can be dispatched from the default branch.A signature made by any other workflow, in any other repository, fails here.
-
Check the bundle against the verified manifest
Section titled “Check the bundle against the verified manifest”The manifest records the bundle’s own checksum, so verifying the manifest also authenticates the archive. Read the expected value out of the manifest rather than off a web page, so the two cannot disagree:
python3 - <<'EOF'import hashlib, json, sysmanifest = json.load(open("metergraph-byoc-release.json"))name = manifest["local_bundle"]actual = hashlib.sha256(open(name, "rb").read()).hexdigest()if actual != manifest["local_bundle_sha256"]:sys.exit(f"{name} does not match the signed manifest. Do not run it.")print(f"{name} matches the signed manifest.")EOFReleases cut before the manifest carried
local_bundle_sha256have no bundle checksum to check. Their release page omits this step rather than describing a check the manifest cannot support. -
Extract, and move the manifest in beside it
Section titled “Extract, and move the manifest in beside it”tar xzf metergraph-customer-local-<version>.tar.gzmv metergraph-byoc-release.json* local/cd localThe three
metergraph-byoc-release.json*files must end up insidelocal/, next tobin/start. If they do not,bin/startstops witherror: metergraph-byoc-release.json not found.
From here, follow
the customer-local bundle:
registry login, .env, ./bin/start.
What bin/start verifies on every boot
Section titled “What bin/start verifies on every boot”The manual check above proves the archive. bin/start then repeats and extends
the proof each time it runs, using the same trust anchor.
- All three manifest files are present, or it exits before doing anything.
cosign verify-blobover the manifest, with the same issuer and identity pattern you used by hand.- Your host architecture is one of the manifest’s
local_platforms, so a release that was never published for this machine fails clearly instead of pulling something that cannot run. - Both image references are resolved from the manifest, and a reference is
refused unless the digest matches
sha256:plus 64 hex characters. A tag-shaped reference is a hard error. There is no fall back to a mutable tag, ever. cosign verifyon each resolved image, against that same identity.
Only then are the digests written to .images.env and handed to Compose, which
reads that file last so a stray METERGRAPH_APP_IMAGE in your .env cannot
override a verified digest.
The images stay private
Section titled “The images stay private”Verification tells you exactly which images you are about to run. Pulling them still needs the registry user and token that came with your invitation. Ask your Metergraph contact if you do not have them.
That split is deliberate. Everything needed to decide whether to trust a release is public. Only the artifact itself is not.