Ранее я установил GitLab на виртуальную машину FreeBSD, однако то был лишь базовый набор. Хотелось продолжить эксперимент и посмотреть, что еще можно выжать из столь нетривиального сочетания. В частности, получится ли развернуть Container Registry, и да - получилось. Каким образом? Об этом и пойдет речь в сегодняшней статье.

Для контекста: устанавливается пакет gitlab-ce и отдельно PostgreSQL, а потом идет довольно длительный этап настройки. Для сборки ресурсов требуется не менее 8 гигабайт оперативной памяти. В качестве веб-сервера я использую Caddy. Пёсель меж тем обновился с версии 18.2 до 18.3, так что я на себе проверил инструкцию по обновлению и даже обнаружил ошибку (пропущенный шаг). Статью, разумеется, подправил.

Компиляция

Почему-то оный реестр не входит ни в пакет gitlab-ce как таковой, ни в какой-либо отдельный. К счастью, он написан на go, а следовательно его нетрудно собрать из исходников. Версия на момент написания – v4.27.0-gitlab. Пожалуй единственный нюанс в том, что для этого потребуется много дискового пространства (почти 2 гигабайта для кэша модулей и где-то гигабайт для кэша сборки). Небольшой скрипт (как обычно, под root, если не указано иное):

cd /usr/src
pkg install lang/go
go telemetry off
fetch -o registry.tar.gz https://gitlab.com/gitlab-org/container-registry/-/archive/v4.27.0-gitlab/container-registry-v4.27.0-gitlab.tar.gz
tar xzf registry.tar.gz
cd container-registry-v4.27.0-gitlab
go mod download
CGO_ENABLED=0 gmake PREFIX=/go binaries
file ./bin/registry | grep "statically linked"

Вместо make (как в Dockerfile) – gmake; clean не нужен, так как директория не является git-репозиторием (впрочем все равно ругается, возможно и впрямь было бы лучше склонировать репозиторий вместо скачивания архива). Последняя команда – дымовой тест, как ни странно команда file есть во FreeBSD. Почему-то пишет for FreeBSD 12.3, а у нас уже 14.3, но надеюсь ничего страшного.

По желанию можно потом очистить кэши: go clean -cache -modcache

Настройка

Копируем или переносим получившийся файл bin/registry в /usr/local/bin, а заготовку конфигурации – как /usr/local/etc/registry/config.yml для определенности. В зависимости от того, задействовать ли базу метаданных или нет, этой заготовкой будет config/database-filesystem.yml или config/filesystem.yml. Давайте пойдем по более сложному пути и все-таки сделаем БД:

# This config file is a basic configuration using database metadata and
# filesystem blob storage.
version: 0.1
log:
  accesslog:
    disabled: false
    formatter: text
  level: info
  formatter: text
  fields:
    service: registry
storage:
  delete:
    enabled: true
  filesystem:
    rootdirectory: "/usr/local/www/gitlab/shared/registry"
database:
  enabled:  true
  host:     127.0.0.1
  port:     5432
  user:     "git"
  dbname:   "registry"
  sslmode:  "disable"
http:
  # Registry API will be accessible at localhost:5000
  addr: localhost:5000
  secret: "BzVHJpRm..."
#  debug:
#    addr: :5001
#      # Metrics will be accessible at localhost:5001/metrics/
#    prometheus:
#      enabled: true
#      path: /metrics
#      # Profiling information will be accessible at localhost:5001/debug/pprof/
#    pprof:
#      enabled: true
auth:
  token:
    realm: "http://192.168.56.143/jwt/auth"
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /usr/local/www/gitlab/config/registry.crt

Раздел log я решил оставить как есть. Поменял адрес на localhost:5000 (значение по умолчанию «торчит» наружу), сгенерировал http/secret, закомментировал подраздел debug, прописал storage/filesystem/rootdirectory и параметры доступа к БД (напомню, что у меня бессовестным образом разрешены локальные подключения без пароля), а также добавил раздел аутентификации, иначе реестром смогли бы пользоваться все подряд.

Создал БД и применил миграции, за них оказывается отвечает сам реестр:

su -l postgres -c "createdb --owner=git registry"
su -l git -c "registry database migrate up /usr/local/etc/registry/config.yml"

Включил реестр в gitlab.yml:

  registry:
    enabled: true
    host: "registry.local"
    http_secret: "BzVHJpRm..."
    api_url: http://localhost:5000/ # internal address to the registry, will be used by GitLab to directly communicate with API
    key: /usr/local/www/gitlab/config/registry.key
    path: /usr/local/www/gitlab/shared/registry
    issuer: gitlab-issuer

