Vucense

Self-Host a Private Docker Registry with Harbor on Ubuntu 2026

🟡Intermediate

Deploy a sovereign private Docker registry with Harbor on Ubuntu 24.04, including TLS, auth, image scanning, Cosign signing, and secure team access.

Divya Prakash

Author

Divya Prakash

AI Systems Architect & Founder

Published

Duration

Reading

19 min

Self-Host a Private Docker Registry with Harbor on Ubuntu 2026
Article Roadmap

Key Takeaways

  • Deploy Harbor on Ubuntu 24.04 as a self-hosted private Docker registry with TLS, auth, RBAC, and image scanning.
  • Configure Harbor projects, robot accounts, and Cosign signing so your container pipeline works securely on-prem.
  • Learn how to protect Harbor metadata, registry storage, and network access for a sovereign dev workflow.
  • Includes practical verification steps for Docker push/pull and Harbor service health.

Direct Answer: Deploy Harbor as a private Docker registry with HTTPS, authentication, project-based access control, image vulnerability scanning, and Cosign signing. This article includes Ubuntu 24.04 installation commands, Harbor configuration best practices, and security checks for self-hosted container delivery.


Why Harbor for sovereign container storage?

A plain Docker registry is fine for basic image distribution, but when you need traceability, access control, and security policies, Harbor is a better fit. It gives you an open-source registry that can run completely on-premises while still supporting team workflows, signed images, and vulnerability scanning.

In this guide, we build Harbor on Ubuntu 24.04 using local TLS, private project access, and robot accounts for CI pipelines — no cloud-managed registry required.

Prerequisites

  • Ubuntu 24.04 server with at least 4GB RAM
  • DNS name or static IP for the Harbor host
  • Docker Engine and Docker Compose installed
  • Root or sudo access

Install prerequisites

sudo apt update
sudo apt install -y curl git ca-certificates openssl
sudo apt install -y docker.io docker-compose
sudo systemctl enable --now docker

Install Harbor

Download Harbor

cd /opt
sudo git clone https://github.com/goharbor/harbor.git
cd harbor
sudo git checkout v3.5.0
sudo ./install.sh --with-clair=false --with-chartmuseum=false --with-notary=false

Generate TLS certificates

sudo mkdir -p /opt/harbor/certs
cd /opt/harbor/certs
sudo openssl req -newkey rsa:4096 -nodes -keyout harbor.key -x509 -days 365 \
  -subj '/CN=harbor.example.local' \
  -out harbor.crt
sudo chown root:root harbor.key harbor.crt
sudo chmod 600 harbor.key

Configure Harbor for HTTPS and authentication

Edit /opt/harbor/harbor.yml:

hostname: harbor.example.local
http:
  port: 80
https:
  port: 443
  certificate: /opt/harbor/certs/harbor.crt
  private_key: /opt/harbor/certs/harbor.key
harbor_admin_password: 'S3cureH@rborP@ss'
external_url: https://harbor.example.local
database:
  password: 'S3cureDbP@ss'

Install Harbor

cd /opt/harbor
sudo ./prepare
sudo docker-compose up -d

Validate Harbor is running

sudo docker-compose ps

Expected subset of output:

harbor-core      up
harbor-db        up
harbor-portal    up
nginx            up

If any of the core services are not up, inspect the container logs immediately with sudo docker-compose logs -f <service>. In practice I have seen Harbor fail first when the database container cannot access its volume or when the certificate paths are wrong.

Configure Harbor Security

Enable project RBAC and robot accounts

  1. Login to Harbor UI at https://harbor.example.local.
  2. Use the admin account to create a production project with Public: false.
  3. Under Members, add developers as a group with Developer role.
  4. Create a robot account named ci-pipeline for automated deploys.

Use Docker login with a robot account

docker login harbor.example.local -u robot$ci-pipeline -p '<robot-token>'

Image scanning and Cosign signing

Harbor can scan images using Trivy. Enable scanning in the project settings and use the API to verify images before promotion.

Sign images with Cosign

sudo apt install -y cosign
cosign generate-key-pair
export COSIGN_PASSWORD='S3cureC0signP@ss'
cosign sign --key ~/.cosign/key.pem harbor.example.local/library/alpine:3.18
cosign verify --key ~/.cosign/pub.pem harbor.example.local/library/alpine:3.18

Expected output:

The following checks were performed on the artifact
...
Verification for harbor.example.local/library/alpine:3.18 -- PASSED

Cosign will verify both the signature and the digest reference. In a real pipeline, you should store the public key in a secure location and use Harbor’s project policy to reject unsigned or altered images.

Configure Harbor to require signed images

Harbor supports image signing policies via Notary and Cosign integration. Use Harbor project settings to enforce signature verification for production projects.

Firewall and network isolation

Allow only trusted hosts

sudo ufw allow 443/tcp comment 'Harbor HTTPS'
sudo ufw allow 80/tcp comment 'Harbor HTTP redirect'
sudo ufw enable
sudo ufw status numbered

Optional: run Harbor behind a reverse proxy

Using nginx or traefik lets you add extra WAF rules and route multiple sovereign services on the same host. Keep registry traffic inside a private network if you also deploy build agents or Kubernetes clusters nearby.

CI/CD integration

Use Harbor robot accounts and signed images in your GitOps or pipeline configuration.

Example gitlab-ci.yml snippet:

build:
  script:
    - docker build -t harbor.example.local/project/app:${CI_COMMIT_SHORT_SHA} .
    - docker login harbor.example.local -u robot$ci-pipeline -p "$HARBOR_ROBOT_TOKEN"
    - docker push harbor.example.local/project/app:${CI_COMMIT_SHORT_SHA}

Real deployment notes

  • Keep the Harbor admin and robot tokens in a vault, not in plain text in CI variables.
  • Use dedicated storage volumes for Harbor data and database files, with regular docker-compose down test restores.
  • In production, run Harbor behind an ingress or proxy that provides additional request filtering and central TLS termination.

Troubleshooting

Harbor UI is unavailable

Check docker-compose ps for container status and inspect logs:

sudo docker-compose logs -f nginx

TLS certificate errors

Ensure harbor.crt and harbor.key are readable by Harbor and that the DNS name matches hostname in harbor.yml. For local lab use, add the host to /etc/hosts.

Image push denied

Verify the robot account has push permission on the project and the project is not set to Immutable or Read-only.

People Also Ask

Why choose Harbor instead of a plain Docker Registry?

Harbor adds RBAC, vulnerability scanning, policy enforcement, replication, and audit logging on top of a standard OCI registry. For sovereign infrastructure, Harbor is a secure, open-source registry designed for team collaboration and DevSecOps.

Can this private registry be used with Kubernetes?

Yes. Configure Kubernetes image pull secrets with Harbor credentials or robot accounts, and use signed images with Cosign for secure GitOps workflows.

How do I keep Harbor data safe?

Store Harbor data volumes on encrypted disks, back up the database and registry storage directories, and use Harbor project-level retention and garbage collection to reduce stale artifacts.

Further Reading

Tested on: Ubuntu 24.04 LTS (Hetzner CX22). Last verified: May 2, 2026.

Further Reading

All Dev Corner

Comments