Sign and publish a release
renew reads a release manifest only once its minisign signature verifies against the public key the app carries. Publishing a release is four steps.
1. Make a key pair, once
Section titled “1. Make a key pair, once”minisign -GThis writes minisign.pub and a secret key (by default under
~/.minisign/). Keep the secret key off the server that hosts the releases.
The app carries the public key: the second line of minisign.pub, which
starts with RW.
const RELEASE_KEY: &str = "RWQ…";2. Put each binary where the app can fetch it
Section titled “2. Put each binary where the app can fetch it”Each platform gets the raw executable, not an archive, at an HTTPS URL. Take its sha256 and its size in bytes:
sha256sum app-linux-x86_64 # Linuxstat -c %s app-linux-x86_64
shasum -a 256 app-macos-arm64 # macOSstat -f %z app-macos-arm64An app that runs from a macOS .app bundle also publishes the bundle, after
it is signed, notarised and stapled, zipped with ditto so its signature,
links and extended attributes survive:
ditto -c -k --keepParent App.app App-macos-arm64.app.zipshasum -a 256 App-macos-arm64.app.zipstat -f %z App-macos-arm64.app.zip3. Write the manifest
Section titled “3. Write the manifest”{ "version": "1.1.0", "platforms": { "linux-x86_64": { "url": "https://example.com/app/1.1.0/app-linux-x86_64", "sha256": "…", "size": 10485760 }, "macos-arm64": { "url": "https://example.com/app/1.1.0/app-macos-arm64", "sha256": "…", "size": 9437184, "app": { "url": "https://example.com/app/1.1.0/App-macos-arm64.app.zip", "sha256": "…", "size": 12582912 } } }}The platform keys are linux-x86_64, macos-arm64 and windows-x86_64;
renew::platform_key() gives the running build’s key. Each sha256 is 64
hex digits and each size is above 0 and at most 512 MiB, or 1 GiB for an
app zip.
Formats has every field and limit.
4. Sign it and serve both files
Section titled “4. Sign it and serve both files”minisign -Sm manifest.jsonThis writes manifest.json.minisig next to the manifest. Serve both over
HTTPS, the signature at the manifest’s URL with .minisig appended:
https://example.com/app/manifest.jsonhttps://example.com/app/manifest.json.minisigSign again every time the manifest changes: renew verifies the signature over the exact bytes it fetched, so a manifest edited after signing is refused, even a change of whitespace.
Try it locally
Section titled “Try it locally”cargo run --example demo in a checkout does all four steps in a temporary
folder, with a key it makes on the spot, and serves the files from a local
port; plain http is allowed only to this machine. Its source,
examples/demo.rs, is a working publisher and client in one file.