rust-redist republishes official stable Rust distributions as maximum-
compression .tar.zst archives. Each GitHub release uses the original stable
Rust version, without a v prefix: 1.97.1, for example.
The uncompressed tar bytes are unchanged. Every archive is recompressed with the highest supported Zstandard compression level:
xz -dc official-component.tar.xz | zstd --ultra -22 -T2 -o official-component.tar.zst-22 is mandatory; -T2 limits each GitHub Actions worker to two compression
threads. GitHub Actions publishes a release only after every expected archive,
checksum, manifest, byte size, and GitHub-calculated SHA-256 digest has been
validated. Historical Rust releases that provide only a signed .tar.gz
archive use gzip -dc with the same zstd --ultra -22 -T2 command.
Every published release includes these Rust distribution packages when the official Rust channel manifest makes them available:
rustc,rustc-dev,cargo,clippy-preview,rustfmt-preview,rust-analyzer-preview, andllvm-tools-previewfor each supported host.rust-stdfor every supported Rust tier-1 or tier-2 target.- The platform-independent
rust-srccomponent. - The separately signed
rustc-VERSION-srccompiler source archive.
The six supported host triples match rules_rs exactly:
x86_64-unknown-linux-gnu
aarch64-unknown-linux-gnu
x86_64-pc-windows-msvc
aarch64-pc-windows-msvc
x86_64-apple-darwin
aarch64-apple-darwin
The 70 supported rust-std target triples also match
rules_rs/rs/platforms/triples.bzl exactly:
aarch64-apple-darwin
aarch64-pc-windows-msvc
aarch64-unknown-linux-gnu
i686-pc-windows-msvc
i686-unknown-linux-gnu
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
x86_64-unknown-linux-gnu
aarch64-pc-windows-gnullvm
aarch64-unknown-linux-musl
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
armv7-unknown-linux-gnueabihf
loongarch64-unknown-linux-gnu
loongarch64-unknown-linux-musl
i686-pc-windows-gnu
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
powerpc64le-unknown-linux-musl
riscv64gc-unknown-linux-gnu
s390x-unknown-linux-gnu
x86_64-apple-darwin
x86_64-pc-windows-gnullvm
x86_64-unknown-freebsd
x86_64-unknown-linux-musl
x86_64-unknown-netbsd
aarch64-apple-ios
aarch64-apple-ios-macabi
aarch64-apple-ios-sim
aarch64-linux-android
aarch64-unknown-fuchsia
aarch64-unknown-none
aarch64-unknown-none-softfloat
aarch64-unknown-uefi
arm-linux-androideabi
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv7-linux-androideabi
armv7-unknown-linux-gnueabi
armv7-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
i686-linux-android
i686-pc-windows-gnullvm
i686-unknown-freebsd
i686-unknown-linux-musl
i686-unknown-uefi
loongarch64-unknown-none
riscv32imac-unknown-none-elf
riscv32imc-unknown-none-elf
riscv64gc-unknown-linux-musl
riscv64gc-unknown-none-elf
sparc64-unknown-linux-gnu
thumbv6m-none-eabi
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
thumbv8m.main-none-eabi
thumbv8m.main-none-eabihf
wasm32-unknown-emscripten
wasm32-unknown-unknown
wasm32-wasip1
wasm32-wasip1-threads
wasm32-wasip2
x86_64-apple-ios
x86_64-apple-ios-macabi
x86_64-linux-android
x86_64-unknown-fuchsia
x86_64-unknown-none
x86_64-unknown-uefi
Older Rust releases do not necessarily contain every newer package or target.
The published manifest.json records the packages and targets actually
available in the signed official manifest for that Rust version.
Archive names preserve official Rust distribution basenames and replace only the compression extension:
rustc-VERSION-HOST.tar.zst
rustc-dev-VERSION-HOST.tar.zst
cargo-VERSION-HOST.tar.zst
clippy-VERSION-HOST.tar.zst
rustfmt-VERSION-HOST.tar.zst
rust-analyzer-VERSION-HOST.tar.zst
llvm-tools-VERSION-HOST.tar.zst
rust-std-VERSION-TARGET.tar.zst
rust-src-VERSION.tar.zst
rustc-VERSION-src.tar.zst
Every .tar.zst archive has an adjacent .tar.zst.sha256 asset. Each release
also contains:
manifest.json
manifest.json.sha256
SHA256SUMS
SHA256SUMS.attestation.jsonl
channel-rust-VERSION.toml
channel-rust-VERSION.toml.sha256
channel-rust-VERSION.upstream.toml
channel-rust-VERSION.upstream.toml.sha256
channel-rust-VERSION.upstream.toml.asc
manifest.json records the exact release inventory and the original and
recompressed SHA-256 digests:
{
"format_version": 1,
"rust_version": "1.97.1",
"release_date": "2026-07-16",
"compression": {
"format": "zstd",
"level": 22,
"arguments": ["--ultra", "-22", "-T2"]
},
"archives": {
"rustc-1.97.1-x86_64-unknown-linux-gnu.tar.zst": {
"sha256": "SHA256_OF_RECOMPRESSED_ARCHIVE",
"size": 123456789,
"source_sha256": "SHA256_FROM_SIGNED_UPSTREAM_MANIFEST",
"source_url": "https://static.rust-lang.org/dist/...tar.xz",
"component": "rustc",
"target": "x86_64-unknown-linux-gnu"
}
}
}channel-rust-VERSION.toml retains the official url, hash, xz_url, and
xz_hash fields and adds zst_url and zst_hash for every redistributed
archive. Consumers can prefer the .tar.zst archive while retaining the
official .tar.xz archive as a fallback for packages or versions that have not
been redistributed.
Release URLs use the stable bare-version tag:
https://github.com/hermeticbuild/rust-redist/releases/download/VERSION/manifest.json
https://github.com/hermeticbuild/rust-redist/releases/download/VERSION/channel-rust-VERSION.toml
https://github.com/hermeticbuild/rust-redist/releases/download/VERSION/rustc-VERSION-HOST.tar.zst
The GitHub Actions release workflow downloads the official Rust channel
manifest, its SHA-256 checksum, and its detached OpenPGP signature from
static.rust-lang.org. The workflow verifies the channel manifest checksum and
signature using the official Rust release signing key, pinned to SHA-256:
e54b09a439647e006b4831eec9785cbaaf3e07ab371c3a6ee6a68e1bdb9fbc6b
Every upstream component archive must match its SHA-256 digest in that signed
channel manifest. The separate rustc-VERSION-src.tar.xz or historical
.tar.gz archive additionally must match its published checksum and its own
detached OpenPGP signature. When the signed channel manifest records the
compiler-source digest, that digest must match as well.
channel-rust-VERSION.upstream.toml and
channel-rust-VERSION.upstream.toml.asc preserve the exact official signed
bytes. channel-rust-VERSION.upstream.toml.sha256 uses the verified upstream
digest but names the renamed local manifest, so ordinary checksum and
signature checks both work:
sha256sum -c channel-rust-VERSION.upstream.toml.sha256
gpg --verify \
channel-rust-VERSION.upstream.toml.asc \
channel-rust-VERSION.upstream.tomlThe rewritten channel-rust-VERSION.toml is not represented as an official
Rust-signed file; its separately named upstream manifest and signature are the
preserved official provenance.
GitHub Actions attests every archive and manifest listed in SHA256SUMS, not
just the SHA256SUMS file. Verify a downloaded archive against the provenance
stored by GitHub:
gh attestation verify rustc-1.97.1-x86_64-unknown-linux-gnu.tar.zst \
--repo hermeticbuild/rust-redist \
--signer-workflow hermeticbuild/rust-redist/.github/workflows/reusable-repack.yml \
--source-ref refs/heads/mainTo verify the release-provided attestation bundle instead, add
--bundle SHA256SUMS.attestation.jsonl to the same command. Each attestation
subject identifies the selected archive by its SHA-256 digest.
The release workflow creates an unpublished draft GitHub release for one stable
Rust version, distributes host packages and standard-library targets across
GitHub Actions matrix jobs, and uploads assets directly to the draft by its
numeric release ID. Every job uses zstd --ultra -22 -T2.
After all archive jobs finish, finalization generates a single attestation bundle for every checksum-listed archive and manifest and validates the complete asset inventory, every expected size, GitHub's SHA-256 asset digests, and all checksums. Internal plan and group-manifest assets are removed before the single operation that publishes the draft release. Interrupted runs leave an unpublished draft and can resume safely.
The scheduled workflow discovers the latest stable release from the official
rust-lang/rust GitHub release metadata. The backfill workflow enumerates
stable Rust releases in reverse semantic-version order, skips versions already
published by hermeticbuild/rust-redist, and republishes the remaining
versions newest first. Backfill defaults to Rust 1.80.0 and newer, runs one
Rust version at a time, and runs up to 16 archive groups concurrently. Each
validated release is immediately published as a non-draft GitHub release.
Before publishing, the workflow compares numeric stable
Rust versions and explicitly sets GitHub's make_latest=true only when the new
release is the newest published version. Older backfills use
make_latest=false, so they cannot replace a newer release as the latest
stable Rust version.
tools/github_release.py provides the draft-release operations used by GitHub
Actions:
python3 tools/github_release.py create \
--repository hermeticbuild/rust-redist --tag VERSION --target COMMIT_SHA
python3 tools/github_release.py upload \
--repository hermeticbuild/rust-redist --release-id RELEASE_ID FILE...
python3 tools/github_release.py download \
--repository hermeticbuild/rust-redist --release-id RELEASE_ID \
--name ASSET_NAME --output OUTPUT_FILE
python3 tools/github_release.py list \
--repository hermeticbuild/rust-redist --release-id RELEASE_ID \
--output ASSETS_JSON
python3 tools/github_release.py delete \
--repository hermeticbuild/rust-redist --release-id RELEASE_ID ASSET_NAME...
python3 tools/github_release.py publish \
--repository hermeticbuild/rust-redist --release-id RELEASE_IDcreate prints only the numeric draft release ID. upload, download,
list, and delete address draft releases by release ID because GitHub's
release-by-tag endpoint does not return drafts. Asset listings retrieve every
page, including releases with more than 100 assets. upload streams files
directly through gh api --input, replaces interrupted uploads safely, and
retries transient failures and GitHub rate limits without exposing
GH_TOKEN or GITHUB_TOKEN.