Home » Devops » Gitlab Container Registry за Nginx reverse proxy

Gitlab Container Registry за Nginx reverse proxy

Достаточно долгое время у меня не получалось корректно настроить одновременную работу Gitlab и встроенный Container Registry. Сложность состояла в том, что все это хозяйство работало за внешним nginx reverse proxy с настроенным https. С прокси же запросы на сам gitlab шли по http и на сервере сертификатов не было вовсе. Это важно, так как не хотелось одновременно настраивать и обновлять сертификаты на nginx proxy и gitlab.

Если у вас есть желание освоить Linux с нуля, не имея базовых знаний, рекомендую познакомиться с онлайн-курсом Administrator Linux.Basic в OTUS. Курс для новичков, для тех, кто хочет войти в профессию администратора Linux. Подробности по .

Введение

Просто настроить gitlab за nginx в режиме proxy_pass не представляет никакой сложности. Трудности возникают именно тогда, когда вы хотите использовать встроенный Container Registry. Я несколько раз подходил к этой задаче и каждый раз отступал, либо отказываясь от registry, либо от nginx proxy.

Без прокси неудобно, так как чаще всего, если у вас есть какая-та инфраструктура, а не одиночный сервер, смотреть напрямую в интернет у вас будет какой-то шлюз, а не сам сервис. Так удобно разграничивать доступ, контролировать и перенаправлять подключения, следить за сертификатами, балансировать нагрузку и т.д. В общем, я использую его всегда, когда это возможно и оправдано (почти всегда).

С registry не получалось корректно настроить работу за прокси. Я перепробовал все советы, что только нашел в интернете. Перечитал всю документацию, но так ничего не получилось. Команда docker login успешно отрабатывала на сервере, а вот запушить образ в реджистри gitlab никак не получалось. Получал ошибку.

Gitlab Error: Status 404 trying to push repository
Error: Status 404 trying to push repository zeroxzed/website

Проблему я в итоге решил, когда залез во внутренности gitlab и разобрался, как там все устроено. Когда все понял, придумал рабочее решение, которым с вами делюсь.

Gitlab и proxy nginx

Если у вас используется только сам gitlab, без встроенного registry, то никаких особых настроек делать не надо. Достаточно выполнить обычную установку gitlab. В качестве EXTERNAL_URL во время установки можно указать адрес с http. Затем, после установки, настраивайте proxy nginx примерно вот так.

server {
    listen 443 http2 ssl;
    server_name gl.serveradmin.ru;
    access_log /var/log/nginx/gl.serveradmin.ru-access.log full;
    error_log /var/log/nginx/gl.serveradmin.ru-error.log;

    ssl_certificate /etc/letsencrypt/live/gl.serveradmin.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gl.serveradmin.ru/privkey.pem;

    limit_conn perip 50;

    location /.well-known {
    root /tmp;
    }

    location / {
    proxy_pass http://10.20.50.8:80;
    proxy_read_timeout      300;
    proxy_connect_timeout   300;
    proxy_redirect          off;
    proxy_set_header        X-Forwarded-Proto https;
    proxy_set_header        Host              $http_host;
    proxy_set_header        X-Real-IP         $remote_addr;
    proxy_set_header        X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Ssl   on;
    }
}

server {
    listen 80;
    server_name gl.serveradmin.ru;
    return 301 https://gl.serveradmin.ru$request_uri;
}

На самом сервере с gitlab в /etc/gitlab/gitlab.rb измените параметры.

external_url 'https://gl.serveradmin.ru'
nginx['listen_port'] = 80
nginx['listen_https'] = false

И после этого дайте команду на переконфигурацию системы.

gitlab-ctl reconfigure

После этого gitlab будет нормально работать за nginx proxy. Дальше рассказываю, что надо сделать, чтобы включить и нормально запустить в работу Container Registry за reverse proxy.

Настройка Gitlab registry за reverse nginx proxy

