Install Harbor 2.13.1 on Ubuntu 24.04 with HAProxy, Let’s Encrypt (DNS-01), and Systemd

What is Harbor?

Harbor is a cloud-native container registry that secures and manages container images for your organization. Initially developed by VMware and now part of the CNCF, Harbor offers features that go well beyond a basic Docker Registry, including:

  • Role-Based Access Control (RBAC)
  • Vulnerability scanning with Trivy
  • LDAP/OIDC authentication
  • Replication between registries
  • Notary (image signing)
  • Garbage collection, retention policies, and quota management
  • REST API, CLI, and Web UI

It’s ideal for organizations looking to self-host a secure, enterprise-grade Docker registry, whether for air-gapped environments, Kubernetes clusters, or hybrid cloud setups.


Overview

In this guide, we will install Harbor 2.13.1 on Ubuntu 24.04, using:

  • TLS via HAProxy on port 443
  • Free HTTPS certificates via Let’s Encrypt (DNS-01) with Cloudflare
  • Harbor bound to 127.0.0.1:80 (local access only)
  • Systemd for startup on boot
  • Auto TLS renewal with reload hooks

Prerequisites

  • Ubuntu 24.04 server
  • DNS: harbor.maksonlee.com managed by Cloudflare
  • Docker + Compose plugin: Install Docker on Ubuntu 24.04
  • Port 443 open (port 80 is not required)

Install required packages:

sudo apt update
sudo apt install -y certbot python3-certbot-dns-cloudflare
sudo add-apt-repository ppa:vbernat/haproxy-3.2 -y
sudo apt-get install haproxy=3.2.\*
sudo systemctl enable --now haproxy

  1. Download and Extract Harbor
curl -LO https://github.com/goharbor/harbor/releases/download/v2.13.1/harbor-online-installer-v2.13.1.tgz
sudo mkdir -p /opt/harbor
sudo tar -xzf harbor-online-installer-v2.13.1.tgz -C /opt/harbor --strip-components=1

  1. Configure harbor.yml
sudo cp /opt/harbor/harbor.yml.tmpl /opt/harbor/harbor.yml
sudo vi /opt/harbor/harbor.yml

Set:

hostname: harbor.maksonlee.com

http:
  port: 80

external_url: https://harbor.maksonlee.com
  • Skip https:
  • HAProxy handles TLS externally.

  1. Install Harbor
cd /opt/harbor
sudo ./install.sh

  1. Bind Harbor to 127.0.0.1:80

Edit:

sudo vi /opt/harbor/docker-compose.yml

Change:

ports:
  - 127.0.0.1:80:8080

Then restart Harbor:

sudo docker compose down
sudo docker compose up -d

  1. Cloudflare Token & Certbot Credentials
  • Generate Cloudflare Token
    • Go to: Cloudflare API TokensCreate Token
    • Use the “Edit zone DNS” template:
      • Permissions:
        • Zone → DNS → Edit
      • Zone Resources:
        • Include → maksonlee.com
    • Click Create Token, copy the value.
  • Create cloudflare.ini
sudo vi /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

Set strict permissions:

sudo chmod 600 /etc/letsencrypt/cloudflare.ini

  1. Issue Let’s Encrypt Cert via DNS-01
sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
  -d harbor.maksonlee.com

Create combined cert for HAProxy:

sudo mkdir -p /etc/haproxy/certs/
sudo bash -c "cat /etc/letsencrypt/live/harbor.maksonlee.com/fullchain.pem /etc/letsencrypt/live/harbor.maksonlee.com/privkey.pem > /etc/haproxy/certs/harbor.maksonlee.com.pem"
sudo chmod 600 /etc/haproxy/certs/harbor.maksonlee.com.pem

  1. Configure HAProxy
sudo vi /etc/haproxy/haproxy.cfg

Add:

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
    mode http
    default_backend harbor

backend harbor
    mode http
    option http-buffer-request
    option http-keep-alive
    option forwardfor
    http-request set-header X-Forwarded-Proto https

    server harbor1 127.0.0.1:80

Verify and reload:

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy

  1. Auto-Renew Deploy Hook

Create a deploy hook:

sudo vi /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh

Paste:

#!/bin/bash
cat "$RENEWED_LINEAGE/fullchain.pem" "$RENEWED_LINEAGE/privkey.pem" > /etc/haproxy/certs/harbor.maksonlee.com.pem
systemctl reload haproxy

Make it executable:

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh

  1. Enable Harbor on Boot

Create systemd service:

sudo vi /etc/systemd/system/harbor.service
[Unit]
Description=Harbor Registry
After=network-online.target docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/harbor
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Enable it:

sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable --now harbor.service

  1. Verify Installation
  • Open in Browser

Visit:

https://harbor.maksonlee.com

You should see the Harbor UI with a valid HTTPS certificate.

  • Docker CLI Login
docker login harbor.maksonlee.com
  • Push a Test Image
docker pull ubuntu:24.04
docker tag ubuntu:24.04 harbor.maksonlee.com/library/ubuntu:24.04
docker push harbor.maksonlee.com/library/ubuntu:24.04

Check the Harbor UI → Projects → library → Repositories.

Leave a Comment

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

Scroll to Top