Harbor
Cloud-native container registry with security
Harbor is an open-source container registry that secures artifacts with policies, role-based access control, vulnerability scanning, and image signing. It is a CNCF graduated project.
Key features
- Private container registry
- Vulnerability scanning
- Image replication
- Role-based access control
Pros & cons
Strengths
- Built-in vulnerability scanning
- Fine-grained RBAC
- CNCF graduated project
Trade-offs
- Many moving components
- Notable resource usage
Harbor replaces
Last reviewed Aug 26, 2026 · 866 words
Harbor is the registry you run when the plain Distribution image stops being enough: when you need to know which of your images carries a critical CVE, who pushed what and when, and a pull-through cache so Docker Hub's rate limit stops breaking rebuilds. It charges 4 GB of RAM and about nine containers for that, and the honest test of whether you need it is whether you have ever wanted any of those three things. A single-machine homelab usually has not. A team building its own images has, weekly.
Nine containers is the price of the feature list
Harbor (Apache-2.0, roughly 29,000 stars, Go, a CNCF graduated project born in 2016) is not one service. The installer brings up the core API, the web portal, the actual OCI registry, a job service for replication and scanning, Postgres, Redis, an nginx front, a log collector, and Trivy for vulnerability scanning. On Kubernetes the Helm chart deploys the same set. For a Compose host the flow is:
tar xzf harbor-online-installer-*.tgz && cd harbor
cp harbor.yml.tmpl harbor.yml
# edit hostname, https certificate paths, harbor_admin_password, data_volume
./install.sh --with-trivy
The key values in harbor.yml:
hostname: registry.example.com
https:
port: 443
certificate: /etc/harbor/cert.pem
private_key: /etc/harbor/key.pem
harbor_admin_password: change-me-before-first-boot
data_volume: /srv/harbor
The installer generates a docker-compose.yml from that file; edit the YAML and rerun ./install.sh rather than editing the generated Compose. Harbor wants to own ports 80 and 443 itself; if a reverse proxy already does, set Harbor's http port to something internal and proxy to it, and set external_url so the portal generates correct addresses. Budget 40 GB of disk before you push anything, because images accumulate faster than you expect.
The proxy-cache project pays for itself in a week
Create a project with type "proxy cache" pointing at Docker Hub, and pull images as registry.example.com/dockerhub/library/postgres:16. Harbor fetches on first pull, stores the layers, and serves every later pull from disk. That does three things: it stops anonymous Docker Hub rate limits from failing a rebuild of 30 containers, it lets Watchtower or your update routine poll without hammering upstream, and it means the images your stack depends on still exist on your disk if upstream deletes a tag. The container updates post covers why that last point matters more than it sounds.
Scanning shows what your Compose stack is actually running
Every push can trigger a Trivy scan, and the project setting "prevent vulnerable images from running" refuses pulls of images above a severity you choose. Turn on the block for critical CVEs only at first; blocking on high will stop half of Docker Hub. The value is less the gate and more the report: a per-project page of which images carry which CVEs, which is the visibility that the container security post argues gives most of the benefit for a fraction of the effort. Scans run in the job service, so the 4 GB floor is real during a scan of a large image.
Robot accounts keep CI away from your admin password
Harbor's model is projects (namespaces) with member roles from guest through project admin, and robot accounts scoped to a project with pull-only or push-and-pull rights and an expiry. CI pushes with a robot; production hosts pull with a different robot; humans log in through OIDC against Authentik or LDAP. Nobody uses the admin account after day one. Replication rules push selected repositories to a second Harbor or pull from another registry on a schedule, which is how you keep an off-site copy of the images you built yourself.
Retention and garbage collection, or the disk fills
Deleting a tag in Harbor does not free space; a scheduled garbage collection does. Set a tag retention rule per project (keep the latest 10, or anything pulled in the last 90 days), turn on the "delete untagged artifacts" option, and schedule GC weekly during a quiet hour, because it takes the registry read-only while it runs.
When Gitea's registry is enough
If you already run Gitea or Forgejo, their built-in package registry hosts OCI images with the same credentials as your Git repos, no extra containers, no scanning, no cache. For one person publishing a handful of images, that is the right size. Plain registry:2 is smaller still. Harbor is for the point where "who can pull this" and "is this image safe" are questions someone asks out loud.
What I'd do
Team, or a homelab that builds more than a few of its own images: Harbor with Trivy, one proxy-cache project for Docker Hub from day one, robot accounts for CI, OIDC for people, weekly GC. Solo with a couple of images: Gitea's registry and skip the 4 GB. Either way, stop pulling library/postgres straight from Docker Hub on every rebuild; whichever registry you pick, that is the habit that causes the outages.
Compare Harbor
5 head-to-head comparisons.
Similar developer tools & git apps
Excalidraw
Developer Tools & GitVirtual hand-drawn style whiteboard
Replaces Miro
lazygit
Developer Tools & GitSimple terminal UI for Git commands
Replaces GitKraken, Sourcetree
Hoppscotch
Developer Tools & GitOpen-source API development ecosystem
Replaces Postman, Insomnia
json-server
Developer Tools & GitFull fake REST API from a JSON file in seconds
Replaces Mockoon, Postman Mock
Strapi
Developer Tools & GitLeading open-source headless CMS
Replaces Contentful
NocoDB
Developer Tools & GitOpen-source Airtable alternative
Replaces Airtable