Over 10 years we help companies reach their financial and branding goals. Engitech is a values-driven technology agency dedicated.

Gallery

Contacts

411 University St, Seattle, USA

+1 -800-456-478-23

How to install Harbor Container Registry Installation on Debian 13

This guide installs Harbor on Debian 13 using the official Harbor installer and Docker Compose.

Harbor is an open-source OCI/container registry that provides:

Private Docker / OCI registry
Projects and repositories
Role-based access control
Vulnerability scanning
Image replication
Robot accounts
OIDC / LDAP authentication
Retention policies
Image signing and verification
Web administration portal

Harbor is a CNCF Graduated project and can be used as a private registry for Docker, Podman, Kubernetes, K3s, CI/CD pipelines, and other OCI-compatible clients. (Harbor)


Architecture

A basic Harbor deployment looks like:

                       Developers / CI/CD
                              │
                              │ HTTPS :443
                              ▼
                    registry.example.com
                              │
                              ▼
                  ┌─────────────────────┐
                  │       Harbor        │
                  │                     │
                  │  Portal             │
                  │  Core               │
                  │  Registry           │
                  │  Job Service        │
                  │  PostgreSQL         │
                  │  Redis              │
                  │  Trivy (optional)   │
                  └──────────┬──────────┘
                             │
                             ▼
                         /data
                             │
                    Container Images

Harbor 2.14 can be installed on a Docker host using Docker Compose, or deployed on Kubernetes using Helm. (Harbor)


System Requirements

Harbor's official requirements for a Docker Compose deployment are: (Harbor)

Resource Minimum Recommended
CPU 2 cores 4 cores
Memory 4 GB 8 GB
Disk 40 GB 160 GB

For a production registry, I recommend:

CPU:       4+ cores
RAM:       8 GB+
OS Disk:   40 GB+
Registry:  200 GB+ depending on images
Storage:   SSD / RAID / Object Storage
Network:   Gigabit Ethernet+

The registry storage requirement depends primarily on:

Number of images
Image sizes
Number of tags
Build frequency
Retention policy
Replication
Vulnerability scanning

Software Requirements

Harbor 2.14 officially requires: (Harbor)

Docker Engine     > 20.10
Docker Compose    > 2.3
OpenSSL           Latest (optional)

Verify:

docker --version
docker compose version
openssl version

Network Requirements

Harbor normally requires:

80/TCP     HTTP
443/TCP    HTTPS

These ports can be changed in harbor.yml. (Harbor)

For production:

443/TCP    Required
80/TCP     Optional / HTTP redirect

1. Install Required Packages

sudo apt update

sudo apt install -y \
    curl \
    wget \
    tar \
    openssl

Docker Engine & Docker Compose

This application requires Docker Engine and Docker Compose v2.

Check whether Docker is already installed:

docker --version
docker compose version

If both commands return valid versions, continue with the installation.

If Docker is not installed, install it first using the Docker installation guide:

📘 Docker Installation Wiki

Quick Docker installation:

curl -fsSL https://get.docker.com | sudo sh

Enable and start Docker:

sudo systemctl enable --now docker

Optionally allow the current user to run Docker without sudo:

sudo usermod -aG docker $USER

Then log out and log back in, or run:

newgrp docker

Verify:

docker --version
docker compose version
docker run --rm hello-world

Note: Membership in the docker group grants effectively root-level privileges. Only trusted users should be added.


2. Create Harbor Directory

sudo mkdir -p /opt/harbor
sudo chown $USER:$USER /opt/harbor

cd /opt/harbor

3. Download Harbor Installer

Harbor provides two official installer types: (Harbor)

Online Installer
Offline Installer

Online Installer

Use this when the Harbor server has Internet access.

The installer itself is small and downloads the required Harbor images during installation.

Offline Installer

Use this when:

Harbor server has no Internet access
Air-gapped environment
Pre-download of all Harbor images is required