Пришлось прописывать «симметричные» параметры, иначе возникала ошибка 500 при попытке открыть настройки репозиториев. Уж не знаю, является ли галлюцинацией ИИ указание http_secret здесь, но пусть живет. «На проде» в Docker такого нет, а сам этот ключ хранится в gitlab-secrets.json, которого в свою очередь нет во FreeBSD. Пути на всякий пожарный прописал абсолютные. Сгенерировал сертификат для реестра:

cd /usr/local/www/gitlab/config
openssl genrsa -out registry.key 3072
openssl req -new -key registry.key -out registry.csr
openssl x509 -req -days 365 -in registry.csr -signkey registry.key -out registry.crt

Вторая команда задает различные вопросы, я конечно же ответил на них весьма номинально:

Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:registry.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Что касается срока сертификата, то я для примера поставил год, но вот как лучше поступить в реальности, вопрос неоднозначный. То ли сделать срок поменьше и генерировать новый при каждом обновлении реестра, то ли поставить лет на 10 и забыть. Кстати в Docker сертификат как раз десятилетний.

Перезапустил GitLab:

service gitlab restart

Реестр пока запустил врукопашную в отдельном сеансе:

su -l git -c "registry serve /usr/local/etc/registry/config.yml"

Проверка и завершение настройки

Создал частный (private) репозиторий root/container-registry и включил в нем реестр контейнеров. Прописал registry.local в /etc/hosts. С помощью установленного ранее Podman попробовал было «запушить» образ freebsd-static:14.3, его идентификатор 749192a8d953. Оказалось, что все должно работать по https. К счастью, у нас есть не только Caddy, но и сертификат, который можно переиспользовать. Автоматический https у меня полностью отключен, так что придется еще и явно прописать редирект. Добавляем настройки в Caddyfile:

http://registry.local {
    redir https://registry.local{uri}
}

registry.local {
    tls /usr/local/www/gitlab/config/registry.crt /usr/local/www/gitlab/config/registry.key
    reverse_proxy localhost:5000
}

Ранее я настраивал portacl только для http (да еще безапелляционно заявил, что https на виртуалке ни к чему, а вот поди ж ты), пришлось вернуть стандартную настройку. Перезапустил сервисы portacl и caddy. Авторизовал Podman в registry.local и повторно отправил образ:

podman login registry.local --tls-verify=false
podman push 749192a8d953 registry.local/root/container-registry:freebsd-14.3-static --tls-verify=false

--tls-verify=false нужно для обхода самоподписанного сертификата. Работает?!

container_registry.png

Чтобы каждый раз не отключать проверку TLS через аргумент командной строки, добавим такой фрагмент в файл /usr/local/etc/containers/registries.conf:

[[registry]]
location = "registry.local"
insecure = true

Если работает podman_service, то целесообразно его перезапустить для применения изменений в нем.

Примечание от 18.09.2025. Фактически благодаря такой записи реестр может работать и по http, так что можно убрать редирект и сертификат из Caddyfile.

Сделаем репозиторий публичным и намутим мутку:

podman logout registry.local
podman image rm 749192a8d953
podman pull registry.local/root/container-registry:freebsd-14.3-static
Trying to pull registry.local/root/container-registry:freebsd-14.3-static...
Getting image source signatures
Copying blob bf0d0a3c3204 done   |
Copying config 749192a8d9 done   |
Writing manifest to image destination
749192a8d9532583948dae8a82a5aad80d4b08eb4b523890505f6d22552eebb0

Таки загружает!

Сервис rc.d

Остается открытым вопрос с автоматическим запуском реестра. Теоретически можно было бы смухлевать и добавить команду в crontab, но лучше написать сервис, хоть и весьма упрощенный.

Файл /usr/local/etc/rc.d/registry (права 755):

#!/bin/sh

# PROVIDE: registry
# REQUIRE: DAEMON NETWORKING
# BEFORE:  gitlab
# KEYWORD: shutdown

#
# Add the following line to /etc/rc.conf to enable registry:
#
# registry_enable (bool):  Set to "NO" by default.
#                          Set it to "YES" to enable registry
# registry_config (str):   Set to "/usr/local/etc/registry/config.yml" by default.
#                          Set it to configuration file to run registry with
# registry_user (str):     Set to "git" by default.
#                          Set it to user to run registry under
# registry_group (str):    Set to "git" by default.
#                          Set it to group to run registry under
# registry_logfile (str):  Set to "/var/log/registry.log" by default.
#                          Set it to file to send registry logs to
#

