м. Київ, вул. Кирилівська 102

24 серпня 2026 р.

Налаштування Harbor Registry

Налаштування Harbor Registry

Власний container registry потрібен не для того, щоб просто перенести образи з Docker Hub на інший сервер. Його практична цінність з’являється тоді, коли команда контролює доступ до приватних репозиторіїв, сканує образи до розгортання, зберігає audit log, встановлює retention і не залежить від зовнішніх rate limits під час релізу. Harbor додає ці можливості поверх OCI-сумісного registry та надає web portal, RBAC, robot accounts, replication і вбудовану інтеграцію з Trivy.

У цій інструкції встановимо Harbor 2.15.2 на окремий Linux-host через офіційний online installer і Docker Compose. Одразу налаштуємо HTTPS, окремий data volume, створимо приватний project, перевіримо push та pull, підключимо Kubernetes через imagePullSecret і розберемо обов’язкові операції після запуску. Така схема підходить для невеликого або середнього внутрішнього registry. Для високої доступності на Kubernetes потрібна інша архітектура через офіційний Helm chart, зовнішні PostgreSQL, Redis та object storage.

Registry стає критичною частиною release path: якщо він недоступний або пошкоджений, нові Pod-и не завантажать image навіть тоді, коли вже запущені репліки ще працюють. Тому Harbor потрібно включати в загальний DevOps-супровід інфраструктури: моніторити, резервувати й оновлювати так само дисципліновано, як CI-систему або Kubernetes control plane.

Підготовка сервера, DNS і TLS

Для Compose-інсталяції Harbor потрібен окремий Linux-host із Docker Engine новіше 20.10 та Docker Compose новіше 2.3. Офіційний мінімум — 2 CPU, 4 GB RAM і 40 GB диска; для стабільної роботи рекомендовано щонайменше 4 CPU, 8 GB RAM і 160 GB. Реальний обсяг storage залежить від кількості repositories, частоти build і retention. Не розміщуйте registry на маленькому системному partition без контролю вільного місця.

Створіть DNS-запис, наприклад `registry.example.com`, який вказує на сервер. Відкрийте TCP 443 для клієнтів і, за потреби, TCP 80 тільки для редиректу або ACME challenge. SSH обмежте адміністративною мережею. Перед установленням перевірте host:

bash
hostname -f
getent hosts registry.example.com
docker version
docker compose version
df -h
free -h
ss -lntp

Harbor повинен працювати через HTTPS. Для публічного DNS використовуйте сертифікат від довіреного CA. Для внутрішньої PKI встановіть root CA на всі Docker, containerd і Kubernetes nodes. Додавання registry до `insecure-registries` вимикає важливу перевірку каналу й не повинно бути стандартним production-рішенням.

Підготуйте каталоги та скопіюйте повний certificate chain і private key. Ключ має читати тільки root:

bash
sudo install -d -m 0755 /opt/harbor /data/harbor /etc/harbor/tls

sudo install -m 0644 fullchain.pem /etc/harbor/tls/registry.crt
sudo install -m 0600 privkey.pem /etc/harbor/tls/registry.key

sudo openssl x509 \
  -in /etc/harbor/tls/registry.crt \
  -noout -subject -issuer -dates

Переконайтеся, що certificate SAN містить точне ім’я `registry.example.com`, а системний час синхронізований. Сертифікат із правильним CN, але без потрібного SAN, сучасні клієнти не приймуть.

Завантаження і перевірка Harbor installer

На дату підготовки інструкції актуальний stable release — 2.15.2. Версію фіксуємо змінною, щоб download URL, archive і каталог не розійшлися. Online installer невеликий, але під час встановлення завантажує images із мережі; для ізольованого host використовуйте offline installer.

bash
cd /opt/harbor
export HARBOR_VERSION="v2.15.2"

curl -fLO \
  "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-online-installer-${HARBOR_VERSION}.tgz"

curl -fLO \
  "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-online-installer-${HARBOR_VERSION}.tgz.sigstore.json"

Починаючи з Harbor 2.15 release artifacts підписуються через Sigstore. Встановіть Cosign перевіреним способом для своєї системи та перевірте archive офіційним bundle. Регулярний вираз обмежує identity workflow репозиторієм Harbor і release tag:

bash
cosign verify-blob \
  --bundle "harbor-online-installer-${HARBOR_VERSION}.tgz.sigstore.json" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  --certificate-identity-regexp '^https://github.com/goharbor/harbor/.github/workflows/publish_release.yml@refs/tags/v.*$' \
  "harbor-online-installer-${HARBOR_VERSION}.tgz"

