FAQ

Answers to the questions people ask about Vega.

What is Vega?

Vega is a Nix binary cache whose globally-trusted entries are gated by independent reproduction and recorded in a public, append-only RFC 9162 Merkle transparency log, so you can verify them rather than trust the operator. See Why Vega.

How do I use Vega?

Add https://vega-cache.dev as a substituter and its public key to trusted-public-keys (see Configuration). To publish your own builds, use the vega CLI: nix run github:Ad-Astra-Computing/vega-agent#vega -- login then vega push (see Caching your builds).

Why use the vega agent? What is the benefit?

Consuming the cache needs no agent: just add https://vega-cache.dev as a substituter. The agent is for contributing and verifying. The GitHub Action builds in CI and attests over OIDC, uploading only novel paths; that is the path that can earn a place in the globally-trusted shared tier, via independent reproduction and distinct-owner agreement. vega push publishes an ad-hoc build to your own tenant namespace only (not the shared tier). And vega verify / vega mcp check a build's signature, transparency-log inclusion, and NAR hash on your own machine. So the benefit is caching your own packages, contributing CI builds toward the shared cache, and proof-checking dependencies rather than trusting the operator. See Caching your builds.

What does it mean to "attest" a build?

To attest is to make a signed, authenticated claim about a build result: "I built this derivation and got exactly this output," bound to the output's NAR hash. A CI attestation is authenticated by a GitHub Actions OIDC token (no stored secret); the claim, the output fingerprint, and the builder's identity are recorded in the public transparency log. An attestation is one builder's evidence, not yet shared-tier trust: the globally-trusted tier needs independent corroboration (distinct owners agreeing on the same output) plus Vega's own reproduction. See Reproducibility.

How do I verify a Vega build?

Run vega verify <hash>: it checks the cache's signature against a key you already trust, verifies the signed tree head and the build's RFC 9162 inclusion proof, and re-derives the NAR hash to confirm the bytes. To do it by hand, fetch the signed tree head at https://vega-cache.dev/log/sth, request an inclusion proof, and check the Merkle proof and tree-head signature yourself. See Transparency log.

How is Vega different from Cachix or a private cache?

With Cachix or a private cache you trust the cache owner: whatever their key signs, you install. Vega's shared tier instead requires independent reproduction plus agreement among distinct builders, and publishes a transparency log, so trust is derived from verification rather than from one key holder. See Why Vega.

How is Vega different from cache.nixos.org?

cache.nixos.org serves builds from the NixOS Foundation's trusted builders. Vega mirrors it and adds a shared tier whose entries are independently reproduced and transparency-logged, plus per-owner and scoped social trust.

Is Vega free?

Yes.

What does the Vega public key sign?

The global (shared) key signs a build only after Vega has independently reproduced it and it has cleared the promotion gates. Per-owner and per-consumer keys sign narrower scopes and are not globally trusted. See Reproducibility.

Why can't a self-hosted runner or my own machine push into the shared cache?

Because a host is controlled by its owner, so whatever it produces is only that one party's say-so, and it could be tampered with, misconfigured, or simply lie about what it built. Vega's whole promise is "verify, don't trust": a build joins the globally-trusted shared tier only after it is independently reproduced and distinct, separate owners agree on the exact same output. That agreement is what earns trust, not where the build was pushed from. A host can still publish to its own namespace (the tenant tier), which just means "this builder vouches for its own builds" and consumers can opt into that one builder; it cannot promote into the shared tier alone, because one owner-controlled machine is not independent evidence. See Why Vega.

How does a build reach the globally-trusted (shared) cache?

Your build starts in your own tenant namespace: just "this builder vouches for its own build." To cross into the shared tier the same output must be corroborated independently. Enough distinct, independent owners (different GitHub accounts, reputation-weighted) build the same derivation and attest the identical output, and Vega's own reproducer rebuilds it from source and gets the same hash. Only when that independent agreement and Vega's reproduction line up (after a settling window) does the master key sign it. The signature means "multiple independent builds of this source produced exactly these bytes," which anyone can re-derive. See Reproducibility.

Can I get my own package into the shared cache just by building it myself?

No. Building it yourself, however many times, only populates your own tenant namespace, because one party is still one party's say-so. The shared tier needs independent corroboration: other distinct owners building the same derivation and agreeing on the output, plus Vega's reproduction. A package only you build stays in your namespace, which is fine: anyone who chooses to trust you can use it directly. See Why Vega.