На первый взгляд никаких особенных сложностей быть не должно. Делаем по аналогии настройки, только для registry_nginx и пробуем работать с registry. Но ничего не получится. Будет приведенная выше ошибка. Я покопался в настройках gitlab и понял, в чем проблема.

Если у вас используется одинаковый url для web интерфейса gitlab и registry, то корректная работа за nginx proxу невозможна. Я посмотрел конфигурацию nginx, входящего в состав gitlab. Она живет тут - /var/opt/gitlab/nginx/conf. Там отдельный конфиг для web интерфейса и для registry. Если используются одинаковые доменные имена, то все запросы попадают на конфигурацию веб интерфейса и проксируются на gitlab-workhorse.

Это происходит, потому что директива server_name в обоих конфигах одинаковая. Обрабатывается первым то, что стоит раньше в конфигурации. Я заподозрил это еще раньше, когда 404 ошибки обращений к registry обнаруживал в лог файлах /var/log/gitlab/nginx/gitlab_access.log, тогда как gitlab_registry_access.log были пустые.

Сбивало с толку то, что авторизация docker login при этом отрабатывала корректно, а ошибка возникала только во время push. Судя по всему, процесс авторизации один и тот же, что для registry, что для http доступа. В общем, чтобы все корректно работало, вам нужно разделить на разные домены gitlab и registry.

Я сделал для registry отдельный домен. Настроил для него проксирование, примерно так.

server {
    listen 443 http2 ssl;
    server_name rg.serveradmin.ru;
    access_log /var/log/nginx/rg.serveradmin.ru-access.log full;
    error_log /var/log/nginx/rg.serveradmin.ru-error.log;

    ssl_certificate /etc/letsencrypt/live/rg.serveradmin.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rg.serveradmin.ru/privkey.pem;

    limit_conn perip 50;

    location /.well-known {
    root /tmp;
    }

    location / {
    proxy_pass http://10.20.50.8:80;
    proxy_read_timeout      300;
    proxy_connect_timeout   300;
    proxy_redirect          off;
    proxy_set_header        X-Forwarded-Proto https;
    proxy_set_header        Host              $http_host;
    proxy_set_header        X-Real-IP         $remote_addr;
    proxy_set_header        X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Ssl   on;
    proxy_set_header        X-Frame-Options   SAMEORIGIN;
    proxy_cache off;
    proxy_buffering off;
    proxy_request_buffering off;
    proxy_http_version 1.1;
    }
}

server {
    listen 80;
    server_name rg.serveradmin.ru;
    return 301 https://rg.serveradmin.ru$request_uri;
}

Дальше в gitalb.rb добавил параметры, отвечающие за работу registry.

registry_external_url 'https://rg.serveradmin.ru'
gitlab_rails['registry_enabled'] = true
registry['enable'] = true
registry_nginx['enable'] = true
registry_nginx['proxy_set_headers'] = {
 "Host" => "$http_host",
 "X-Real-IP" => "$remote_addr",
 "X-Forwarded-For" => "$proxy_add_x_forwarded_for",
 "X-Forwarded-Proto" => "https",
 "X-Forwarded-Ssl" => "on"
 }
registry_nginx['listen_port'] = 80
registry_nginx['listen_https'] = false

Я не уверен, что нужны все эти параметры. Привожу пример с реально работающего сервера и чтобы случайно чего-то не забыть, привожу сразу все, что на нем сейчас активно из настроек. Думаю, заголовки указывать не обязательно. Без них тоже заработает.

После этого перечитывайте конфигурацию gitlab и nginx и проверяйте работу.

Проверка работы gitlab registry

Теперь проверим работу Gitlab Container Registry. Для этого создаем любой проект через web интерфейс. Идем в раздел Packages -> Container Registry. Там увидите краткую инструкцию по работе с реджистри.

Настройка gitlab registry

Идем на сервер, где будем собирать образы docker. Настраиваем подключение к registry, указав логин с паролем.

