Product

Overview

How it works Watch it work All 35 features Screenshots How ForgeRepo™ is secured

Keep bad packages out

Malware scanning Typosquat detection Dependency confusion protection Cooling off new releases Allow lists and block lists

When something goes wrong

Kill switch Who has it Lockdown and degraded modes Vulnerability monitoring

Developers and approvals

Requests and auto approve Check, walk and review Waivers Dry run
Formats

Languages

Private npm registry PyPI proxy and private index Private NuGet feed and proxy Maven repository proxy RubyGems mirror Composer and Packagist proxy

Apple, containers and Linux

CocoaPods CDN mirror Swift package registry Docker registry mirror RPM mirror for dnf and yum APT mirror for Debian and Ubuntu

Use it as

An npm firewall Artifacts, SBOMs and lifecycle More than one node SSO, roles and allow lists
Learn

Guides

Learn secure development Secure coding Secure pipelines Unsafe vs safe Security and development

Supply chain

Supply chain attacks, 2016 to 2026 Software supply chain security
Compare Side by side, all four ForgeRepo™ vs JFrog ForgeRepo™ vs Sonatype ForgeRepo™ vs Cloudsmith
Docs

Start

Getting started Download All documentation Questions

For developers

npm setup pip setup docker login Push a Docker image CI basics

For administrators

First setup Rules and their order Six incidents, walked through Backup and upgrade
Pricing Install it

Container images

Push an image

Push your own images under the names your admin reserved.

You can push when both of these are true:

  • Your role is publisher, approver or admin. A pipeline usually pushes with a token that belongs to a publisher account.
  • The image name is reserved for your company, like everything under acme/. A reserved name is never pulled from a public registry, so nobody can publish a lookalike with the same name and have it pulled instead.

Build the image with packages.example.com in front of its name, sign in with the publisher token, and push it:

Push an image
$ cat Dockerfile
FROM packages.example.com/node:22-alpine
WORKDIR /app
COPY server.js .
CMD ["node", "server.js"]
$ docker build -t packages.example.com/acme/storefront:1.4.0 .
...
#8 exporting to image
#8 exporting layers 0.0s done
#8 writing image sha256:a78fc97bb96fe2195e45b93ed7d0c17d03074f5b420ce002abf9c4a83600e8be done
#8 naming to packages.example.com/acme/storefront:1.4.0 done
#8 DONE 0.0s
$ echo "$PUBLISH_TOKEN" | docker login packages.example.com -u your-user-name --password-stdin
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores

Login Succeeded
$ docker push packages.example.com/acme/storefront:1.4.0
...
b28665727eef: Preparing
dbbe8cb33f3c: Preparing
8b919b825a05: Preparing
74d97c428c51: Preparing
74d97c428c51: Waiting
62c29257d759: Pushed
7528ea25b763: Pushed
b28665727eef: Pushed
dbbe8cb33f3c: Pushed
74d97c428c51: Pushed
8b919b825a05: Pushed
1.4.0: digest: sha256:84d369428612290a8cf291c891e4d93d2f8c501d7f4538171aef252687350889 size: 1571

Captured by running these commands against a real ForgeRepo™.

Tip

In a pipeline, keep the token in a secret variable like PUBLISH_TOKEN. Never put it in the repository or the Dockerfile.

What happens next

  • Every layer is scanned for malware before anyone can pull the image. Until the scan is done, a pull says toomanyrequests: ... is still being scanned for malware. Try again in a few minutes.
  • A layer the scanner flags is rejected, and a pull says what was found.
  • When malware scanning is switched off, an admin releases the image on the Quarantine page before anyone can pull it.
  • After that it pulls like any other image. In whitelist mode your admin adds an allow rule for your names.

A pushed tag never moves

Once a tag is pushed, it always means the same image, so the release you tested is the release that runs. Pushing different content under it is refused. Push the change under a new tag, like 1.4.1. The one exception is latest, which moves to whatever you push under it last.

Pushing other content under a tag that was pushed
$ docker push packages.example.com/acme/storefront:1.4.0
...
dbbe8cb33f3c: Layer already exists
74d97c428c51: Layer already exists
09952fac6131: Pushed
tag invalid: acme/storefront:1.4.0 was pushed before as sha256:84d369428612290a8cf291c891e4d93d2f8c501d7f4538171aef252687350889, and a pushed tag never moves. Push it under a new tag

Captured by running these commands against a real ForgeRepo™.

If the push is refused

Pushing without the publisher role
$ docker push packages.example.com/acme/storefront:dev
...
62c29257d759: Layer already exists
09952fac6131: Layer already exists
74d97c428c51: Layer already exists
denied: your-user-name cannot push here, it needs the publisher, approver or admin role

Captured by running these commands against a real ForgeRepo™.

The error saysWhat to do
cannot push here, it needs the publisher, approver or admin rolePush with a token owned by a publisher account, or ask an admin to change your role.
is not a reserved nameAsk an admin to reserve the name or a namespace like acme/*.
a pushed tag never movesPush under a new tag.
pushing needs a tokenRun docker login packages.example.com with your user name and a token as the password.
nothing is deleted through the registry herePushed images are kept. Push a new tag instead of replacing an old one.