The Deployer documentation
Connecting your accounts

Package repositories (Artifactory, Nexus, CodeArtifact...)

Some companies require every build to download its packages through a company package repository, such as JFrog Artifactory or Sonatype Nexus, instead of straight from npmjs.org, PyPI or Docker Hub. The repository keeps a copy of approved packages, blocks ones the security team hasn't allowed, and often holds the company's own private packages too. If your company works this way, you connect the repository once on the Connections page, and each project can then build through it.

Do I need this?

Most teams don't. If nobody at your company has asked you to download packages through a particular repository, skip this page: builds download from the public registries, and that works out of the box.

You need it when one of these is true:

  • Your security or platform team requires builds to use the company's approved packages.
  • Your app depends on private packages that only live in your company's repository.
  • Your builds run in a network that can't reach the public internet.

Package repositories are available on the Pro and Team plans. Only the workspace owner can add, change or remove one; everyone in the workspace can see which repositories exist and which projects use them.

Supported products

ProductHow it signs in
JFrog Artifactory (cloud or self-hosted)An access token, or a username and password
Sonatype Nexus Repository 3A username and password (or a user token)
AWS CodeArtifactYour connected AWS account, no token stored
Google Artifact RegistryYour connected Google Cloud account, or a service account key
Azure ArtifactsYour connected Azure account, or a personal access token with Packaging read
GitHub PackagesA classic personal access token with read:packages
GitLab Package RegistryA deploy token or personal access token
CloudsmithAn API token, or a username and password
Inedo ProGetAn API key, or a username and password
Container registries (Harbor, Quay, Amazon ECR, Docker Hub, GitHub Container Registry)A token or password, for base images only
Other (any repository that speaks the standard protocols, such as Verdaccio or devpi)A token, or a username and password

The kinds of packages a build can route through a repository are npm (and pnpm, Yarn, Bun), Python (pip, uv, Poetry), Maven and Gradle, Go modules, NuGet, RubyGems, Composer, Cargo, Dart and Flutter, Docker base images, Debian and Alpine system packages, and runtime downloads. Each product serves only some of these; kinds it can't serve keep using the public registry.

Use a read-only token. Builds only ever download. A token that can also publish or delete packages works, but the connect step may warn you about it. Nexus 2 has reached end of life and is not supported; connect Nexus 3 instead.

Connecting a repository

On the Connections page, scroll to Package repositories and click Add. A short window walks you through four steps.

  1. Choose. Pick your product. Not sure which one your company uses? Ask your platform team for "the URL we use for npm install".
  2. Connect. Give the connection a name and fill in only the fields your product needs: usually the address you open the repository at, plus a token. You don't need to work out the API path; The Deployer finds it. Under Advanced you can add a username and password instead of a token, your company CA certificate (if the repository uses a certificate your company issued), a proxy your builds must go through, and the Docker host format if Docker images live on a different address.
  3. Repositories. The Deployer lists the repositories your token can see and suggests one for each kind of package. If your token can't list repositories, type the repository key for each kind your builds use. Each row has a role:
    • Mirror: the repository also serves public packages, so it replaces the public registry for that kind. Artifactory virtual repositories and Nexus groups are mirrors.
    • Only our packages: the repository holds just your company's own packages. You name which ones it serves (for example an npm scope like @acme), and everything else still comes from the public registry.
    • Stays public: that kind of package keeps downloading from the public registry.
  4. Test. The Deployer downloads a real package through each repository you mapped and shows a result per row. Save becomes available once every routed row passes, or is set to Stays public.

Where an "Other" repository's token can go

For Other, you type the full address of each repository. The token is only ever sent to addresses under the connection's base URL, or to addresses the workspace owner has allowed for that connection. If you map an address outside those, the Test step asks for your account password to allow it; you can also change the list later with Allowed addresses on the connection's card (password required). A teammate who can change a project's settings can't send the token anywhere else, and a build whose mapping names an address that isn't allowed stops before the token leaves The Deployer.

Why some kinds can't be "Only our packages"

