Maintainers
These pages are for maintainers who cut releases or hold a release signing key.
- Releasing walks through the seven steps from the release PR to a published and verified release, and what to do when a step fails.
- YubiKey signing setup generates an OpenPGP key on a YubiKey, which it never leaves, adds it to the allowlist, and sets up registry access on the build server.
Operators install a release with Installing a release and read what changed in Release notes.
How a release is trusted
Only keys in .github/maintainer-gpg-keys/ on main can sign a release, one file per maintainer, named after their GitHub handle.
The same key signs the git tag and SHA256SUMS.asc, the detached signature over the checksums of the tarball and of the image digest.
One signature is required (MIN_SIGNATURES in etc/release.sh).
CI, the release scripts and the operator check in Installing a release read the allowlist from main, never from the tagged tree, so a tag cannot bring its own key.
Signing happens on a maintainer’s macOS laptop, with a key that was generated on a YubiKey and never leaves it.
Building happens on the build server, an Ubuntu or Debian Linux x86_64 host that holds the registry credential and never sees the YubiKey.
A release that passes make release-verify needs both machines: the build server builds and pushes the image, and the YubiKey signs the checksums.
The signature shows that a maintainer approved the files.
It does not show that they were built from the tagged source: release builds are not reproducible, and there is no SBOM or third-party build provenance.
The moving image tags :latest and :adiri are not signed, and whoever holds the registry credential can move them, which is why operators pin the digest from IMAGE_DIGEST.
Where things live
| Path | What it holds |
|---|---|
.github/maintainer-gpg-keys/ | The allowlist: one <handle>.asc public key per maintainer |
SECURITY.md | The maintainer release keys table that operators check fingerprints against |
CHANGELOG.md and cliff.toml | The release notes git-cliff generates from commit messages, and its configuration |
etc/release.sh | Every release step; the release-* Make targets call it |
Makefile | release-prep, release-tag, release-build, release-sign, release-verify, release-publish and docker-login |
.github/workflows/release.yaml | CI that validates a pushed tag, creates the draft release, and verifies a published release |
.github/ACTIONS.md | How CI works, including the release workflow and the attestation that the merge queue relies on |