What is Sybil resistance, and how does Vega achieve it?

A Sybil attack is one actor posing as many independent builders to fake "independent agreement." Vega resists it on three fronts. First, the shared tier is gated by agreement among distinct GitHub owners, not by a count of attestations, so attesting your own build many times proves nothing. Second, every attestation is bound to a GitHub identity by Actions OIDC, which cannot be spoofed, and an attester's weight scales with GitHub account age: a brand-new account counts for about 1 and a long-established one is capped at 5, so cheaply spun-up identities do not buy a quorum (promotion needs enough reputation weight across distinct owners). Third, the master key signs only after Vega's own independent reproduction rebuilds the output from source and gets the same hash, which no external identity, real or fake, can fabricate. Faking consensus would require many old, distinct, reputable GitHub accounts, and still could not bypass Vega's own rebuild. See Reproducibility.

What is the Vega reproducer?

It is the independent rebuilder, the part that performs the "reproduced by Vega" check. Given an attested output's recorded provenance (its flake reference and locked revision), it re-evaluates and rebuilds from source and computes the NAR hash itself; that hash, not anyone's claim, is what the master key signs. Because the reproducer is a public, auditable repository, you can read exactly how Vega arrives at a shared signature rather than take it on faith. See Reproducibility.

What does the transparency log prove?

That every attestation is publicly recorded in an append-only Merkle log: inclusion proofs show a build is in the log, and consistency proofs show the log was only appended to, never rewritten. See Transparency log.

Why does the same output appear many times in the transparency log?

Because the log is append-only and records every attestation. Each CI run that builds an output adds a new entry, so a repository that rebuilds the same derivation on every push (and on both github-hosted and self-hosted runners) produces one log entry per run for that store-path hash. They are not duplicates: the log is the full, ordered audit trail, and the repeated entries are exactly how you watch a build reproduce over time. The output's /status page collapses them into the current verdict and the count of distinct agreeing builders. See Transparency log.

Why does a self-hosted GitHub Actions build show as gh-actions in the log?

The gh-actions lane means a GitHub Actions OIDC token attested the build's workflow identity, which holds whether it ran on a github-hosted or a self-hosted runner. Where it ran is a separate attested field, shown as github-hosted or self-hosted in the transparency log. A self-hosted entry is a real attestation and publishes to its own tenant tier, but because a self-hosted runner is owner-controlled, only github-hosted builds count toward the distinct-owner quorum that promotes an output to the shared tier.

Can AI coding agents verify builds with Vega?

Yes. vega mcp runs a local, read-only MCP server exposing vega_verify (signature + transparency-log inclusion + NAR re-derivation), vega_risk (an allow/warn/deny gate with proof-backed reason codes), and vega_reproduce (a read-only query of whether Vega has independently reproduced the build), and vega_assess_change (one allow/warn/deny over the store paths a change adds), so an agent can check a dependency, or a whole change, before it installs or builds it. The verify and risk checks run on your machine against a key you trust, not on Vega's say-so; the reproduction query reports what Vega has already recorded.

Do I need to install the Vega GitHub App?

Caching runs over your workflow's OIDC token (permissions: id-token: write), so builds are uploaded and attested without the App. Install the Vega GitHub App to get the Vega check on each attested commit: it is the visible confirmation of what was cached and links to the build's status page. Recommended as the last step of setup. See Caching your builds.

Does Vega record where I build from?

By default each attestation records the builder's continent, and only the continent: never a city, precise location, or IP. It feeds the aggregate "N continents" independence signal and the k-anonymous Network Health view, never a per-builder location. It is on by default; set privacy.continent: false in your vega.yaml to opt out, after which you are recorded as unknown and excluded from every geographic aggregate.

How do I check a build's status?

Every output has a status page at https://vega-cache.dev/status/<hash> (the 32-character store-path hash): reproducible, diverged, uncorroborated, mirrored, or unknown. There is an embeddable badge at https://vega-cache.dev/badge/<hash>.svg, and when the Vega GitHub App is installed, each attested commit gets a check linking to its status page. See Transparency log.

What does "(insufficient)" mean, and why does the agent print "0/N published to the shared cache"?