For npm, NuGet, Go and Docker, a package manager can be told "packages with this name come from this repository, and nowhere else". For Python, RubyGems, Cargo, Composer and (for now) Maven, there is no safe way to do that: a public package with the same name as one of yours could be installed instead. For those kinds, the window explains this and asks you to put your private packages behind your mirror repository instead.

Using your cloud account instead of a token

For AWS CodeArtifact, Google Artifact Registry and Azure Artifacts, the first option in the Connect step is Use my connected AWS / Google Cloud / Azure account. Pick the cloud connection you already added, and there is no token to store at all: each build gets a short-lived one from your cloud account (at most 12 hours on AWS, about an hour on Google Cloud and Azure).

Choose Use a token instead when the repository sits in a different cloud account from your connection, or when you'd rather store a token. For Azure Artifacts, the identity behind your Azure connection must be added to your Azure DevOps organization before this works.

When the repository isn't reachable from the internet

If your repository is only reachable inside your company network (over a VPN, a private link, or a private address), the Test step says so. That's fine: you can still save the connection, and you choose the network builds run in per project with Build location. Verification finishes the first time a build checks the repository from inside that network.

Using it in a project: Package sources

Connecting a repository doesn't change any project by itself. To use it, open the project, find the Build settings card on its dashboard, and click Change on the Package sources row. Pick the repository and a mode:

  • Use for dependencies. Language packages and base images go through your repository. Anything not mapped still uses the public registry. This is the right choice for most companies.
  • Private only. Everything goes through your repository. If a build would need to reach the public internet for anything, it stops before it starts, before anything is created in your cloud account, and tells you what isn't covered. Use this when your build network has no internet access at all.

With Private only, your project's servers also download their own system packages, Docker and tool images through the repository, so its settings and token are kept on each server. When the project stops being Private only (you switch to Use for dependencies, remove the repository from the project, or choose another), the next deploy puts each server's package settings back as they were and removes the token from it.

The panel shows which package managers were found in your project and where each kind of package will come from. Test routing checks each route before you save.

Every panel ends with the same two buttons:

  • Apply on next deploy saves the change; it is used the next time this project deploys.
  • Redeploy now saves it and redeploys straight away. The running version keeps serving until the new build passes its health check.

You can undo any time by switching back. That also takes effect on the next deploy.

When you deploy another service from the same repository as its own project, it starts with the same package repository, mode, build method and build location as the project you started from. If it builds inside your network, you confirm that location's cost for the new project before its first build.

Private only works best with a Build method of Auto or Dockerfile. Some buildpacks download language runtimes from the internet, so the panel offers to switch for you when the two don't fit together.

Package managers with extra requirements

Most package managers need nothing from you. These do, and the Package sources panel and the check before each build name them when they apply:

  • Python with uv or Poetry, in your own Dockerfile. uv sync --frozen (or --locked) downloads the files written in uv.lock, which point at PyPI, and poetry install doesn't take a package index from the build at all, so neither goes through your repository. Install an export of the lock instead, for example uv export --frozen --format requirements-txt --no-dev --no-emit-project -o /tmp/r.txt && uv pip install --system --require-hashes -r /tmp/r.txt, or poetry export --without-urls followed by pip install --require-hashes. A plain pip install -r requirements.txt needs no change.
  • Go without a go.sum. Go checks each module that isn't in go.sum against sum.golang.org. Commit go.sum, or map a Generic remote for sum.golang.org. On Nexus, turn off strict content type validation on that raw repository: the checksum database's files have no content type Nexus recognises.
  • PHP (Composer). A composer.lock written against packagist.org downloads each package from GitHub, whatever repository is set. Run composer update through your repository once, so the lock points at it. With no lock, Composer resolves through your repository directly.
  • Rust (Cargo) on Nexus. Turn on Require authentication on the Cargo repository. Without it, Nexus doesn't tell Cargo that crate downloads need a token, and every download is refused.
  • Yarn 1. The build sends your repository's credentials with every package download, including the ones yarn.lock lists, so a repository that refuses anonymous reads works.
  • Native Node.js modules (built with node-gyp). The build uses the Node.js headers already in the image, so nothing is downloaded from nodejs.org.
  • Dart and Flutter (pub). pub sends only access tokens, so the repository needs one (not a username and password), and pub trusts only the certificates built into the image, so a repository signed by your company's own certificate authority can't be used.
  • Buildpacks and PHP. The buildpacks builder has no PHP support: PHP apps build with the Dockerfile method.

