Skip to content

Getting started

Haven serves two main use cases, and most organizations end up doing both:

  • 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.

The onboarding funnel walks you through the first three steps, then asks which path your first namespace takes. Both paths are below. The examples use acme as the namespace name and https://haven.example.com as the Haven host; substitute your own.

Sign up, then create your organization. Namespaces, tokens, members, and the audit log all belong to the organization.

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.

From the funnel (or the Namespaces page), create a namespace. Two decisions happen here and both are permanent for the namespace’s lifetime:

  • Path: a publish namespace (a registry for your own crates) or a crates.io mirror (your gate on the open source you consume).
  • Visibility starts as private. You can flip it to public later; see Namespaces.

Add the namespace to .cargo/config.toml (the funnel and the namespace page show this snippet filled in with your real URLs):

[registries.acme]
index = "sparse+https://haven.example.com/ns/acme/index/"
[registry]
global-credential-providers = ["cargo:token"]

Store the token for that registry:

Terminal window
cargo login --registry acme

Paste 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:

Terminal window
cargo publish --registry acme

The new version appears on the namespace’s crate page, and the funnel completes when it lands. If the namespace 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" }

First, set the policy: the mirror’s whole point is that its rules decide what your builds can pull. Open the namespace’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/ns/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:

Terminal window
cargo fetch

Plain 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.