docker login rg.serveradmin.ru
Username: zeroxzed
Password:
Login Succeeded

Создадим тестовый докер образ из Dockerfile.

FROM busybox
RUN echo "Test OK"

Собираем образ и загружаем его в registry.

# docker image build -t rg.serveradmin.ru/zeroxzed/myapp:latest .
# docker push rg.serveradmin.ru/zeroxzed/myapp:latest
docker build and push image

Указанный образ будет загружен в Registry данного проекта.

Container registry в gitlab

Часто задаваемые вопросы по теме статьи (FAQ)

Почему запросы с proxy на сервер gitlab идут без шифрования по протоколу http?

В моем примере запросы с прокси на рабочий сервер идут в рамках закрытой непубличной инфраструктуры, где вероятность перехвата трафика минимальна. Нет смысла тратить ресурсы и время на настройку и обновления сертификатов не только на nginx proxy, но и рабочем сервере.

Возможно ли настроить подобное проксирование со шлюза на рабочий сервер через интернет?

Да, это возможно. Принципиальной разницы нет. Единственное отличие - нужно использовать протокол https при перенаправлении запросов с прокси на сервер gitlab.

Можно ли таким же способом проксировать запросы к встроенным gitlab pages или mattermost?

Да, настраивается это примерно так же. Необходимо создать поддомен для каждого сервиса и по аналогии с приведенным примером настроить перенаправление запросов с nginx на gitlab.

У вас есть подробный материал, где рассказано о том, как настроить и начать работать с gitlab?

Да, у меня есть отдельная статья - установка, настройка и работа с gitlab.

Заключение

Не понравилась статья и хочешь научить меня администрировать? Пожалуйста, я люблю учиться. Комментарии в твоем распоряжении. Расскажи, как сделать правильно!

На этом все по работе gitlab за nginx proxy. Настройка очень простая, продуктом пользоваться удобно. Настроить типовой ci/cd на базе докера очень просто. В будущем опишу такой пример. Так что рекомендую Gitlab для совместной работы команды. Минус у него только один - очень требователен к ресурсам.

Онлайн курс IoT-разработчик

Если у вас есть желание научиться обрабатывать миллиарды данных, рекомендую познакомиться с онлайн-курсом "IoT-разработчик" в OTUS. Курс не для новичков, для поступления нужны базовые знания по ООП и умение программировать. Обучение длится 4 месяца, после чего успешные выпускники курса смогут пройти собеседования у партнеров. По окончании курса вы будете уметь:
  • анализировать основные составные части IoT;
  • строить системы датчиков/исполнительных элементов, используя микроконтроллер Arduino и эмуляторы, в том числе самописные;
  • создавать программы на Python, обеспечивающие функциональность IoT для одноплатного компьютера Raspberry Pi;
  • формировать представление об архитектуре существующих IoT-решений и программно-аппаратных комплексах;
  • разбираться в системах IoT, способных решать глобальные проблемы производства, транспорта, здравоохранения или энергетических систем;
  • проектировать и строить прототипы IoT-решений с помощью платформы Интернета вещей Rightech IoT Cloud от уровня железа до клиентоориентированного приложения.
Проверьте себя на вступительном тесте и смотрите подробнее программу по .

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Автор Zerox

Zerox
Владимир, системный администратор, автор сайта. Люблю настраивать сервера, изучать что-то новое, делиться знаниями, писать интересные и полезные статьи. Открыт к диалогу и сотрудничеству.