The offline installer contains the required container images and is therefore significantly larger. (Harbor)


Download Example

Go to the official Harbor releases page and download the required release.

For example, for Harbor 2.14.x:

wget https://github.com/goharbor/harbor/releases/download/v<VERSION>/harbor-online-installer-v<VERSION>.tgz

Example structure:

harbor-online-installer-v2.14.x.tgz

or:

harbor-offline-installer-v2.14.x.tgz

Replace <VERSION> with the exact Harbor release you intend to deploy rather than blindly using an old example version.

Harbor's official documentation recommends downloading either the online or offline installer from the Harbor releases page. (Harbor)


4. Extract Harbor

Example:

tar -xzf harbor-online-installer-v<VERSION>.tgz

Move into the directory:

cd harbor

Check:

ls

Typical contents:

harbor.yml.tmpl
install.sh
prepare
common.sh
LICENSE

The offline installer additionally contains:

harbor.v<VERSION>.tar.gz

5. Create Harbor Configuration

Copy the template:

cp harbor.yml.tmpl harbor.yml

Edit:

nano harbor.yml

Harbor requires at minimum that you configure the:

hostname:

property. (Harbor)


Basic HTTP Configuration

For an internal test environment:

hostname: harbor.example.local

http:
  port: 80

harbor_admin_password: CHANGE_THIS_PASSWORD

database:
  password: CHANGE_DATABASE_PASSWORD

data_volume: /data

Harbor's official documentation states that plain HTTP should only be used for air-gapped test or development environments. Production deployments should use HTTPS. (Harbor)


Recommended HTTPS Configuration

For production:

hostname: registry.example.com

http:
  port: 80

https:
  port: 443
  certificate: /data/cert/registry.example.com.crt
  private_key: /data/cert/registry.example.com.key

harbor_admin_password: CHANGE_THIS_ADMIN_PASSWORD

database:
  password: CHANGE_THIS_DATABASE_PASSWORD

data_volume: /data

Generate Strong Passwords

For example:

openssl rand -base64 32

Generate one for:

harbor_admin_password

and another for:

database.password

Do not reuse them.


Important Harbor Password

The initial administrator username is:

admin

The password comes from:

harbor_admin_password:

Example:

harbor_admin_password: VeryStrongRandomPassword

After Harbor is installed, use:

Username: admin
Password: <harbor_admin_password>

Data Storage

The default persistent data location is commonly:

data_volume: /data

Create it:

sudo mkdir -p /data

Check disk space:

df -h /data

A production registry should have sufficient space for container images and database growth.


Recommended Storage Layout

/
├── opt/
│   └── harbor/
│       └── harbor/
│           ├── harbor.yml
│           ├── install.sh
│           └── docker-compose.yml
│
└── data/
    ├── registry/
    ├── database/
    ├── redis/
    ├── job_logs/
    ├── secret/
    └── ca_download/

Keep:

/opt/harbor

for installation/configuration files and:

/data

for persistent Harbor data.


HTTPS Configuration

For production, use a certificate issued by:

Let's Encrypt
Internal Enterprise CA
DigiCert
Sectigo
GoDaddy
Other trusted CA

Harbor's documentation explicitly recommends a trusted third-party certificate for production deployments. (Harbor)


6. Create Certificate Directory

sudo mkdir -p /data/cert

For example:

/data/cert/registry.example.com.crt
/data/cert/registry.example.com.key

Set permissions:

sudo chmod 600 /data/cert/registry.example.com.key

Example with Let's Encrypt

If your certificates already exist:

/etc/letsencrypt/live/registry.example.com/fullchain.pem
/etc/letsencrypt/live/registry.example.com/privkey.pem

you can reference them directly:

https:
  port: 443
  certificate: /etc/letsencrypt/live/registry.example.com/fullchain.pem
  private_key: /etc/letsencrypt/live/registry.example.com/privkey.pem

Or copy/manage them under:

