Harbor Active-Standby Deployment

Environment Setup

Operating System: CentOS 8.4 64bit

Harbor Version: harbor-offline-installer-v2.11.1.tgz

Docker Compose: docker-compose-linux-x86_64

Role Hostname IP Address
Primary Harbor Harbor01 192.168.8.161
Standby Harbor Harbor02 192.168.8.162
Docker Host web01 192.168.8.188

Harbor is an open-source enterprise Docker Registry project by VMware, built on the official Docker Registry with added features like management UI, role-based access control (RBAC), AD/LDAP integration, and audit logging. Each Harbor component runs as a Docker container, deployed using Docker Compose.


Part 1: Deploy Primary Harbor (HTTP Mode, No Certificates)

This method is suitable for internal networks where Harbor is accessed directly via HTTP without SSL certificates.

1. Install Docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Remove existing yum repo files
rm -rf /etc/yum.repos.d/*

# Download repo file from Alibaba Cloud mirror
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo

# Install Docker CE
yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Start Docker and enable on boot
systemctl enable docker.service --now

2. Configure Docker Mirror

1
vim /etc/docker/daemon.json

Enter the following content:

1
2
3
4
5
6
{
  "registry-mirrors": [
    "https://37564ea7e7cc4824a5049fd666807c27.mirror.swr.myhuaweicloud.com"
  ],
  "insecure-registries": ["http://192.168.8.161"]
}
1
2
systemctl daemon-reload
systemctl restart docker.service

3. Install Docker Compose and Harbor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Place docker-compose and harbor offline packages in /data
ls /data
# docker-compose-linux-x86_64  harbor-offline-installer-v2.11.1.tgz

# Install docker-compose
cp /data/docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod a+x /usr/local/bin/docker-compose

# Extract harbor
tar -zxvf /data/harbor-offline-installer-v2.11.1.tgz -C /usr/local/

4. Modify Harbor Configuration

1
2
3
cd /usr/local/harbor/
cp harbor.yml.tmpl harbor.yml
vim harbor.yml

Modify the following key settings:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
hostname: 192.168.8.161

http:
  port: 80

# Comment out the entire https section (not needed for HTTP mode)
#https:
#  port: 443
#  certificate: /your/certificate/path
#  private_key: /your/private/key/path

harbor_admin_password: Harbor12345

data_volume: /images

Leave all other settings at their defaults.

5. Run Installation

1
./install.sh

After installation, access http://192.168.8.161 in your browser and log in with admin / Harbor12345.

Harbor Login Interface

6. Create Users and Projects

Create user1 in the Harbor Web UI:

Create User

Log in as user1:

user1 Login

Create a new project (e.g., openssh) as user1:

New Project

7. Test Image Push and Pull

On the Docker host (web01):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Log in to Harbor
docker login 192.168.8.161
Username: user1
Password:
# Login Succeeded

# Tag the image
docker tag nginx:latest 192.168.8.161/openssh/nginx:latest

# Push to Harbor
docker push 192.168.8.161/openssh/nginx:latest

After successful push, the image appears in Harbor:

Image Upload Success

1
2
3
# Remove local image and pull again
docker image rm -f 192.168.8.161/openssh/nginx:latest
docker pull 192.168.8.161/openssh/nginx:latest

Harbor shows download count +1 after pull:

Download Count


Part 2: Deploy Standby Harbor

The standby deployment is identical to the primary, just change the hostname to the standby IP.

1
vim /usr/local/harbor/harbor.yml
1
hostname: 192.168.8.162

After deployment, access http://192.168.8.162 and create user2:

Standby Login

Create user2

Log in to standby Harbor as user2:

user2 Login


Part 3: Configure Active-Standby Replication

1. Create Replication Endpoint on Primary

Log in to primary Harbor as admin, go to Administration → Registries, and create a new endpoint:

Administration

Enter standby information:

  • Endpoint URL: http://192.168.8.162
  • Access ID / Access Secret: user2 credentials

New Endpoint

Endpoint Details

Creation successful:

Endpoint Created

2. Create Replication Policy

Go to Administration → Replications, create a new replication policy:

Replication Management

  • Destination Registry: Select Harbor02
  • Mode: Event-Based (or other modes)

Configure Policy

Sync Success

3. Verify Sync Results

Push more images from Docker host to primary:

1
2
3
4
5
docker tag httpd:2.4 192.168.8.161/openssh/httpd:2.4
docker push 192.168.8.161/openssh/httpd:2.4

docker tag mysql:5.7 192.168.8.161/openssh/mysql:5.7
docker push 192.168.8.161/openssh/mysql:5.7

Check primary images:

Primary Images

Check standby images (auto-synced):

Standby Images

The standby shows synced images from primary, confirming active-standby replication is working.

Note: Images that existed on primary before configuring replication need manual sync.


Part 4: Enable HTTPS (Self-Signed Certificate)

For production or public network access, HTTPS is recommended. Here’s the complete self-signed certificate workflow.

1. Generate CA and Server Certificates

On the Harbor server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
mkdir -p /data/cert && cd /data/cert

# Generate CA private key
openssl genrsa -out ca.key 4096

# Generate CA certificate (valid for 10 years)
openssl req -x509 -new -nodes -sha512 -days 3650 \
  -subj "/C=CN/CN=HarborRootCA" \
  -key ca.key \
  -out ca.crt

# Generate server private key
openssl genrsa -out harbor.key 4096

# Generate server certificate request (CN = Harbor IP or domain)
openssl req -sha512 -new \
  -subj "/C=CN/CN=192.168.8.161" \
  -key harbor.key \
  -out harbor.csr

2. Configure Certificate Extensions

Create v3.ext file with SAN (Subject Alternative Name):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
IP.1=192.168.8.161
EOF

IP.1 must match Harbor’s actual access address, otherwise Docker client will report certificate domain mismatch errors.

3. Sign Server Certificate

1
2
3
4
5
openssl x509 -req -sha512 -days 3650 \
  -extfile v3.ext \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -in harbor.csr \
  -out harbor.crt

4. Enable HTTPS in Harbor Configuration

1
vim /usr/local/harbor/harbor.yml

Uncomment the https section and update certificate paths:

1
2
3
4
5
6
hostname: 192.168.8.161

https:
  port: 443
  certificate: /data/cert/harbor.crt
  private_key: /data/cert/harbor.key

hostname must match IP.1 in v3.ext.

5. Redeploy Harbor

1
2
3
4
cd /usr/local/harbor/
docker-compose down
./prepare
docker-compose up -d

Warning: Do NOT use docker-compose down -v, as -v deletes named volumes, causing loss of Harbor database and user data.

Access via https://192.168.8.161 after deployment.

6. Configure Docker Clients to Trust Certificate

Execute on every machine that needs to push/pull images:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Create certificate directory (name must be Harbor IP or domain)
mkdir -p /etc/docker/certs.d/192.168.8.161

# Copy CA certificate to the directory
# Method 1: scp from Harbor server
scp root@192.168.8.161:/data/cert/ca.crt /etc/docker/certs.d/192.168.8.161/

# Method 2: Manually copy the ca.crt file content

# Restart Docker
systemctl restart docker

# Test login
docker login 192.168.8.161
# Enter admin and password, "Login Succeeded" indicates success

Part 5: FAQ

Q: Can I switch between HTTP and HTTPS modes?

Yes. Modify the https section in harbor.yml, then re-run ./install.sh. Switching from HTTP to HTTPS requires generating certificates first; switching back to HTTP requires commenting out the https section.

Q: Docker client reports “x509: certificate relies on legacy Common Name field” when logging into HTTPS Harbor?

This means the certificate lacks SAN (Subject Alternative Name). Regenerate the certificate ensuring v3.ext contains IP.1=<Harbor IP> and sign with -extfile v3.ext.

Q: How to troubleshoot replication failures?

Check network connectivity between primary and standby, verify the target registry credentials, and ensure the user has write permission to the target project.