7 комментариев

  1. Аватар
    Александр

    Ой какая тема классная! как раз на прошлой неделе занимался gitlab.
    Вобщем такая проблема имеется:

    есть сервер nginx, он в моей локальной сети с адресом 192.168.10.40 (к нему микротик пробрасывает 80 и 443 порты)
    есть сервер gitlab, он тоже в моей сети с адресом 192.168.10.50

    настраиваю сертификат на nginx, проксирую на gitlab

    Если из внешки заходить - gitlab виден, с https, все красиво.
    Чтоб из локалки заходить - прописываю на микротике static dns и направляю его на nginx. Все, теперь из локалки gitlab виден по https.

    А теперь пробую клонировать репозиторий, и тут затык.
    Запрос идет на 22 порт nginx.

    Гуглил, спрашивал в телеграм чатах.
    Мне подсказали делать через hairpin nat.
    Тоесть чтоб запросы шли как-то через внешку.
    Вот и статья есть вроде понятная - https://lantorg.com/article/kak-zajti-po-vneshnemu-ip-adresu-iz-lokalnoj-seti-dlya-mikrotik

    Но мне кажется я что-то упустил, и делаю неправильно.
    Как быть? Подскажите направление.

    • Zerox

      Да, с ssh есть нюансы, как и со всем остальным. Держать gitlab за NAT немного геморройно, если доступ идет с двух сторон. Как самое простое решение, работать с репозиториями по https, а не ssh.

      Может еще сработает вариант подключения git по ip адресу, а не домену. Для ssh подключений валидный сертификат не нужен, так что должно сработать, но я не проверял. Обычно у меня gitlab где-то в виртуалке на дедике за шлюзом. Работать из локальной сети с ним не надо. Все запросы из вне идут.

    • Аватар

      У меня сделано так:

      /ip firewall nat print

      0 chain=dstnat action=dst-nat to-addresses= to-ports= protocol=tcp dst-address= dst-port= log=no log-prefix=""
      1 chain=srcnat action=masquerade protocol=tcp src-address= dst-address= out-interface=bridge-local dst-port=
      2 chain=srcnat action=masquerade out-interface=WAN log=no log-prefix=""

  2. Аватар
    Евгений

    Добрый день, Владимир. Можете подсказать в следующей ситуации. У нас есть корпоративный registry gitlab, к которому можно подключиться только по VPN. Есть такая задача, я тестирую новое облако, в котором поднят кластер kuberntetes, чтобы выкачивать образы с нашего registry я добавлял IP ноды в новом кластере в белый список IP-ков для registry. Но выяснилась проблема так как в облаке нет нет VPC (как у большой тройки), Pod-ы поднимаются на разных нодах которые имеют каждый раз разные IP-адреса и постоянно расширять свой список адресов, которым разрешен доступ я не могу. Как вы посоветуете решить эту проблему? Я пытался поднять в кубернетес openvpn, и запустить его с коропоротвным VPN сертификатом, но это у меня не вышло, да и не совсем правильное наверно это решение пробовал вот это https://github.com/helm/charts/tree/master/stable/openvpn
    Буду благодарен за любой совет, спасибо!

    • Zerox

      Openvpn в Kubernetes тут точно не поможет. Нужно разбираться, как организована маршрутизация для нод кластера Kubernetes. Самое простое и верное решение, на мой взгляд - настроить отдельный шлюз, через который все ноды кластера будут выходить во внешний мир. Возможность такой настройки зависит от конкретного облачного провайдера Kubernetes. Я думаю, проще всего задать этот вопрос поддержке облака. Я думаю, они предложат решение. Ситуация не экзотическая, а скорее типовая. А дальше уже ip адрес этого шлюза добавите в белый лист на доступ к registry.

      • Аватар
        Евгений

        Спасибо за быстрый ответ, Владимир. Ситуация в том, что маршрутизацию в Kubernetes можно было бы организовать если бы у меня был бы доступ к самому кластеру, а такак у меня доступ через Kubectl только то вредил удасться настроить маршруты через какой нибудь соседний инстанс у этого провайдера.

        • Zerox

          Если у вас доступ только как пользователя кластера, судя по всему в отдельном неймспейсе, решить этот вопрос вы можете только через тех. поддержку.

Добавить комментарий

Ваш адрес email не будет опубликован.

Нажимая кнопку "Отправить комментарий" Я даю согласие на обработку персональных данных.