Home/Quickstart
Quickstart

Protected in one config line.

Point your package manager at your Upwarden instance. Every install from then on flows through the firewall — malicious versions stripped, floating ranges rolled back to the last safe version, builds still green.

Upwarden Cloud is live. The endpoints below are real and ready — <ecosystem>.pkg.upwarden.io. You need a project API key (vk_…) from the dashboard first; every endpoint rejects unauthenticated requests.

Self-hosting is not available yet. Everything in this view is a preview of the planned setup, published so you can review the shape before it ships — not instructions you can follow today. Run it in your own network, with nothing leaving it: join the early-access list. To start protecting builds now, switch to .

1 · Get a project API key

Every Cloud endpoint requires one — an unauthenticated request is rejected, so this step is not optional. Create a key in the dashboard under your project's API keys, copy the vk_… value once (it is shown only at creation), and put it in the environment variable each config below expects.

In CI you do not need a key at all — setup-upwarden exchanges an OIDC token for short-lived credentials, so nothing long-lived is stored in your workflow.

2 · npm protocol — npm, bun, yarn, pnpm

One file covers all four; they read the same registry config.

.npmrc — npm, bun, pnpm, yarn
registry=https://npm.pkg.upwarden.io/
//npm.pkg.upwarden.io/:_authToken=${VG_NPM_API_KEY}

3 · Python — pip, uv

shell — pip, uv
$ export PIP_INDEX_URL=https://${VG_PYPI_API_KEY}@pypi.pkg.upwarden.io/simple/

Not pip.conf. pip does not expand ${VAR} inside its config file — environment variables and config files are separate mechanisms there, so a ${…} written into pip.conf is sent literally and the install fails. Use the shell form above, or paste the key into pip.conf in full.

4 · Rust — cargo

.cargo/config.toml — cargo
# The env var name is derived from the REGISTRY NAME below. Rename the
# registry and this must change with it: CARGO_REGISTRIES_<NAME>_TOKEN,
# uppercased with hyphens turned into underscores (my-reg -> MY_REG).
[source.crates-io]
replace-with = "upwarden"

[registries.upwarden]
index = "sparse+https://crates.pkg.upwarden.io/index/"
shell — the token cargo will send
$ export CARGO_REGISTRIES_UPWARDEN_TOKEN=${VG_CRATES_API_KEY}

The two names must match. Cargo derives the variable from the registry name in your config — call the registry something else and it becomes CARGO_REGISTRIES_<THAT>_TOKEN, uppercased with hyphens replaced by underscores — a registry named my-reg uses CARGO_REGISTRIES_MY_REG_TOKEN. Nothing on our side reads the variable; we only see the resulting header, so a mismatch looks exactly like a bad key.

A 401 after a working start is normal-looking and usually a typo. config.json is served anonymously on purpose, because cargo reads it before authenticating to discover whether auth is required. So a mistyped token gives you a successful bootstrap and then a 401 on the first real fetch — the registry is up; the credential is wrong.

5 · Go, Maven, NuGet & RubyGems

Same pattern — point each ecosystem's standard registry setting at its Upwarden endpoint:

  • GoGOPROXY=https://go.pkg.upwarden.io,direct
  • Maven — mirror https://maven.pkg.upwarden.io/maven2 in ~/.m2/settings.xml
  • NuGet — add https://nuget.pkg.upwarden.io/v3/index.json as a packageSource
  • RubyGems — point Bundler's mirror at https://rubygems.pkg.upwarden.io

Each takes the same credential as the ecosystems above. All get the same proxy, content scan, behavioral signals and silent rollback — Maven adds JVM bytecode analysis on top.

npm protocol — npm, bun, yarn, pnpm

Anything that speaks the npm registry protocol is covered. Set the registry once and every install resolves through Upwarden.

npm — global
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
$ npm config set registry https://upwarden.example.com/
.npmrc — per project (npm, pnpm, yarn classic)
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
registry=https://upwarden.example.com/
bunfig.toml — bun
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[install]
registry = "https://upwarden.example.com/"
.yarnrc.yml — yarn berry (v2+)
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
npmRegistryServer: "https://upwarden.example.com/"

bun is first-class. Because bun reads the standard registry config, it's covered exactly like npm — something wrapper-based tools don't offer. Private and scoped packages keep working: your existing tokens pass straight through to the upstream registry, untouched.

Python — pip, poetry, uv

Point the index URL at Upwarden's /simple/ endpoint.

pip — environment variable
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
$ export PIP_INDEX_URL=https://upwarden.example.com/simple/
pip.conf — persistent
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[global]
index-url = https://upwarden.example.com/simple/
uv
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
$ export UV_INDEX_URL=https://upwarden.example.com/simple/
poetry
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
$ poetry source add --priority=primary upwarden https://upwarden.example.com/simple/

Rust — cargo

cargo uses a sparse index. Replace crates.io with your Upwarden sparse endpoint in .cargo/config.toml.

.cargo/config.toml
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[source.crates-io]
replace-with = "upwarden"

[registries.upwarden]
index = "sparse+https://upwarden.example.com/cargo/"

Go, Maven, NuGet & RubyGems

These use the same pattern — point each ecosystem's standard registry setting at your Upwarden endpoint:

  • Go — set GOPROXY to your Upwarden Go endpoint.
  • Maven — add an Upwarden <mirror> in ~/.m2/settings.xml.
  • NuGet — add your Upwarden feed as a packageSource in nuget.config.
  • RubyGems — point Bundler's mirror at your Upwarden RubyGems endpoint.

All four get the same proxy, content scan, behavioral signals and silent rollback as npm and PyPI — Maven adds JVM bytecode analysis on top. Ask us for the exact per-ecosystem snippet for your setup.

Verify it works

Install anything. A normal, safe package installs as usual — the only added latency is a single proxy hop. To see the firewall act, request a version known to be blocked and watch it roll back:

terminal
$ npm install lodash
upwarden › lodash@4.17.22 — BLOCKED (malware signature match)
upwarden › resolving to last safe version → 4.17.21
added 1 package — lodash@4.17.21  ✓ build green

What happens on a block

  • Floating ranges (^1.2.0, ~=1.2, cargo semver) resolve around blocked versions automatically — silent rollback to the highest safe version.
  • Exact pins to a blocked version fail loudly with an actionable [UPWARDEN] message that names a safe version to use.
  • Lockfile installs keep working as long as the locked version stays safe. If it later becomes blocked, you get a clear error and a one-command fix.
  • Brand-new versions are quarantined and scanned. Requests are briefly held for a verdict; if none is reached, the request fails closed rather than letting an unscanned artifact through.
  • Registry downtime doesn't stop you — Upwarden keeps serving cached manifests, so builds keep working.
Get started

Keep your builds green and your malware out

Self-serve in a minute, or talk to us about an enterprise deployment.