/data/cert/

according to your certificate-renewal architecture.


Self-Signed Certificate

For an internal Harbor registry, you can use your own CA.

Harbor provides an official procedure for creating:

CA certificate
Server certificate
Server private key

using OpenSSL. (Harbor)

Example CA private key:

openssl genrsa -out ca.key 4096

Create CA:

openssl req \
    -x509 \
    -new \
    -nodes \
    -sha512 \
    -days 3650 \
    -key ca.key \
    -out ca.crt

Create server key:

openssl genrsa \
    -out registry.example.com.key \
    4096

Create CSR:

openssl req \
    -sha512 \
    -new \
    -key registry.example.com.key \
    -out registry.example.com.csr

Make sure the resulting server certificate contains the registry hostname in its Subject Alternative Name (SAN).

Harbor's HTTPS documentation requires SAN-compliant certificates for modern clients. (Harbor)


Copy Certificates

sudo cp registry.example.com.crt /data/cert/
sudo cp registry.example.com.key /data/cert/

Then configure:

https:
  port: 443
  certificate: /data/cert/registry.example.com.crt
  private_key: /data/cert/registry.example.com.key

7. Install Harbor

Harbor's official installer uses:

sudo ./install.sh

after harbor.yml has been configured. (Harbor)

Run:

sudo ./install.sh

The installer generates the Docker Compose configuration and starts Harbor.


Install Harbor with Trivy

The default installation does not include Trivy. Harbor supports installing it using the optional installer flag. (Harbor)

For a production container registry, I recommend enabling Trivy:

sudo ./install.sh --with-trivy

Trivy provides container image vulnerability scanning.

Architecture:

Image pushed
     │
     ▼
Harbor Registry
     │
     ▼
Trivy Scanner
     │
     ▼
Vulnerability Report

Recommended Installation Command

For most production installations:

sudo ./install.sh --with-trivy

8. Check Harbor Containers

docker compose ps

Harbor runs as several Docker containers. (Harbor)

You should see components similar to:

harbor-core
harbor-db
harbor-jobservice
harbor-log
harbor-portal
nginx
redis
registry
registryctl
trivy-adapter

Check:

docker ps

All required services should be:

Up

Harbor's troubleshooting documentation recommends docker compose ps as the first check when services fail to start. (Harbor)


9. Open Harbor

Open:

https://registry.example.com

Login:

Username: admin
Password: <harbor_admin_password>

DNS

Create:

registry.example.com
          │
          ▼
Harbor Server IP

For example:

Type:   A
Name:   registry
Value:  163.53.181.162

Internal deployments can instead resolve:

registry.example.local

through internal DNS.


Firewall

For HTTPS:

sudo ufw allow 443/tcp

Optionally allow HTTP:

sudo ufw allow 80/tcp

Check:

sudo ufw status

Production clients normally need only:

443/TCP

Harbor's documented network ports are HTTP 80 and HTTPS 443, unless overridden in harbor.yml. (Harbor)


Test Docker Login

From a Docker client:

docker login registry.example.com

Enter:

Username: admin
Password: ********

Expected:

Login Succeeded

Create Harbor Project

Open:

Projects
    → New Project

Example:

Project Name:
xeon

You then have:

registry.example.com/xeon/

for container images.


Push Docker Image

Pull an image:

docker pull nginx:alpine

Tag it:

docker tag \
    nginx:alpine \
    registry.example.com/xeon/nginx:alpine

Push:

docker push \
    registry.example.com/xeon/nginx:alpine

Image path:

registry.example.com/xeon/nginx:alpine

Pull Image

docker pull \
    registry.example.com/xeon/nginx:alpine

ASP.NET Core Image Example

Suppose your application image is:

myCompanyApp-api:latest

Tag:

docker tag \
    myCompanyApp-api:latest \
    registry.example.com/erp/myCompanyApp-api:latest

Push:

