Getting started
Haven serves three main use cases, and most organizations end up combining them:
- Publishing crates in a private registry, with guarantees for the people who depend on them: your customers and teams get versions that passed your policy gate, with SBOMs, attestations, and an audit trail behind every release.
- Consuming crates securely through a mirror of crates.io that applies your rules. Supply chain attacks arrive through the registry, so that is where the protection belongs: quarantine for fresh releases, advisory holds, license allowlists, and publisher trust, enforced before a crate can reach your builds.
- Hosting static files: versioned release archives, prebuilt binaries, and other artifacts that are not crates, behind the same gate.
The onboarding funnel walks you through the first three steps, then
asks which path your first registry takes. All three paths are below.
The examples use acme as the registry name and
https://haven.example.com as the Haven host; substitute your own.
1. Create an organization
Section titled “1. Create an organization”Sign up, then create your organization. Registries, tokens, members, and the audit log all belong to the organization.
2. Mint a token
Section titled “2. Mint a token”Cargo authenticates to Haven with a token, for publishing and pulling alike. The funnel mints one for you; outside the funnel, use your organization’s Tokens page. The token is shown once, at mint time. Store it somewhere safe. Tokens & access explains the scopes and the least-privilege options for CI.
3. Create a registry and choose its path
Section titled “3. Create a registry and choose its path”From the funnel (or the Registries page), create a registry. Two decisions happen here and both are permanent for the registry’s lifetime:
- Path: a publish registry (a registry for your own crates), a crates.io mirror (your gate on the open source you consume), or a static files registry (versioned files that are not crates).
- Visibility starts as private. You can flip it to public later; see Registries.
Path A: publish your crates
Section titled “Path A: publish your crates”Add the registry to .cargo/config.toml (the funnel and the
registry page show this snippet filled in with your real URLs):
[registries.acme]index = "sparse+https://haven.example.com/r/acme/index/"
[registry]global-credential-providers = ["cargo:token"]Store the token for that registry:
cargo login --registry acmePaste the token when prompted. In CI, set it through the environment
instead: CARGO_REGISTRIES_ACME_TOKEN (the registry name uppercased,
with - replaced by _). Then publish:
cargo publish --registry acmeThe new version appears on the registry’s crate page, and the funnel completes when it lands. If the registry has a policy, the version may start out held rather than available; that is the gate doing its job, not an error. See Policy overview.
To depend on it from another project using the same registry configuration:
[dependencies]my-crate = { version = "1", registry = "acme" }Path B: mirror crates.io
Section titled “Path B: mirror crates.io”First, set the policy: the mirror’s whole point is that its rules decide what your builds can pull. Open the registry’s Policy tab and pick your rules; quarantine, advisory holds, and publisher trust are the usual starting set. With no rules set, everything flows. See the Policy rules reference.
Then point cargo’s built-in crates.io source at the mirror in
.cargo/config.toml:
[registries.acme-mirror]index = "sparse+https://haven.example.com/r/acme-mirror/index/"
[source.crates-io]replace-with = "acme-mirror"
[registry]global-credential-providers = ["cargo:token"]Store the token (cargo login --registry acme-mirror, or the
CARGO_REGISTRIES_ACME_MIRROR_TOKEN environment variable in CI), then
fetch any project:
cargo fetchPlain serde = "1" dependencies now resolve through the mirror and
its policy, with zero Cargo.toml changes. The funnel completes on
the first tarball pulled through. One caveat: dependencies already in
cargo’s local cache are not downloaded again, so fetch in a project
whose dependencies are not cached yet. More in
Mirrors and Consuming crates.
Path C: host static files
Section titled “Path C: host static files”No .cargo/config.toml here; the client is curl. Upload a version’s
files, then publish the version:
curl -X PUT -H "Authorization: Bearer $HAVEN_TOKEN" \ --data-binary @some-file.tar.gz \ https://haven.example.com/r/acme/files/some-package/1.0.0/some-file.tar.gz
curl -X POST -H "Authorization: Bearer $HAVEN_TOKEN" \ https://haven.example.com/api/v1/registries/acme/files/some-package/1.0.0/publishThe funnel completes when the version is published. As with crates, CI can skip the stored token: trusted publishing mints one from the job’s own identity. Downloading takes the same token (or a narrower read token):
curl -L -O -H "Authorization: Bearer $HAVEN_TOKEN" \ https://haven.example.com/r/acme/files/some-package/1.0.0/some-file.tar.gzThe full lifecycle — drafts, licenses, yank, policy — is in Publishing files; resolution by version range and grants are in Consuming files.