Nix-free seed (stage0)
Goal: produce the first elpe binary (Rust backend elpe-server)
without Nix, from a content-hash-pinned toolchain. After stage0, elpe
rebuilds itself (build.ml → Rust.rust, toolchain from Ubuntu, crates
pinned by SHA256 in Cargo.lock). Full design + inventory:
../../../elpe.roadmap/project_nixfree_seed.md.
The one insight
Elpe already compiles its own Rust backend without Nix (build.ml,
elpe/lib/rust/rust.ml). rustc/cargo come from Ubuntu (rust.ml:661,663),
crates from crates.io pinned by SHA256 (rust.ml:8-17). The ONLY thing Nix
uniquely produces is the first elpe binary needed to run build.ml — a
chicken-and-egg. This directory pins the stage0 toolchain by hash so that
first binary can be built without Nix.
Trust roots (all content hashes)
| File | Pins | Status |
|---|---|---|
toolchain.lock | rustc/cargo/gcc/clang/libc6-dev/protoc (Ubuntu .deb, SHA256) | filled + verified (resolute 26.04 LTS, rustc-1.93; all 6 .debs fetched & hash-checked) |
sq.lock | sq binary (PGP verifier, src/lib.rs:580) | filled + verified (resolute pkg sq 1.3.1-6, src rust-sequoia-sq) |
crates.lock | 323 crate SHA256 — pointer to Cargo.lock (source of truth) | derivable, run extract-hashes.sh |
elpe.SHA256SUMS | pre-built seed elpe binary (option 1) | TODO — after reference build |
Usage
# 1. derive crates.lock from Cargo.lock (real values, no build needed)
./extract-hashes.sh
# 2. toolchain.lock + sq.lock are already filled & verified against Ubuntu
# resolute 26.04 LTS (PGP InRelease -> Packages.xz -> .deb sha256), matching
# rust.ml (rust_version=1.93, ~release:"resolute"). To refresh for a newer
# suite, re-run the fetch+verify and update the hashes/URLs + rust_version.
# 3. (human, on a clean Ubuntu box) build stage0:
./bootstrap-seed.sh # fetch+verify+extract pinned toolchain, build stage0
bootstrap-seed.sh refuses to run while any lock still has TODO. It cannot
be run in an agent fork (no building here).
Why not just cargo?
We use cargo build only for stage0 (to make the first elpe without a
pre-existing elpe). cargo is never used as the compiler afterwards: elpe’s
rust.ml calls rustc directly (rust.ml:348,360); cargo is only used for
cargo metadata --offline (rust.ml:168). So the cargo path here is the
bootstrap floor, not the steady state.