How can I install Harbor container registry on CentOS, Ubuntu, Debian, Rocky Linux, AlmaLinux?. Harbor is an open-source cloud native registry that stores, signs, and scans container images for vulnerabilities. If you’re looking for enterprise Docker image registry, then Harbor is the right tool for you. It has some of the best features only available in commercial Registry products like Quay.
Harbor fills a gap for applications and organizations that cannot use a public or cloud-based registry. You’ll enjoy a consistent experience across all clouds platforms. This guide will walk you through the installation of Harbor on any system with Docker support.
Features of Harbor Registry
- Multi-tenant support
- Security and vulnerability analysis support
- Extensible API and web UI
- Content signing and validation
- Image replication across multiple Harbor instances
- Identity integration and role-based access control
1. Server Preparation
You need an operating system with support for docker and following system requirements:
Hardware
Resource | Capacity | Description |
---|---|---|
CPU | minimal 2 CPU | 4 CPU is preferred |
Mem | minimal 4GB | 8GB is preferred |
Disk | minimal 40GB | 160GB is preferred |
Software
Software | Version |
---|---|
Docker engine | Version 20.10.10-ce+ or higher |
Docker Compose | docker-compose (v1.18.0+) or docker compose v2 (docker-compose-plugin) |
Openssl | Latest is preferred |
Network ports
Port | Protocol |
---|---|
443 | HTTPS |
4443 | HTTPS |
80 | HTTP |
Let’s now start the installation of Harbor on Linux system – CentOS, Ubuntu & Debian Linux distribution.
Storage Preparation (Optional)
I’ll be using a secondary disk as data store for all container images – /dev/sdb
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 74G 0 part
├─rhel-root 253:0 0 10G 0 lvm /
├─rhel-swap 253:1 0 16G 0 lvm [SWAP]
├─rhel-home 253:2 0 4G 0 lvm /home
├─rhel-var 253:3 0 20G 0 lvm /var
├─rhel-var_log 253:4 0 10G 0 lvm /var/log
├─rhel-var_log_audit 253:5 0 2G 0 lvm /var/log/audit
├─rhel-tmp 253:6 0 8G 0 lvm /tmp
└─rhel-var_tmp 253:7 0 4G 0 lvm /var/tmp
sdb 8:16 0 200G 0 disk
sr0 11:0 1 1024M 0 rom
Let’s prepare and mount this disk.
sudo parted -s -a optimal -- /dev/sdb mklabel gpt
sudo parted -s -a optimal -- /dev/sdb mkpart primary 0% 100%
sudo parted -s -- /dev/sdb align-check optimal 1
sudo pvcreate /dev/sdb1
sudo vgcreate vg0 /dev/sdb1
sudo lvcreate -n harbor -l +100%FREE vg0
sudo mkfs.xfs /dev/vg0/harbor
sudo mkdir /data
echo "/dev/vg0/harbor /data xfs defaults 0 0" | sudo tee -a /etc/fstab
Mount and confirm:
$ sudo mount -a
$ df -hT /data/
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg0-harbor xfs 200G 1.5G 199G 1% /data
2. Install Docker Engine and Compose
Follow our guides below on installation of Docker Engine.
- Install Docker and Docker Compose on Debian
- How to install Docker CE on Ubuntu / Debian / CentOS
- How to install Docker on Fedora
- Install Docker CE on CentOS 8 | RHEL 8
Our next installation is for docker-compose command. This is not available on system repositories. Follow instructions shared in our previous guide below.
3. Download and Install Harbor
Download harbor installer.
curl -s https://api.github.com/repos/goharbor/harbor/releases/latest | grep browser_download_url | cut -d '"' -f 4 | grep '\.tgz$' | wget -i -
You can also pull the latest Harbor release from the downloads page.
Unpack downloaded Harbor file.
tar xvzf harbor-offline-installer*.tgz
Change into harbor created after file unpacking.
cd harbor
Option 1) Harbor Installation without SSL
In the first setup, we’ll consider installation without TLS/SSL. Copy configuration template:
cp harbor.yml.tmpl harbor.yml
Edit harbor configuration file, and set like below.
$ nano harbor.yml
....
# The IP address or hostname to access admin UI and registry service.
hostname: registry.computingforgeeks.com
harbor_admin_password: StrongAdminPs5W0d
# Harbor DB configuration
database:
password: StrongdbrootP@s5W0$d
Reference Harbor configure yml file documentation for how to customize the settings.
Option 2) Install Harbor with Let’s Encrypt
if your server has a public IP, you can use Let’s Encrypt free SSL certificate.
Start by installing certbot tool.
# Ubuntu / Debian
sudo apt update && sudo apt install certbot -y
# Fedora
sudo dnf install certbot -y
# RHEL 8/9 based systems
sudo dnf -y install epel-release
sudo dnf -y install certbot
# CentOS 7
sudo yum -y install epel-release
sudo yum -y install certbot
# Arch / Manjaro
sudo pacman -Syy certbot
Then obtain SSL certificate.
export DOMAIN="registry.computingforgeeks.com"
export EMAIL="[email protected]"
sudo certbot certonly --standalone -d $DOMAIN --preferred-challenges http --agree-tos -m $EMAIL --keep-until-expiring
Configure https related config.
....
https:
port: 443
certificate: /etc/letsencrypt/live/registry.computingforgeeks.com/fullchain.pem
private_key: /etc/letsencrypt/live/registry.computingforgeeks.com/privkey.pem
Option 3) Install Harbor with Self Signed SSL
Create directory for storing SSL information:
sudo mkdir -p /etc/pki/tls/certs
cd /etc/pki/tls/certs
Create a new file
sudo vim harbor_certs.cnf
For Self signed certificates, create certificate configuration file – modify the file to match your values.
[ req ]
default_bits = 4096
default_md = sha512
default_keyfile = harbor_registry.key
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
# distinguished_name
[ req_distinguished_name ]
countryName = "KE"
localityName = "Nairobi"
stateOrProvinceName = "Nairobi"
organizationName = "Computingforgeeks"
commonName = "registry.computingforgeeks.com"
emailAddress = "[email protected]"
Generate key and csr:
sudo openssl req -out harbor_registry.csr -newkey rsa:4096 --sha512 -nodes -keyout harbor_registry.key -config harbor_certs.cnf
Create self-singed certificate with 10 years expiration date:
sudo openssl x509 -in harbor_registry.csr -out harbor_registry.crt -req -signkey harbor_registry.key -days 3650
To view certificate details use the command:
openssl x509 -text -noout -in harbor_registry.crt
Open harbor.yml
file for editing:
cd -
nano harbor.yml
Configure https related config.
...
https:
port: 443
certificate: /etc/pki/tls/certs/harbor_registry.crt
private_key: /etc/pki/tls/certs/harbor_registry.key
Install Harbor Docker image registry
Once harbor.yml and storage backend (optional) are configured, prepare the environment by generating Harbor configurations.
sudo ./prepare
To see installer options, run:
$ ./install.sh --help
Note: Please set hostname and other necessary attributes in harbor.yml first. DO NOT use localhost or 127.0.0.1 for hostname, because Harbor needs to be accessed by external clients.
Please set --with-trivy if needs enable Trivy in Harbor.
Please do NOT set --with-chartmuseum, as chartmusuem has been deprecated and removed.
Please do NOT set --with-notary, as notary has been deprecated and removed.
Note that the default installation does not include Trivy service. This service is used for vulnerability scanning.
To install Harbor with Trivy service, run:
sudo ./install.sh --with-trivy
Example of the installation output:
....
[Step 5]: starting Harbor ...
WARN[0000] /root/harbor/docker-compose.yml: `version` is obsolete
WARN[0000] The "d" variable is not set. Defaulting to a blank string.
[+] Running 11/11
✔ Network harbor_harbor Created 0.1s
✔ Container harbor-log Started 0.4s
✔ Container registry Started 1.4s
✔ Container harbor-db Started 1.3s
✔ Container redis Started 1.4s
✔ Container harbor-portal Started 1.1s
✔ Container registryctl Started 1.1s
✔ Container trivy-adapter Started 1.8s
✔ Container harbor-core Started 1.8s
✔ Container harbor-jobservice Started 2.3s
✔ Container nginx Started 2.5s
✔ ----Harbor has been installed and started successfully.----
Harbor log files are stored in the directory /var/log/harbor/:
$ ls -1 /var/log/harbor/
core.log
jobservice.log
portal.log
postgresql.log
proxy.log
redis.log
registryctl.log
registry.log
trivy-adapter.log
You can list running containers using docker compose ps
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
harbor-core goharbor/harbor-core:v2.11.0 "/harbor/entrypoint.…" core 2 minutes ago Up 2 minutes (healthy)
harbor-db goharbor/harbor-db:v2.11.0 "/docker-entrypoint.…" postgresql 2 minutes ago Up 2 minutes (healthy)
harbor-jobservice goharbor/harbor-jobservice:v2.11.0 "/harbor/entrypoint.…" jobservice 2 minutes ago Up About a minute (healthy)
harbor-log goharbor/harbor-log:v2.11.0 "/bin/sh -c /usr/loc…" log 2 minutes ago Up 2 minutes (healthy) 127.0.0.1:1514->10514/tcp
harbor-portal goharbor/harbor-portal:v2.11.0 "nginx -g 'daemon of…" portal 2 minutes ago Up 2 minutes (healthy)
nginx goharbor/nginx-photon:v2.11.0 "nginx -g 'daemon of…" proxy 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443-
4. Access Harbor web interface
After the installation has succeeded, access Harbor web console on https://registry_domain.

