Versions are SemVer. Releases are cut by FerrFlow from the Conventional
Commit history of main: a merged feat: or fix: produces the tag, the
CHANGELOG.md entry and the GitHub release, and the release builds and pushes
the image.
Images live at ghcr.io/ferrlabs/lfsx under three tags:
| Tag | Moves | For |
|---|---|---|
1.7.0 |
never | production, where an upgrade should be a deliberate change |
1.7 |
on every fix to that line | picking up fixes without picking up behaviour changes |
latest |
on every release | trying it out |
Every tag is a manifest list covering linux/amd64 and linux/arm64, so a NAS, a Raspberry Pi or
a Graviton instance pulls the right image without being told. Each one is scanned for known
vulnerabilities, has to answer /health before it is allowed out, and is then signed with cosign
and shipped with a CycloneDX SBOM.
Verifying what you downloaded
Every release ships four kinds of proof: a .sha256 beside each archive, a build provenance
attestation on each archive, a .sigstore signature bundle beside each archive, and a CycloneDX
SBOM per crate (lfsx-server.cdx.json, lfsx.cdx.json). They answer different questions.
The checksum proves the download survived the wire:
sha256sum -c lfsx-server-x86_64-unknown-linux-musl.tar.gz.sha256
The attestation proves the bytes were built by this repository's release workflow from a specific commit, which is the claim a checksum next to the artifact it checks cannot make:
gh attestation verify lfsx-server-x86_64-unknown-linux-musl.tar.gz --repo FerrLabs/LFSX
The signature bundle says the same thing without asking GitHub. gh attestation verify reads
GitHub's attestation store, so it needs GitHub to answer; the bundle beside the archive is checked
against the public transparency log by cosign alone:
cosign verify-blob lfsx-server-x86_64-unknown-linux-musl.tar.gz \
--bundle lfsx-server-x86_64-unknown-linux-musl.tar.gz.sigstore \
--certificate-identity-regexp '^https://github.com/FerrLabs/LFSX/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
The two identity flags are the point of the check: without them cosign confirms that somebody signed the bytes, not that this repository's workflow did.
The SBOM lists every crate in the build for scanners and licence tooling, and is attested the same way. The container image is verified separately: it is signed with cosign at push and its signature and SBOM live next to it in the registry.