Продовжуйте лише після `Verified OK`. Після цього розпакуйте installer і збережіть каталог: він потрібен для reconfigure та upgrade.

bash
tar -xzf "harbor-online-installer-${HARBOR_VERSION}.tgz"
cd harbor
cp harbor.yml.tmpl harbor.yml

Не запускайте випадковий installer від root без перевірки походження. Також не використовуйте floating URL на майбутню версію: повторне виконання runbook повинно встановлювати той самий release, поки upgrade не запланований окремо.

Конфігурація harbor.yml та встановлення з Trivy

Відкрийте `harbor.yml` і змініть принаймні hostname, HTTPS, administrator password, data volume та log settings. Значення нижче показують ключові фрагменти, а не повну заміну template. Зберігайте структуру та параметри з `harbor.yml.tmpl` саме вибраної версії.

yaml
hostname: registry.example.com

https:
  port: 443
  certificate: /etc/harbor/tls/registry.crt
  private_key: /etc/harbor/tls/registry.key

harbor_admin_password: REPLACE_WITH_LONG_RANDOM_PASSWORD

database:
  password: REPLACE_WITH_ANOTHER_RANDOM_PASSWORD
  max_idle_conns: 50
  max_open_conns: 100

data_volume: /data/harbor

log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M
    location: /var/log/harbor

trivy:
  ignore_unfixed: false
  skip_update: false
  offline_scan: false

Не коммітьте реальний `harbor.yml` із паролями у звичайний репозиторій. Зберігайте encrypted backup конфігурації або генеруйте файл із secret manager. Administrator password потрібен лише для первинного керування; CI jobs повинні використовувати robot accounts із мінімальними правами.

Запустіть підготовку конфігурації та installer із Trivy:

bash
sudo ./prepare
sudo ./install.sh --with-trivy

Перевірте Compose services, HTTPS і health API:

bash
sudo docker compose ps
sudo docker compose logs --tail=100

curl -fsS https://registry.example.com/api/v2.0/health
curl -I https://registry.example.com/

Очікуваний health status — `healthy`. Якщо сертифікат підписаний внутрішнім CA, не додавайте `-k` у постійні перевірки. Встановіть CA в trust store host і контейнерного runtime, потім повторіть curl без обходу TLS verification.

Для керування lifecycle використовуйте згенерований Compose-файл у installer directory:

bash
sudo docker compose stop
sudo docker compose start
sudo docker compose down
sudo docker compose up -d

Прапорець `-v` під час `docker compose down` може видалити named volumes. Не копіюйте команди з troubleshooting без розуміння, де зберігаються PostgreSQL, Redis, registry data та secrets.

Project, robot account і перший push

Увійдіть у web portal як `admin`, одразу змініть початковий password, якщо він не був заданий безпечно, і створіть приватний project `platform`. Image не можна push до repository, поки відповідний project не існує. Private project дозволяє pull лише авторизованим учасникам.

Для automation створіть project robot account, наприклад `ci-push`, і дайте тільки `Push Repository` та `Pull Repository` у project `platform`. Не використовуйте administrator credentials у pipeline. Secret robot account показується під час створення — одразу збережіть його в захищеному CI variable або secret manager.

На workstation перевірте login, tag, push і pull. Пароль безпечніше передавати через stdin:

bash
export HARBOR_HOST="registry.example.com"
export HARBOR_USER='robot$platform+ci-push'

printf '%s' "$HARBOR_TOKEN" | \
  docker login "$HARBOR_HOST" \
    --username "$HARBOR_USER" \
    --password-stdin

docker pull nginx:1.28-alpine
docker tag nginx:1.28-alpine \
  "$HARBOR_HOST/platform/nginx:1.28-alpine"

docker push "$HARBOR_HOST/platform/nginx:1.28-alpine"
docker image rm "$HARBOR_HOST/platform/nginx:1.28-alpine"
docker pull "$HARBOR_HOST/platform/nginx:1.28-alpine"

Після push відкрийте artifact у Harbor і запустіть scan. Перевірте digest, vulnerability report, SBOM і час останнього scan. Увімкнення Trivy не гарантує автоматичний контроль кожного майбутнього artifact: налаштуйте scan on push або scheduled scan та політику блокування образів із критичними вразливостями відповідно до процесу винятків.

Kubernetes namespace повинен отримати окремий pull-only robot account. Створіть Secret без збереження token у manifest:

bash
kubectl create namespace demo

kubectl -n demo create secret docker-registry harbor-pull \
  --docker-server="registry.example.com" \
  --docker-username='robot$platform+k8s-pull' \
  --docker-password="$HARBOR_PULL_TOKEN"

