Cargo-Rail removes compiler work at two boundaries. The planner first removes actions that a change cannot affect. The native cache then restores eligible rustc results inside the actions that still need to run. Local reuse requires no configuration. An optional S3 L2 lets CI runners and SSH build hosts exchange the same verified results.
This is compiler-result reuse, not a copied target/ directory. Cargo still owns fingerprints, build scripts still
run, and linker-producing invocations still execute. Every imported result must pass the same local proof as an L1 hit
before Cargo-Rail restores it.
L2 is deliberately strict. Two machines can share an action only when all action inputs match, including:
- the canonical physical source root;
- Cargo, rustc, rustdoc, sysroot, host, target, flags, and wrapper identity;
- bounded source and dependency contents; and
- every selected compiler-visible environment name and value.
Use the same canonical checkout path on compatible CI and SSH hosts. A symlink does not make different physical roots equivalent. Different operating systems, architectures, toolchains, source roots, flags, features, or selected environments produce different actions and compile normally.
One practical topology is:
| Machine | Canonical checkout | L1 | L2 authority |
|---|---|---|---|
| Developer laptop | Developer-owned path | Default user-wide CAS | Optional |
| Linux CI runner | /srv/rust/acme |
Runner-local CAS | read_write |
| Linux SSH builder | /srv/rust/acme |
Host-local CAS | read or read_write |
The CI and SSH rows can exchange results when their remaining action inputs match. The laptop still gets automatic L1 reuse, but its different physical root correctly prevents it from importing path-bearing CI artifacts.
Run an ordinary build action. Cargo-Rail enables native reuse automatically when it can prove the invocation is in the graduated class:
cargo rail doctor native-cache --format json
cargo rail run --all --action build --explain
cargo clean
cargo rail run --all --action build --explain
cargo rail cache status --scope local --format jsonThe second run starts with an empty Cargo target directory but can restore eligible compiler results from L1. A bypass is not a cache failure: it means Cargo-Rail could not prove that unit safe to reuse and ran the original compiler.
The local CAS defaults to cargo-rail/local-cas-v2 below the effective Cargo home. Set CARGO_RAIL_CACHE_DIR to move
it or CARGO_RAIL_CACHE_MAX_BYTES to change its positive result-byte limit. Treat L1 as one machine-owned authority;
share verified results through L2 instead of copying that directory between machines.
Select a machine target by alias in the tracked Cargo-Rail configuration:
[cache]
l2 = "team"On each machine, set CARGO_RAIL_CACHE_TARGETS_FILE to an absolute JSON file outside the checkout. The file identifies
the target but contains no credentials:
{
"version": 1,
"targets": {
"team": {
"protocol": "s3",
"region": "us-east-1",
"expected_bucket_owner": "123456789012",
"bucket": "company-cargo-rail-cache",
"prefix": "rust/team",
"role": "read_write",
"shareable_environment": ["CARGO", "CARGO_CRATE_NAME", "LANG", "PATH"]
}
}
}The complete schema, immutable protocol marker, conditional-write requirement, and minimum S3 authority are defined in Caching. Provision those controls before granting a build principal access.
shareable_environment permits named inputs to enter L2 identity; it does not ignore their values. The list above is
an example, not a universal allowlist. Use the smallest non-secret set required by the workspace. An action with a
selected name absent from the list stays local. Normalize every listed value across the machine images, including
PATH, or the actions will remain distinct and compile cold.
Credentials come from the standard AWS SDK chain. Use workload identity in CI and an instance profile on the SSH
host. Do not write AWS credentials into the target map, repository, workflow arguments, or SSH command. The two
machines may use different target maps for the same alias: for example, CI can use read_write while a production SSH
host uses read.
Validate configuration and credentials before the first build:
export CARGO_RAIL_CACHE_TARGETS_FILE=/etc/cargo-rail/cache-targets.json
cargo rail cache status --scope local --format json
cargo rail doctor native-cache --format jsoncache status validates the selected target without resolving credentials. doctor native-cache resolves credentials
and validates the remote protocol marker.
Give every compatible runner the same canonical checkout path and Rust toolchain. The checkout mechanism is CI-specific; assert the physical root before spending build time:
set -eu
expected_root=/srv/rust/acme
actual_root=$(pwd -P)
test "$actual_root" = "$expected_root" || {
echo "expected canonical checkout $expected_root, got $actual_root" >&2
exit 2
}
export CARGO_INCREMENTAL=0
export CARGO_RAIL_CACHE_TARGETS_FILE=/etc/cargo-rail/cache-targets.json
cargo rail doctor native-cache --format json
cargo rail run --merge-base --profile ci --explainFor GitHub-hosted or self-hosted Actions, record ${GITHUB_WORKSPACE} after resolving it physically and provision the
SSH checkout at that exact path. If a runner manager cannot guarantee one canonical path, keep its actions separate;
Cargo-Rail will use L1 locally and compile a distinct L2 variant instead of making different roots appear compatible.
The repository's cache qualification workflow is a complete GitHub Actions example of workload identity, a machine-owned target map, publication, empty-L1 import, and unavailable-L2 fallback. Keep third-party actions pinned when adapting it.
Provision the same repository at the CI root, install the same Rust toolchain and Cargo-Rail release, and attach an AWS instance profile scoped to the selected cache prefix. Then invoke the build through SSH:
ssh rust-builder -- 'set -eu
cd /srv/rust/acme
test "$(pwd -P)" = /srv/rust/acme
export CARGO_INCREMENTAL=0
export CARGO_RAIL_CACHE_TARGETS_FILE=/etc/cargo-rail/cache-targets.json
cargo rail doctor native-cache --format json
cargo rail run --all --action build --explain'Run the same commit when demonstrating a transfer. A different commit may still reuse unchanged dependency actions, but it is not a clean end-to-end proof of CI-to-SSH sharing.
Use this sequence after the target and principals are provisioned:
- Select a new empty
CARGO_RAIL_CACHE_DIRon each machine. This proves the transfer without deleting either machine's normal L1. - On CI, run the build with a
read_writetarget. The command admits verified local results before publishing immutable result packs and action associations. - On the SSH host, use the same commit, canonical source root, toolchain, flags, and selected environment. Start with an empty host-local L1 and run the same action.
- Inspect
--explain. The remote summary records authenticated requests and verified result-pack payload bytes; the unit evidence distinguishes hits, misses, and deliberate bypasses. - Run the command again on the SSH host with the same proof directory. Accepted L1 hits are network-free.
Give the SSH target read_write when results should also flow back to later CI runners. Use read when that host may
consume shared results but must not publish. A remote miss or unavailable service compiles cold. An integrity conflict
or malformed object restores nothing and requires operator investigation; build clients should not have list or delete
authority.
The first empty-L1 import includes S3 latency and payload transfer. Measure its remote request and payload counters on the intended hosts. Do not present local warm-L1 timing as remote first-import timing.
The native cache currently reuses graduated dependency and workspace-library compiler results. It deliberately bypasses
linker-producing binaries, tests, examples, and benchmarks; build scripts and generated output; proc-macro linking;
native dependencies and links contracts; rustdoc; cross compilation; and unmodeled configuration or environments.
That boundary is the point. Cargo-Rail claims a hit only when it can reconstruct and verify the exact result. Everything else stays on Cargo's normal path with a stable explanation.