Workspace policy

On the Package repositories section, the workspace owner can set a policy for every project:

  • Projects choose. Each project opts in on its own. This is the default.
  • On by default. New projects start with the repository turned on.
  • Required. Every project must use it. Members can't turn it off, and builds missing it are refused.

A policy change applies on each project's next deploy. Nothing redeploys when you change it. Under Required, a project's mapping must route every kind of package the project uses: a mapping that leaves one on the public registry is refused, and the message names what to map.

Keeping the token safe

  • Encrypted at rest, like every other connection.
  • Write-only. After you save it, the token is never sent back to the page. The card shows only a short masked hint. Viewing or replacing it needs your account password, as described in Viewing & replacing your credentials.
  • Never shown to AI models, and masked in build logs.
  • Never written into your app's image. Builds receive the token only while they download packages; it isn't left behind in any image layer, lockfile or your repository.
  • Your repository is never edited. Any package manager settings The Deployer needs are applied to the build's own copy of your code.
  • Replace before you revoke. When a token has to go, click Replace token first and redeploy the projects that use it, then revoke the old token in your repository. The redeploy writes the new token everywhere the old one was kept (including the servers of Private only projects), so nothing is left holding a token that no longer works.

When a build fails because of the repository

If a build fails because of your package repository, the deployment page shows a card that names the problem in plain words, with the raw log below it.

What the card saysWhat it meansWhat to do
(Repository) rejected the tokenThe token is wrong, expired or revokedClick Replace token. The new token is checked before it replaces the old one, so a mistyped token never breaks a working connection. Then click Redeploy now.
(Repository) token can't read what the build needsThe token works but can't read the repositories you mappedGive it read access in your repository, or replace it with one that has it. Open Package sources shows the mapping.
A package was blocked by your company's policyYour repository's security rules blocked a package this build needsPin a version your policy allows and push, or click Copy details for your platform team and ask them to allow it. The build log on the card names the package.
Not found in (repository)A package, version or image isn't there, or a repository name in the mapping is wrongClick Open Package sources and check the mapping
The build doesn't trust (repository)'s certificateThe repository uses a certificate your company issuedClick Add your company CA, add the certificate to the connection, then redeploy
The build couldn't reach your repositoryThe build couldn't reach the repository from where it runsCheck the address. If the repository is only on your company network, click Open Build location and choose Inside my network (Build location)

When a deploy fails this way, nothing new was put live: the version that was running keeps serving. On a phone, tap What to do at the top of the deployment page to see the card.

When to use what

If you...Choose
don't have a company package repositoryNothing. Skip it
have one and security wants approved packagesPackage sources: Use for dependencies
your build network can't reach the internetPrivate only, and Build location: Inside my network
the repository only accepts listed IP addressesBuild location with a fixed IP
have no Dockerfile and want a bill of materials and base-image patchesBuild method: Buildpacks
want everything routable with the fewest surprisesBuild method: Auto or Dockerfile
need every project in the workspace to complyWorkspace policy: Required

Removing a repository

Click the trash icon on the repository's card. The Deployer forgets the connection and its token; nothing in your repository changes. A repository that projects still build through can't be removed until those projects stop using it.

Registry logins for private base images

A package repository connection can also be used only to log in while a project builds, so the build can pull a private base image (for example FROM gcr.io/your-project/base). This is separate from routing: nothing is rewritten, mirrored or checked, and the project keeps downloading its packages the way it did. Bind the connection from the project's Build inputs and choose the registry hosts it is for. A login is sent only to the hosts its connection belongs to, is made fresh for each build, and is removed afterwards. See Build arguments and secrets.