docker push \
    registry.example.com/erp/myCompanyApp-api:latest

Kubernetes/K3s can then pull:

registry.example.com/erp/myCompanyApp-api:latest

Podman Login

Harbor also works with Podman.

podman login registry.example.com

Push:

podman push \
    registry.example.com/xeon/application:latest

Kubernetes / K3s Registry Authentication

Create an image pull secret:

kubectl create secret docker-registry harbor-registry \
    --docker-server=registry.example.com \
    --docker-username=USERNAME \
    --docker-password=PASSWORD \
    [email protected]

Then:

spec:
  imagePullSecrets:
    - name: harbor-registry

Example:

apiVersion: apps/v1
kind: Deployment

metadata:
  name: myCompanyApp-api

spec:
  template:

    spec:

      imagePullSecrets:
        - name: harbor-registry

      containers:

        - name: myCompanyApp-api
          image: registry.example.com/erp/myCompanyApp-api:latest

For automated systems, prefer a Harbor Robot Account rather than using the Harbor administrator account.


Robot Accounts

Harbor robot accounts are designed for:

GitHub Actions
GitLab CI
Jenkins
Kubernetes
K3s
Argo CD
Automated deployments
Build servers

Example architecture:

GitHub Actions
      │
      │ Robot credentials
      ▼
Harbor
      │
      ▼
registry.example.com/erp

Create from:

Project
    → Robot Accounts
    → New Robot Account

Give only the permissions required by the CI/CD system.

For example:

Pull Repository
Push Repository

Avoid using:

admin

credentials in CI/CD pipelines.


GitHub Actions Example

Store:

HARBOR_USERNAME
HARBOR_PASSWORD

as repository secrets.

Then:

- name: Login to Harbor
  uses: docker/login-action@v3
  with:
    registry: registry.example.com
    username: ${{ secrets.HARBOR_USERNAME }}
    password: ${{ secrets.HARBOR_PASSWORD }}

- name: Build and Push
  uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: registry.example.com/erp/myCompanyApp-api:latest

Prefer a Harbor robot account for these credentials.


Vulnerability Scanning with Trivy

If Harbor was installed with:

sudo ./install.sh --with-trivy

you can scan repositories for vulnerabilities.

Typical flow:

Container Image
      │
      ▼
Harbor
      │
      ▼
Trivy
      │
      ├── Critical
      ├── High
      ├── Medium
      └── Low

Projects can also be configured to prevent vulnerable artifacts from being pulled based on your security policy.


Image Retention

Container registries can grow quickly.

Example:

myCompanyApp-api
│
├── build-1001
├── build-1002
├── build-1003
├── build-1004
├── ...
└── build-4500

Configure:

Project
    → Policy
    → Tag Retention

Example policy:

Keep latest 20 images

or:

Keep artifacts pushed during the last 30 days

Retention policies help control storage consumption.


Garbage Collection

Deleting image tags does not necessarily immediately reclaim all registry storage.

Use Harbor's:

Administration
    → Clean Up
    → Garbage Collection

to reclaim unused artifact storage.

A typical schedule might be:

Weekly

during a low-traffic maintenance window.


Replication

Harbor supports registry replication.

Example:

Harbor Bangladesh
       │
       │ Replication
       ▼
Harbor Singapore

or:

Harbor
   │
   ├── Docker Hub
   ├── Another Harbor
   └── Other supported registries

Harbor supports third-party replication adapters as part of its registry ecosystem. (Harbor)


LDAP / Active Directory

Harbor can use external authentication such as:

LDAP
Active Directory
OIDC

Configure from:

Administration
    → Configuration
    → Authentication

For enterprise environments, OIDC can be used with an identity provider such as authentik.

Example:

Users
   │
   ▼
authentik
   │ OIDC
   ▼
Harbor

Harbor Behind Reverse Proxy

Harbor includes its own nginx component.

A standard deployment can therefore expose:

443

directly.