kubectl -n demo patch serviceaccount default \
  -p '{"imagePullSecrets":[{"name":"harbor-pull"}]}'

kubectl -n demo run harbor-test \
  --image=registry.example.com/platform/nginx:1.28-alpine

kubectl -n demo get pod harbor-test
kubectl -n demo describe pod harbor-test

У production не patch-те default ServiceAccount для всіх workloads без оцінки доступів. Краще створити окремий ServiceAccount для застосунку й керувати Secret через GitOps або external secrets. Інтеграцію build, scan і deploy варто оформити як керований CI/CD pipeline, де promotion відбувається за digest, а не через mutable tag `latest`.

Retention, garbage collection, backup і monitoring

Без retention registry ростиме доти, доки заповнить disk. Створіть project retention policy, яка зберігає release tags і потрібну кількість останніх development artifacts. Спочатку запустіть policy в dry-run, перегляньте результат і лише потім виконуйте видалення. Не будуйте правило тільки за віком: старий image може бути єдиною перевіреною версією для rollback.

Retention видаляє references за правилами, але фактичне звільнення storage відбувається через garbage collection. Заплануйте GC у період низької активності, контролюйте job logs і не запускайте кілька cleanup-процесів одночасно. Перед агресивною політикою зробіть backup і перевірте можливість відновити registry metadata та blobs узгоджено.

Для Compose-інсталяції резервуйте весь стан Harbor: data volume, PostgreSQL data, registry storage, configuration, secret key і TLS material. Просте копіювання `/data/harbor` під час активного запису не гарантує consistency. Використовуйте узгоджену процедуру з maintenance window або application-aware database backup та snapshot storage. Recovery runbook повинен містити ту саму Harbor version, `harbor.yml`, certificates, порядок restore і перевірку push/pull.

Harbor також може реплікувати artifacts в інший Harbor або підтримуваний registry. Replication корисна для другого майданчика, але не замінює backup: помилкове видалення або retention policy може бути відтворене на target залежно від правил.

Моніторинг має охоплювати не тільки HTTP 200 portal. Контролюйте:

- health API та TLS certificate expiry; - доступність registry push і pull; - заповнення disk та inode; - PostgreSQL, Redis, core, registry, jobservice і Trivy; - черги scan, replication, retention і garbage collection; - кількість помилок authorization та audit log; - вік останнього успішного backup і restore test.

Після встановлення корисно виконати контрольний pull з кожного Kubernetes node або runtime-середовища. Це швидко знаходить відсутній CA, DNS-проблему або firewall rule, які не видно з самого Harbor-host. Якщо Kubernetes ще не підготовлений, використайте практичну інструкцію про встановлення Docker та Docker Compose на Ubuntu як базу для перевірки клієнтського Docker Engine.

Типові помилки та висновок

Найнебезпечніша помилка — запускати Harbor через HTTP і додавати його в `insecure-registries` на всіх nodes. Це створює постійний виняток замість правильної PKI. Друга помилка — використовувати `admin` у CI. Витік такого credential дає значно ширші права, ніж потрібні build job; project robot account повинен мати лише push/pull у конкретному project.

Третя помилка — публікувати тільки `latest`. Mutable tag не показує, який саме image працює, ускладнює rollback і може непомітно змінити deploy. Використовуйте version tag та immutable digest, а retention правила узгоджуйте з release history.

Четверта помилка — вважати vulnerability scan абсолютним захистом. Scanner бачить відомі проблеми у доступній vulnerability database, але не знаходить усі помилки конфігурації або логіки застосунку. Database Trivy має регулярно оновлюватися, а критичні результати — блокувати promotion за визначеною policy.

П’ята помилка — оновлювати Harbor без backup і перевірки upgrade path. Зберігайте installer directory, читайте release notes, оновлюйтесь підтримуваними кроками та тестуйте migration на копії даних. Compose deployment залишається набором взаємозалежних сервісів із state, а не одним stateless container.

Робочий Harbor Registry починається з окремого DNS, довіреного HTTPS, перевіреного installer і достатнього storage. Після запуску потрібні приватні projects, мінімальні robot accounts, scan policy, retention, garbage collection, monitoring та узгоджений backup. Лише весь цей контур робить registry надійною частиною delivery process.

Після першого push виконайте pull на чистому client, deploy у тестовий namespace, rollback за digest і recovery drill із backup. Якщо ці сценарії описані та регулярно перевіряються, Harbor зменшує залежність від зовнішніх registry й дає команді контроль над ланцюгом container artifacts без прихованих ручних кроків.

📞