. /etc/rc.subr

name="registry"
rcvar="registry_enable"

load_rc_config $name

: ${registry_enable:="NO"}
: ${registry_config:="/usr/local/etc/registry/config.yml"}
: ${registry_user:="git"}
: ${registry_group:="git"}
: ${registry_logfile:="/var/log/registry.log"}
: ${registry_args:="serve $registry_config"}
: ${registry_svcj_options:="net_basic"}

pidfile="/var/run/${name}.pid"
procname=/usr/local/bin/${name}

start_precmd="registry_startprecmd"
start_cmd="registry_startcmd"

registry_startprecmd()
{
        if [ ! -e "${pidfile}" ]; then
                install -g ${registry_group} -o ${registry_user} -- /dev/null "${pidfile}";
        fi
}

registry_startcmd()
{
        daemon -u ${registry_user} -p ${pidfile} ${procname} ${registry_args} run < /dev/null >> ${registry_logfile} 2>> ${registry_logfile}
}

run_rc_command $1

Фактически я переделал сервис gitlab_pages. Помимо прочего, добавил указание запуска до GitLab. Вообще, раз теперь лог пишется в файл, возможно стоило бы повысить его уровень до warn или даже error.

Если вдруг реестр еще запущен, то выходим по Ctrl+\. Включаем и запускаем сервис:

service registry enable
service registry start

Вот теперь все практически как в лучших домах.

Прокси зависимостей

Оно включено по умолчанию и, как ни странно, тоже работает. Добавляем «реестр» 192.168.56.143 как небезопасный (GitLab как таковой у меня работает «по IP» без https):

[[registry]]
location = "192.168.56.143"
insecure = true

Авторизуем Podman непосредственно в GitLab (несмотря на публичность группы, без входа возвращается статус 403 Forbidden) и скачаем для примера все тот же образ freebsd-static:

podman login 192.168.56.143
podman pull 192.168.56.143/containers/dependency_proxy/containers/freebsd/freebsd-static:14.3

Первая containers – это идентификатор (пространство имени) группы.

dependency_proxy.png

В настройках группы (Settings – Package and registers, разделе Dependency proxy) можно задать настройки аутентификации в Docker Hub, по идее станет чуть свободнее в плане ограничений на загрузку образов.

Резервное копирование и обновление

Напомню основную команду бэкапа для варианта компиляции из исходников, к которой относится установка GitLab во FreeBSD:

su -l git -c "cd /usr/local/www/gitlab && rake gitlab:backup:create RAILS_ENV=production"

Файловое хранилище реестра контейнеров, благодаря выполненным настройкам, в данный архив попадает. Базу метаданных же придется сохранять отдельно:

pg_dump -U git registry | gzip -9 > registry.sql.gz

А также созданные нами файлы настроек и определения сервиса.

Обновление сводится к компиляции новой версии реестра, остановке сервиса, замене исполняемого файла, применения миграций к базе метаданных при наличии таковой и запуске сервиса обратно. Если вдруг закончился срок действия сертификата для аутентификации, то потребуется сделать его заново наряду с перезапуском GitLab и веб-сервера (если он вдруг задействован и там).

Вместо заключения

Я не очень понял, почему нет пакета для реестра контейнеров, в то время как в стандартную поставку входят Pages (с которыми-то, забегая вперед, все как раз очень сложно). К счастью, программу реестра оказалось относительно просто скомпилировать и настроить вручную.

Я подумывал о том, чтобы сделать контейнер Podman, но тогда не совсем понятно, как быть с PostgreSQL в частности и IP адресами в целом, ведь все это должно друг с другом и самим GitLab интенсивно взаимодействовать. А еще меня немного смущает Apache License 2.0, ну и актуальность сего действа (в смысле создание образа) тоже далеко не очевидна.


Категория: Программирование, веб | Опубликовано 12.09.2025 | Редакция от 18.09.2025

Похожие материалы

Переезд реестра контейнеров GitLab в S3

Ранее я писал о MinIO в качестве хранилища реестра контейнеров, но в случае VDS/VPS такой вариант экономически не выгоден: чуть ли не на порядок дешевле воспользоваться услугой аренды S3 у какого-нибудь облачного провайдера. Что я и решил сделать, ведь место на сервере стало очень быстро заканчиваться. Заодно мигрируем прокси зависимостей, LFS и всякое такое.


Комментарии, обсуждение