If another reverse proxy is placed in front:

Internet
    │
    ▼
Nginx / HAProxy
    │
    ▼
Harbor

ensure that:

Large request bodies are allowed
Long upload timeouts are supported
HTTPS scheme/headers are preserved
Docker Registry API paths are forwarded

Container layers can be several gigabytes, so ordinary website reverse-proxy upload limits may cause failed pushes.


Self-Signed Certificate on Docker Clients

When Harbor uses an internal CA, Docker clients must trust that CA.

Create:

sudo mkdir -p \
    /etc/docker/certs.d/registry.example.com

Copy CA:

sudo cp ca.crt \
    /etc/docker/certs.d/registry.example.com/ca.crt

Restart Docker:

sudo systemctl restart docker

Then:

docker login registry.example.com

Harbor's official HTTPS documentation describes installing registry trust material under /etc/docker/certs.d/<registry>/. (Harbor)


Registry with Non-Standard Port

Suppose Harbor uses:

registry.example.com:8443

The Docker certificate directory must include the port:

/etc/docker/certs.d/registry.example.com:8443/

For example:

/etc/docker/certs.d/
└── registry.example.com:8443/
    └── ca.crt

Harbor's official HTTPS documentation explicitly notes this requirement for non-default ports. (Harbor)


Harbor Service Management

Go to the Harbor installer directory:

cd /opt/harbor/harbor

Check:

docker compose ps

Stop:

docker compose down

Start:

docker compose up -d

Restart:

docker compose restart

Logs:

docker compose logs

Follow:

docker compose logs -f

Reconfigure Harbor

Edit:

nano harbor.yml

Then regenerate configuration:

sudo ./prepare

Recreate:

docker compose down
docker compose up -d

The prepare utility regenerates Harbor's runtime configuration from harbor.yml. Harbor documents this workflow when reconfiguring an existing deployment. (Harbor)


Harbor Logs

Check all logs:

docker compose logs

Core:

docker compose logs harbor-core

Registry:

docker compose logs registry

Database:

docker compose logs harbor-db

Trivy:

docker compose logs trivy-adapter

Follow:

docker compose logs -f

Check Storage

sudo du -sh /data

Registry:

sudo du -sh /data/registry

Database:

sudo du -sh /data/database

Check filesystem:

df -h

Registry servers should be monitored carefully for low disk space.


Backup

Important Harbor data includes:

/data
harbor.yml
Certificates
Database
Registry artifacts
Secrets

At minimum:

sudo tar \
    -czf harbor-config-backup.tar.gz \
    /opt/harbor/harbor/harbor.yml \
    /data/cert

For a complete backup strategy, include the database and registry storage.

Harbor's upgrade documentation explicitly instructs administrators to back up both the Harbor installation files and the database before an upgrade. (Harbor)


Upgrade Harbor

Do not simply replace the Harbor image versions in the generated Compose file.

Harbor upgrades may require:

Configuration migration
Database migration
New installer
Updated harbor.yml

The official upgrade procedure for Harbor 2.14 begins by stopping Harbor and backing up the installation and database before migration. (Harbor)

Typical high-level process:

1. Back up Harbor
2. Back up /data/database
3. Download newer Harbor installer
4. Migrate harbor.yml
5. Run prepare/migration
6. Start new Harbor version
7. Verify repositories and users

Always follow the official migration guide for the exact source and target versions.


Recommended Production Configuration

Example:

hostname: registry.example.com

http:
  port: 80

https:
  port: 443
  certificate: /data/cert/registry.example.com.crt
  private_key: /data/cert/registry.example.com.key

harbor_admin_password: CHANGE_TO_STRONG_PASSWORD

database:
  password: CHANGE_TO_DIFFERENT_STRONG_PASSWORD

data_volume: /data

Install:

sudo ./install.sh --with-trivy

