OrbitalReg
Sign in →

Registry formats · Docker / OCI

A self-hosted container registry that looks inside your images.

Push your own images, cache Docker Hub, GHCR and Quay, and serve all of it from one hostname in your own cluster. OrbitalReg speaks OCI Distribution 1.1 and the Docker Registry v2 API, keeps cosign signatures and SBOMs next to the images they describe, and scans image layers with Trivy and Grype. Your images live in the same registry as the npm, Maven and PyPI packages they are built from.

Try it free for 30 days → Read the Docker docs ↗

Nothing new to learn

docker login, push, pull.

Every image lives at <host>/<project>/<repo>/<image>:<tag>. A local repository takes your pushes, a remote repository caches an upstream registry, and a virtual repository puts both behind one name. The first member that has the image answers.

Because the wire protocol is the standard one, CI jobs, build tools and clusters only need a new hostname and a token.

# log in with a token
$ echo $ORBITALREG_TOKEN | docker login registry.example.com \
    -u $ORBITALREG_USER --password-stdin

# push your own image into a local repo
$ docker tag my-app:1.4.0 registry.example.com/acme/internal/my-app:1.4.0
$ docker push registry.example.com/acme/internal/my-app:1.4.0

# pull Docker Hub images through the cache
$ docker pull registry.example.com/acme/dockerhub/library/alpine:3.20
# sign it; the signature is stored as an OCI referrer
$ cosign sign registry.example.com/acme/internal/my-app@sha256:…

# list everything that refers to that digest
GET /v2/acme/internal/my-app/referrers/sha256:…

Docker Hub mirror

Fetch each layer once. Keep serving when the upstream doesn't.

A remote repository fetches every manifest and blob from upstream the first time it is asked for and serves it locally after that. Digests never expire. Tags are re-checked at most every five minutes by default, so a busy CI fleet asking for node:22 all day costs a handful of upstream requests instead of thousands.

If Docker Hub fails while a tag is being refreshed, you get the copy OrbitalReg already holds rather than a broken build. Store Docker Hub credentials on the repository and upstream requests are authenticated. In air-gapped installs, upstream access stays blocked unless you allow egress for that one remote repository.

# remote repo "dockerhub" → https://registry-1.docker.io
docker pull …/acme/dockerhub/library/node:22
  manifest   cache miss  → fetched upstream, stored
  layers     cache miss  → fetched upstream, stored

docker pull …/acme/dockerhub/library/node:22   # 2 min later
  manifest   tag fresh   → served locally
  layers     cached      → served locally

docker pull …/acme/dockerhub/library/node:22   # upstream down
  manifest   upstream error → last known copy served

What you get

A container registry with the security layer in the free version.

OCI Distribution 1.1 and Docker Registry v2

The full v2 API, including chunked uploads and cross-repo blob mounts. Tools that work with Docker Hub, GHCR or Harbor work unchanged: docker, buildx, podman, skopeo, crane, containerd. Multi-arch manifest lists are stored as pushed, never flattened.

Signatures and SBOMs live next to the image

Manifests pushed with a subject (cosign signatures, SBOMs, in-toto attestations) are indexed at push time and served through the OCI 1.1 Referrers API, with the OCI-Subject header clients look for. Older tooling that uses the sha256-<digest>.sig tag scheme keeps working.

Scans the layers, not the manifest

Switch on Trivy and Grype for a project and every pushed image is scanned as an image: OS packages and the libraries inside its layers, one platform at a time. The scan reads the blobs OrbitalReg already holds, so it needs no network access once the vulnerability databases are local.

Auto-quarantine on findings

Opt a project into auto-quarantine and set a severity threshold. A finding at or above it blocks the image digest within one five-minute sweep, and every docker pull of it is refused with an explanation while the block is in place.

Block an image everywhere by digest

A sha256 security block applies to the manifest and to every blob request, on local, remote and virtual repositories alike. That includes images that only ever came through the Docker Hub cache.

A pull-gate in front of docker pull

Optional and off by default. Before an image you host is served, the gate can check its worst open CVE severity, whether it has an SBOM, and your own Rego rules. Blocked pulls get a 403 that says why.

Who pulled which digest

Every manifest pull of an image you host is recorded with the digest, the token or user, the client IP and the user agent, so "who pulled the vulnerable build?" is a query instead of a guess.