Each path tagged [tenant] was attested and signed into your own tenant namespace (tenant/<owner>/<repo>): that succeeded, and anyone who trusts your tenant key can substitute it. (insufficient) means the path's evidence has not yet met the bar for shared-tier promotion: distinct-owner agreement on the same output fingerprint, plus Vega's own independent reproduction. With a single builder's attestation, none of those is met, so each path is correctly held at tenant tier. "0/N published to the shared cache" is the expected result for one builder with no independent corroboration, not an error. ("Resumed: N already uploaded" just means the NARs were already in the cache from a prior run, so the agent re-attested without re-uploading.) If a package is only ever built by you, it stays tenant-tier until another independent owner builds and agrees on the same output and Vega reproduces it. See Reproducibility and Caching your builds.

Why does a status page show "cache absent"?

It means Vega has a trust record for the path (an attestation or pending entry) but is not currently serving a signed narinfo for it in the shared cache. The path is attested but not promoted to a fetchable shared entry (for example awaiting corroboration, or published only to a tenant scope), or a shared binding was revoked. It is a status, not an error: the build is still cached and usable from your tenant tier. See Reproducibility.

Can I cache and reproduce a flake that lives in a subdirectory?

Yes. If your repository keeps its flake in a subdirectory (for example a monorepo with one flake per host), point the build at that subdirectory in the installable: ${{ github.workspace }}/sub#attr. Vega records the subdirectory in the build's provenance (?dir=sub) and the reproducer rebuilds it from there as github:<owner>/<repo>/<rev>?dir=sub#attr, so a subdirectory flake reaches the same trust tiers as a root flake. The subdirectory is honored only on the repository's own canonical github reference at an immutable commit, and the reproducer rejects a symlinked component so it cannot escape the pinned source. Earlier such a build was treated as foreign and stayed at the tenant tier. See Caching your builds and Reproducibility.

Can I trust specific builders directly?

Yes. Beyond the globally-trusted shared tier you can trust individual builders, scoped to all their builds, a single package, or a flake/org (the last two match only a build with verified github-hosted CI provenance), with vega trust add <github-login>. vega view then gives you a personalized /u/<token> substituter that serves the shared cache plus anything your trust graph resolves, re-signed with a key only you trust. Trust is revocable and never propagates. See Social trust.

Can I use a build before Vega has reproduced it?

Yes, that is the point of social trust. The shared tier waits for Vega's independent reproduction and distinct-owner agreement, but you do not have to: vega trust add <login> tells your view to serve that builder's outputs immediately, re-signed with a per-consumer key only you trust. It decouples "can I use this build" from "has Vega reproduced it yet," so you can pull a teammate's or a trusted org's build the moment they publish it. Reproduction still proceeds in the background (and requesting a build you trust nudges it up Vega's queue); if Vega later rebuilds it and gets a different hash, that binding is withheld, and if the builders you trust disagree on a path it is withheld too. So social trust is fast and opt-in, while the shared tier remains the verified-by-reproduction default. See Social trust.

If I trust another builder, how do I get their cache?

You do not add their cache as a substituter or import their key. Your personalized /u/<token> substituter (from vega view or the dashboard) is the single front door: it serves the globally-trusted shared cache plus any binding your trust graph resolves. When you request a path that is not in the shared tier, Vega checks the builders you trust; if a trusted builder published it in scope and the trusted builders for that path do not disagree, Vega re-signs that one binding with a per-consumer key only you trust. You keep just two keys in trusted-public-keys: your own view key and the shared key. The other builder's key and substituter stay invisible to you, and a binding resolved for you is signed for you alone. See Social trust.

How do I find builders to trust?

You trust a GitHub identity, so you can start from builders you already know. To discover and evaluate others, a path's status page (https://vega-cache.dev/status/<hash>) lists who attested that exact output, the transparency log records every attestation, and a builder's profile (https://vega-cache.dev/builder/<id>) shows their standing: outputs attested, how many were independently corroborated, and how many diverged. Judge a builder by independent corroboration, not by how many builds they push, then vega trust add <login>. See Finding builders to trust.

How do I report a security issue?

Email [email protected]. A machine-readable contact is published at https://vega-cache.dev/.well-known/security.txt (RFC 9116).

Canonical endpoints

WhatWhere
Substituterhttps://vega-cache.dev
Public keysee Configuration
Signed tree headhttps://vega-cache.dev/log/sth
Inclusion proofhttps://vega-cache.dev/log/proof/inclusion/<index>
Consistency proofhttps://vega-cache.dev/log/proof/consistency?first=<m>&second=<n>
Human transparency loghttps://vega-cache.dev/log