Recommended Production Architecture

                     Internet / Private WAN
                              │
                              ▼
                    registry.example.com
                              │
                         HTTPS :443
                              │
                              ▼
                  ┌────────────────────┐
                  │       Harbor       │
                  │                    │
                  │ Portal             │
                  │ Core               │
                  │ Registry           │
                  │ Job Service        │
                  │ Trivy              │
                  │ Redis              │
                  │ PostgreSQL         │
                  └─────────┬──────────┘
                            │
                            ▼
                         /data
                            │
                ┌───────────┴───────────┐
                │                       │
                ▼                       ▼
           Registry Data            Database

Clients:

GitHub Actions ──┐
                 │
Docker ──────────┤
                 │
Podman ──────────┼──→ Harbor
                 │
K3s ─────────────┤
                 │
Kubernetes ──────┘

Quick Installation

Install dependencies:

sudo apt update

sudo apt install -y \
    wget \
    curl \
    tar \
    openssl

Download the Harbor installer:

wget https://github.com/goharbor/harbor/releases/download/v<VERSION>/harbor-online-installer-v<VERSION>.tgz

Extract:

tar -xzf harbor-online-installer-v<VERSION>.tgz

cd harbor

Create configuration:

cp harbor.yml.tmpl harbor.yml

Edit:

nano harbor.yml

Configure:

hostname: registry.example.com

https:
  port: 443
  certificate: /data/cert/registry.example.com.crt
  private_key: /data/cert/registry.example.com.key

harbor_admin_password: YOUR_STRONG_PASSWORD

database:
  password: YOUR_DATABASE_PASSWORD

data_volume: /data

Install with Trivy:

sudo ./install.sh --with-trivy

Check:

docker compose ps

Open:

https://registry.example.com

Login:

Username: admin
Password: <harbor_admin_password>

Test Registry

Login:

docker login registry.example.com

Pull:

docker pull nginx:alpine

Tag:

docker tag \
    nginx:alpine \
    registry.example.com/library/nginx:alpine

Push:

docker push \
    registry.example.com/library/nginx:alpine

Pull back:

docker pull \
    registry.example.com/library/nginx:alpine

Recommended Security Checklist

  • [ ] Use HTTPS in production.
  • [ ] Use a trusted TLS certificate where possible.
  • [ ] Do not use the default/example administrator password.
  • [ ] Use a different strong database password.
  • [ ] Protect harbor.yml.
  • [ ] Keep /data on reliable persistent storage.
  • [ ] Back up the Harbor database.
  • [ ] Back up registry data.
  • [ ] Enable Trivy vulnerability scanning.
  • [ ] Use robot accounts for CI/CD.
  • [ ] Do not use the admin account in GitHub Actions or Kubernetes.
  • [ ] Configure retention policies.
  • [ ] Configure garbage collection.
  • [ ] Monitor available disk space.
  • [ ] Keep Harbor updated.
  • [ ] Follow the official migration guide before upgrades.
  • [ ] Restrict Harbor's management access where appropriate.
  • [ ] Use OIDC/LDAP for centralized enterprise authentication where appropriate.

References

Harbor 2.14 officially supports Docker Compose deployments and documents minimum resources of 2 CPU, 4 GB RAM, and 40 GB disk, with 4 CPU, 8 GB RAM, and 160 GB disk recommended. It requires Docker Engine newer than 20.10 and Docker Compose newer than 2.3. (Harbor)

Harbor provides both online and offline installers. The online installer downloads Harbor container images during installation, while the offline installer packages the required images for disconnected environments. (Harbor)

The standard Harbor installation process is to download the installer, configure HTTPS, configure harbor.yml, and run install.sh; the default installation excludes Trivy, while --with-trivy installs Harbor with vulnerability scanning. (Harbor)

Harbor strongly recommends HTTPS for production environments and supports either trusted third-party certificates or self-signed certificates for internal environments. (Harbor)

Leave a comment

Your email address will not be published. Required fields are marked *