More than container images

The same endpoint accepts other OCI artifacts: Helm charts via helm push, ORAS-pushed files, attestations. Layers that no manifest references any more are removed after a one-hour grace period, so in-flight pushes are never reaped.

Curated base images

Cache everything. Build only from what you approved.

The pull-through cache is about speed and availability; it serves whatever upstream publishes. Scanning, auto-quarantine and the pull-gate act on images that are pushed into OrbitalReg.

So copy the base images you approve from the cache into a curated local repository and point your Dockerfiles at that one. With Trivy and Grype enabled for that project, each copy is scanned layer by layer, and with auto-quarantine on, anything above your threshold is blocked before a build can use it. Clients that support cross-repo mounts can skip re-uploading layers the registry already holds.

# approve a base image: copy it from the cache into the curated repo
$ skopeo copy \
    docker://registry.example.com/acme/dockerhub/library/python:3.12-slim \
    docker://registry.example.com/acme/base-images/python:3.12-slim

# Dockerfile: builds only ever see the curated repo
FROM registry.example.com/acme/base-images/python:3.12-slim

Images that turn out to be malicious can be blocked by digest on every repository at once, the cache included. PHP2Shell shows why runtime CVEs hiding inside base images are worth this step.

Why one registry

An image is only as clean as the packages built into it.

Harbor and the Docker Hub mirrors are good at what they do: hosting and caching container images. The packages that end up inside those images usually come from somewhere else (npm, PyPI, Maven Central, Go modules), each with its own proxy and its own idea of a security policy. In OrbitalReg the container registry is one GA adapter among 40+, so the images and the dependencies baked into them share one set of projects and roles, one blocklist, one pull-gate and one append-only audit log.

Charts that deploy those images belong next to them too: see the Helm chart repository. Coming from Artifactory or Nexus? The migration page covers the cutover, and the pricing page shows what is free and what needs a licence.

Questions

Self-hosted container registries, answered.

How do I use OrbitalReg as a Docker Hub mirror?

Create a remote Docker repository pointing at https://registry-1.docker.io (or ghcr.io, quay.io, any OCI registry) and pull through it: docker pull registry.example.com/acme/dockerhub/library/alpine:3.20. The first request for each digest fetches and caches it; later pulls are served locally. Tags are re-checked upstream at most every five minutes by default, and you can store Docker Hub credentials on the repository so upstream requests are authenticated.

What happens when Docker Hub is down or rate-limits us?

Anything already cached keeps being served. Pulls by digest never leave your network once cached, and if the upstream fails while refreshing a tag, OrbitalReg answers with the copy it already holds instead of an error. A definite "tag not found" upstream is passed through, never masked.

Are images from the pull-through cache scanned?

Not on their own. Scanning, auto-quarantine and the pull-gate act on images pushed into OrbitalReg. The usual pattern is to cache upstream images for speed and copy the base images you approve into a curated local repository (skopeo copy or crane copy), where they are scanned and gated, and to point builds at that repository. Digest blocks apply to cached images too.

Can we migrate from Harbor?

Yes. Harbor speaks the same OCI Distribution API, so a docker pull, tag and push loop works for a handful of images, and skopeo sync moves whole projects in parallel: skopeo sync --src docker --dest docker harbor.example.com/library registry.example.com/acme/library. Signatures and SBOMs stored as OCI referrers come along with the images.

Is OrbitalReg a Harbor alternative?

For hosting and caching container images, yes. Harbor is a solid open-source container and OCI registry, and if images and charts are all you host, it does that well. OrbitalReg is one self-hosted registry for 40+ formats, so your images sit next to the npm, Maven, PyPI and Go packages they are built from, under the same projects, roles, security blocks, pull-gate and audit log.

How do Kubernetes clusters pull from it?

Like from any private registry: reference images by the OrbitalReg hostname and give the cluster a pull secret with a read-only token. In CI, GitLab, GitHub and Kubernetes service-account OIDC tokens can be exchanged for short-lived OrbitalReg tokens instead of long-lived ones (a licensed feature).

Documentation: Docker / OCI format reference · pull-gate · format support matrix · air-gapped operations

Free forever · no contract

Run your own container registry today.

One Helm chart, one Go binary, Postgres and S3-compatible storage. Security blocks, the pull-gate and image scanning are part of the free version.