Login with:
Username: admin
Password: as-set-in-harbor.yml
You should get to Harbor web dashboard.

5. Managing Harbor’s lifecycle
List running Harbor service containers:
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
harbor-core goharbor/harbor-core:v2.11.0 "/harbor/entrypoint.…" core 9 minutes ago Up 9 minutes (healthy)
harbor-db goharbor/harbor-db:v2.11.0 "/docker-entrypoint.…" postgresql 9 minutes ago Up 9 minutes (healthy)
harbor-jobservice goharbor/harbor-jobservice:v2.11.0 "/harbor/entrypoint.…" jobservice 9 minutes ago Up 9 minutes (healthy)
harbor-log goharbor/harbor-log:v2.11.0 "/bin/sh -c /usr/loc…" log 9 minutes ago Up 9 minutes (healthy) 127.0.0.1:1514->10514/tcp
harbor-portal goharbor/harbor-portal:v2.11.0 "nginx -g 'daemon of…" portal 9 minutes ago Up 9 minutes (healthy)
nginx goharbor/nginx-photon:v2.11.0 "nginx -g 'daemon of…" proxy 9 minutes ago Up 9 minutes (healthy) 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp
You can use docker-compose to manage the lifecycle of Harbor. See examples below.
Stopping Harbor:
$ docker compose stop
[+] Stopping 10/10
✔ Container harbor-jobservice Stopped 0.2s
✔ Container registryctl Stopped 0.2s
✔ Container trivy-adapter Stopped 0.2s
✔ Container nginx Stopped 0.2s
✔ Container harbor-portal Stopped 0.1s
✔ Container harbor-core Stopped 0.1s
✔ Container harbor-db Stopped 0.2s
✔ Container registry Stopped 0.1s
✔ Container redis Stopped 0.2s
✔ Container harbor-log Stopped 10.1s
Restarting Harbor after stopping:
$ docker compose start
[+] Running 10/10
✔ Container harbor-log Started 0.2s
✔ Container harbor-portal Started 0.4s
✔ Container harbor-db Started 0.5s
✔ Container registryctl Started 0.5s
✔ Container redis Started 0.6s
✔ Container registry Started 0.5s
✔ Container harbor-core Started 0.3s
✔ Container trivy-adapter Started 0.2s
✔ Container nginx Started 0.4s
✔ Container harbor-jobservice Started 0.3s
Updating Harbor’s configuration:
To change Harbor’s configuration, first, stop existing Harbor instance and update harbor.yml. Then run prepare script to populate the configuration. Then re-create and start Harbor’s instance:
docker compose down -v
vim harbor.yml
./prepare --with-trivy
docker compose up -d
For troubleshooting, check the log files of containers in directory /var/log/harbor.
$ ls -1 /var/log/harbor/
core.log
jobservice.log
portal.log
postgresql.log
proxy.log
redis.log
registryctl.log
registry.log
trivy-adapter.log
Visit Harbor user guide page to learn more on usage.
More Harbor guides:
- Integrate Harbor Registry With LDAP for user Authentication
- Prevent users from Creating Projects in Harbor registry
Similar articles:
- Setup Red Hat Quay Registry on CentOS / RHEL / Ubuntu
- Install and Use Docker Registry on Fedora
- Install and Configure Docker Registry on CentOS 7
Hello, Well written document on how to install Harbor registry on a Linux VM.
I am in the process of installing harbor on a Rocky8 VM. I have completed installing Docker and Docker Compose, I can see there is a step for adding our user to Docker group. I am performing the install using root ID. So what would be the User ID that I should be adding to the Docker Group. Answers would help a lot. Thanks a lot.