Harbor - это бесплатный реестр для хранения Docker образов. Умеет сканировать образы на уязвимости. Проект запущен в 2016 году командой VMware. В 2018 Harbor перешел под контроль организации CNCF и с тех пор активно развивается, поэтому новые релизы выходят несколько раз в месяц.
Зачем он нужен?
Хранить образы контейнеров в Docker Hub конечно удобно, но 99% компаний хранят их приватно на своих серверах.
Но хранить на своих серверах это половина, другое дело делать это в закрытом контуре компании, где нет интернета.
Этот гайд именно про такую установку.
Основные отличия установки: переменные закрывающие обновление сканеру уязвимостей Trivy и ручное обогащение баз. В остальном всё тоже самое.
Собираю единомышленников в телеграм канале -
Присоединяйся

Шаг 1. Установка Harbor

Шаг 1.1 Ставим docker
Ставим docker и compose:
1
2
3
4
| apt update && \
apt install containerd docker.io docker-compose -y`
systemctl enable docker --now && \
sudo usermod -aG docker $USER
|
Шаг 1.2 Скачиваем Harbor и готовим конфиги
Клонируем репозиторий. Обернул в переменные, чтобы версия файла была всегда актуальна:
1
2
3
4
5
6
7
8
9
10
11
| LATEST=$(curl -s https://api.github.com/repos/goharbor/harbor/releases/latest \
| grep browser_download_url \
| grep offline-installer \
| cut -d '"' -f 4)
FILE=$(basename "$LATEST")
wget "$LATEST" && \
tar xvzf "$FILE" && \
rm "$FILE" && \
cd harbor
|
Создаём файл .env:
Прописываем в переменных пароль Админа и БД:
1
2
| HARBOR_ADMIN_PASSWORD=super_admin_pazzword
DB_PASSWORD=super_db_mazafaka
|
Изменяем права:
Далее работаем с файлом harbor.yml
Создаём резервную копию файла:
1
| sudo cp harbor.yml.copy harbor.yml
|
Чтобы хосты доверяли этому репозиторию нужно создать серты в Центре Сертификатов (CA).
1
2
3
4
5
| Создайте сертификаты в вашем ЦА с именами:
harbor.example.local.key
harbor.example.local.crt
где harbor.example.local доменное имя вашего будущего репозитория.
Или перейдите на Шаг 3, затем вернитесь сюда.
|
Открываем на редактирование:
1
| sudo nano /opt/harbor/harbor.yml
|
Удаляем содержимое файла и вставляем параметры:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| hostname: harbor.example.local
http:
port: 80
https:
port: 443
certificate: /opt/harbor/harbor.example.local.crt
private_key: /opt/harbor/harbor.example.local.key
harbor_admin_password: ${HARBOR_ADMIN_PASSWORD}
database:
password: ${DB_PASSWORD}
max_idle_conns: 200
max_open_conns: 100
conn_max_lifetime: 5m
conn_max_idle_time: 5m
data_volume: /data
trivy:
ignore_unfixed: false
skip_update: true #Если есть инет, то ставь false
skip_java_db_update: true #Если есть инет, то ставь false
offline_scan: true #Если есть инет, то ставь false
security_check: vuln
insecure: false
timeout: 5m0s
jobservice:
max_job_workers: 10
max_job_duration_hours: 24
job_loggers:
- STD_OUTPUT
- FILE
logger_sweeper_duration: 1 #days
notification:
webhook_job_max_retry: 3
webhook_job_http_client_timeout: 3 #seconds
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 2.14.0
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy
upload_purging:
enabled: true
age: 168h
interval: 24h
dryrun: false
cache:
enabled: false
expire_hours: 24
|
Мой Harbor работает в закрытом контуре (без доступа к интернету). Что это значит?
Это значит что базы сканера уязвимостей Trivy встроенного в него не будут обновляться напрямую, а только вручную (Шаг 4). Настройки конфигурации я делал исходи из этого требования.
Шаг 2. Запуск установки
Без дополнительных параметров (–with) компонент не установится:
1
| sudo ./install.sh --with-trivy
|
Шаг 2.1 Вход в UI
После установки мы можем войти по адресу, который вы указали. В моём случае https://harbor.example.local
Логин и пароль мы задавали в .env файле

Шаг 3. Создание ЦА и подписание сертификата
Создаём директорию:
1
2
| sudo mkdir -p ~/harbor/certs
sudo cd ~/harbor/certs
|
Создаём серты ЦА:
1
2
3
4
5
6
7
| # Root CA key
openssl genrsa -out root-ca.key 4096
# Root CA cert (10 лет, можно меньше)
openssl req -x509 -new -nodes -sha256 -days 3650 \
-key root-ca.key -out root-ca.crt \
-subj "/C=RU/ST=Moscow/L=Moscow/O=HomeLab/OU=ITZM/CN=My-Root-CA"
|
Изменить значение перменных на своё имя и IP Harbor сервера:
1
2
| export HARBOR_HOST=harbor.example.local
export MyIP=2.2.2.2
|
Выполнить команды:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| # server key
openssl genrsa -out ${HARBOR_HOST}.key 4096
# csr config with SAN
cat > ${HARBOR_HOST}.csr.cnf <<EOF
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
C=RU
ST=Moscow
L=Moscow
O=HomeLab
OU=ITZM
CN=${HARBOR_HOST}
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${HARBOR_HOST}
IP.1 = ${MyIP}
EOF
# create CSR
openssl req -new -key ${HARBOR_HOST}.key -out ${HARBOR_HOST}.csr -config ${HARBOR_HOST}.csr.cnf
# sign server cert by our CA
openssl x509 -req -in ${HARBOR_HOST}.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial \
-out ${HARBOR_HOST}.crt -days 825 -sha256 \
-extensions req_ext -extfile ${HARBOR_HOST}.csr.cnf
|
На выходе:
root-ca.crt - корневой сертификат, который надо раздать всем клиентам/нодам.
${HARBOR_HOST}.crt и ${HARBOR_HOST}.key - серверные для Harbor
Корневой скопировать на все хосты:
Ubuntu
1
2
3
| /usr/local/share/ca-certificates/
# Применить:
sudo update-ca-certificates
|
CentOS
1
2
3
| /etc/pki/ca-trust/source/anchors/
# Применить:
sudo update-ca-trust extract
|
Перезапустить докер на хостах:
1
| systemctl restart docker.service
|
Шаг 4. Оффлайн обновление Trivy
Сканер уязвимостей Trivy требует регулярных обновлений.
В данном примере мы выкачаем базу уязвимостей, а затем перенесем на закрытый контур.
Дальше можно автоматизировать обновления скриптом и т.д. на вашу фантазию.
Есть например вариант, поднять Harbor в контуре с инетом и в контуре без него и настроить репликацию между ними.
На компе с инетом ставим докер и качаем обновления:
1
2
3
4
| apt update && \
apt install docker.io -y`
systemctl enable docker --now && \
sudo usermod -aG docker $USER
|
Далее выкачиваем образы:
1
2
| docker pull ghcr.io/aquasecurity/trivy-db:2
docker pull ghcr.io/aquasecurity/trivy-java-db:1
|
После чего упаковываем:
1
2
3
4
5
6
7
8
9
10
11
12
| # DB
cid=$(docker create ghcr.io/aquasecurity/trivy-db:2)
docker cp $cid:/db db
docker rm $cid
# Java DB
cid=$(docker create ghcr.io/aquasecurity/trivy-java-db:1)
docker cp $cid:/java-db java-db
docker rm $cid
tar czf trivy-db.tgz db
tar czf trivy-java-db.tgz java-db
|
Переносим на Harbor-хост, где нет инета и распаковать в контейнер trivy-adapter:
1
2
3
4
5
6
| sudo mkdir -p /data/trivy-adapter/trivy/db
sudo mkdir -p /data/trivy-adapter/trivy/java-db
sudo tar -xzf trivy-db.tgz -C /data/trivy-adapter/trivy/db
sudo tar -xzf trivy-java-db.tgz -C /data/trivy-adapter/trivy/java-db
sudo chown -R 10000:10000 /data/trivy-adapter/trivy 2>/dev/null || true
docker restart trivy-adapter
|
Сканирование работает.
