The Secret VM Build System is a specialized Yocto-based build system designed for creating secure virtual machines, primarily used within the Secret Network ecosystem. This build system enables the creation of secure, attestable virtual machine images that form the foundation for confidential computing environments.
Built for the Secret Network, a privacy-first blockchain platform, this system ensures that computational environments maintain the highest standards of security and privacy. The build system leverages TEE (Trusted Execution Environment) technology and remote attestation to provide verifiable guarantees about the integrity and confidentiality of running environments.
Security Note: This build system is designed for production-grade secure environments. Proper handling of attestation keys and secure configurations is critical for maintaining the security guarantees.
- Docker
- Git
- 120GB+ free disk space
- Linux host system (recommended: Ubuntu 20.04 or later)
-
Clone the repository:
git clone https://github.com/scrtlabs/secret-vm-build.git cd secret-vm-build -
Initializes and updates all submodules:
git submodule update --init
-
Build:
scripts/build_reproducible.sh
Build artifacts are located in ./artifacts:
rootfs.cpio,rootfs.iso: Root file system for VMs without GPUrootfs-gpu.cpio.rootfs-gpu.iso: Root file system for VMs with GPUbzImage: Linux kernelinitramfs.cpio.gz: Initial RAM filesystemovmf.fd: UEFI firmware imageencryptedfs.qcow2: empty image for the encrypted file system
- Without GPU:
scripts/start_vm.sh
- With GPU:
sudo scripts/start_vm_gpu.sh
- Enable IOMMU in your host system
- Configure PCI pass-through in your VM launch script
- Use GPU-enabled image build
Each release published by .github/workflows/build.yaml carries a signed
SLSA v1 build-provenance attestation. It is stored in GitHub's
attestation API and also attached to the release as
provenance-<version>.sigstore.json.
Verification requires the GitHub CLI (gh >= 2.60). Verify an artifact you
downloaded from a release, constraining the signer to the build workflow:
gh attestation verify <artifact-file> \
--repo scrtlabs/secret-vm-build \
--signer-workflow scrtlabs/secret-vm-build/.github/workflows/build.yamlThis proves the artifact was built by this workflow, but does not by
itself bind the artifact to one specific release — if identical bytes ship
under more than one tag it may match another tag's attestation. To bind to a
specific release, add --source-ref refs/tags/<tag> and/or
--source-digest <commit-sha> (these two flags require gh >= 2.68; the
base verification commands above work on gh >= 2.60).
Offline / air-gapped verification, one artifact at a time, against the
attached bundle. --bundle supplies the attestation itself, but gh still
needs Sigstore's TUF trust root. On a machine that has run gh attestation verify online before, that root is cached and the command below works as-is.
For a truly air-gapped host, first export the trust root on an online
machine and carry it over:
# once, on an online machine:
gh attestation trusted-root > trusted_root.jsonl# offline, with trusted_root.jsonl alongside the artifact and bundle:
gh attestation verify <artifact-file> \
--repo scrtlabs/secret-vm-build \
--bundle provenance-<version>.sigstore.json \
--custom-trusted-root trusted_root.jsonl \
--signer-workflow scrtlabs/secret-vm-build/.github/workflows/build.yaml
--custom-trusted-rootis only needed when the cached TUF root is unavailable (a fully offline host); online and previously-cached machines can omit it.--signer-workflowis matched as a regular expression, andgh attestation verifyoperates on one file at a time (it does not accept file globs). Offline--bundleverification of a combined multi-subject bundle has hadghedge cases across versions; if it fails on a given release, verify online (omit--bundle) against GitHub's attestation store, which is the primary path.
This provides SLSA Build Level 2 at most: the provenance exists, is generated by the build service, and is signed by the build platform's identity (logged in Sigstore's transparency log). It does not reach Level 3 — the build runs on a self-hosted runner, which shares a trust boundary with the build job, so the provenance is authenticated but not isolated/unforgeable. Only the signing certificate and timestamps are non-manipulable; the predicate's contents are as trustworthy as the workflow that produced them.
Because the build runs on a self-hosted runner, do not pass
--deny-self-hosted-runnerstogh attestation verify— it will reject these otherwise-valid release attestations.
Runner prerequisite:
actions/attest-build-provenance@v4runs on Node 24, which requires the self-hosted build runner's Actions agent to be reasonably current (GitHub Actions runner ≥ v2.327.1). A stale runner will complete the multi-hour build and then fail at the attestation step — and because attestation gates the release, no release is published. Confirm the runner agent version (and outbound HTTPS to Fulcio/Rekor/Sigstore TUF + OIDC) before the next real tag.
Releases published before provenance was added can be attested with the
manual Backfill Provenance workflow. Backfill attests the digests of the
release-asset bytes as they exist at backfill time — it cannot prove how
those artifacts were originally built. Backfilled attestations are signed by
provenance-backfill.yaml and attached under a distinct asset name
(provenance-backfill-<tag>.sigstore.json, so they never overwrite a
build-time provenance-<tag>.sigstore.json). Verify them with:
gh attestation verify <artifact-file> \
--repo scrtlabs/secret-vm-build \
--signer-workflow scrtlabs/secret-vm-build/.github/workflows/provenance-backfill.yaml(Backfill itself runs on ubuntu-latest, so the runner prerequisite below
does not apply to it — only to the build workflow.)