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.
1. Create an organization
Section titled “1. Create an organization”Sign up, then create your organization. Namespaces, 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 namespace and choose its path
Section titled “3. Create a namespace and choose its path”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.
Path A: publish your crates
Section titled “Path A: publish your crates”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:
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 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" }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 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:
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.