Стабильно

Настройка GitLab за BusinessProxy App Gateway

Пошаговая настройка самостоятельного GitLab через BusinessProxy без прямой публикации сервера GitLab в интернет.

Шаги

Выполняйте по порядку.

  1. 01Выбрать один канонический доменРедиректы, cookies, статика и WebSocket GitLab должны работать через один и тот же публичный хост.
  2. 02Подготовить внутренний GitLabОставьте публичный URL GitLab на HTTPS; для внутреннего подключения выберите HTTP, проверяемый HTTPS или существующий reverse proxy.
  3. 03Создать внутреннее приложение BusinessProxyОпубликуйте GitLab через коннектор и привяжите пользовательский домен, совпадающий с external_url GitLab.
  4. 04Добавить технический доступ для пакетных инструментовПредоставьте npm, Yarn и разрешённым CI-клиентам ограниченный межмашинный доступ без раскрытия GitLab credential.
  5. 05Проверить редиректы, статику и WebSocketКорректная настройка отдаёт страницу входа и загружает CSS, JavaScript и live-endpoints с того же публичного домена.
  6. 06Разобрать типовые ошибки502, зависшая статика, циклические редиректы и ошибки CSRF обычно указывают на несовпадение домена, схемы или TLS внутреннего сервера.

Справочник

Детали реализации для настройки и проверки.

Когда использовать эту инструкциюИспользуйте эту схему, когда GitLab развёрнут в частной сети и должен открываться только через управляемую сессию внутреннего приложения BusinessProxy. BusinessProxy контролирует, кто может открыть веб-интерфейс GitLab; пользователи, проекты, группы, права и доступ к репозиториям по-прежнему управляются внутри GitLab.
  • Не оставляйте внутренний GitLab напрямую доступным из интернета.
  • Предпочтителен постоянный пользовательский домен, например gitlab.example.com. Системный адрес тоже допустим: используйте его точное уникальное имя, показанное BusinessProxy, как канонический URL.
  • Запустите коннектор BusinessProxy там, где он достигает выбранного внутреннего HTTP- или HTTPS-адреса GitLab.
1. Выберите канонический публичный доменGitLab чувствителен к публичному адресу. Редиректы, CSRF-проверки, cookies, пути к статике и WebSocket-адреса формируются из external_url. Выберите один домен, который пользователи будут открывать в браузере, и используйте его везде без расхождений.
  • Рекомендуемый вид: https://gitlab.example.com.
  • Не открывайте один GitLab через несколько публичных alias-адресов; cookies и редиректы могут стать непредсказуемыми.
  • Создайте DNS-запись, которую показывает мастер пользовательского домена BusinessProxy, и дождитесь активного сертификата.
2. Настройте GitLab для работы за reverse proxyПубличный URL и внутренний транспорт — разные настройки. external_url описывает HTTPS-адрес в браузере пользователя; listen_https управляет только внутренним NGINX. Для GitLab 19.1 и более ранних версий, включая 18.11, вариант с HTTP-upstream ниже не требует локального TLS-сертификата.
external_url 'https://gitlab.example.com'
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['redirect_http_to_https'] = false
letsencrypt['enable'] = false
  • После изменения /etc/gitlab/gitlab.rb выполните sudo gitlab-ctl reconfigure.
  • В поле «Внутренний upstream» укажите внутренний адрес, например http://gitlab.internal:9080 при отображении Docker-порта 9080 на порт 80 контейнера. Не подставляйте этот внутренний IP, хост или порт в external_url.
  • Оставьте одно действующее объявление external_url. Ruby обрабатывает файл по порядку: позднее значение HTTP перекрывает предыдущее HTTPS. Также проверьте явно заданные proxy_set_headers.
  • Используйте HTTP только на доверенном внутреннем участке. Разрешите доступ к порту GitLab только узлам коннектора; публичное соединение браузера и туннель коннектора BusinessProxy остаются зашифрованными.
2а. Имена настроек в GitLab 19.2 и новееВ GitLab 19.2 настройки NGINX для Rails перенесены в gitlab_rails[nginx]. Используйте имена параметров для установленной версии, а не копируйте конфигурацию другой версии без проверки.
external_url 'https://gitlab.example.com'
gitlab_rails['nginx']['listen_port'] = 80
gitlab_rails['nginx']['listen_https'] = false
gitlab_rails['nginx']['redirect_http_to_https'] = false
letsencrypt['enable'] = false
2б. HTTPS между коннектором и GitLabВыберите этот вариант, если во внутренней сети тоже требуется шифрование. Сохраните тот же канонический external_url и включите TLS внутреннего слушателя. Пример использует имена параметров GitLab до 19.2; для 19.2+ примените ключи gitlab_rails[nginx], показанные выше.
external_url 'https://gitlab.example.com'
nginx['listen_port'] = 443
nginx['listen_https'] = true
nginx['ssl_certificate'] = '/etc/gitlab/ssl/gitlab.example.com.crt'
nginx['ssl_certificate_key'] = '/etc/gitlab/ssl/gitlab.example.com.key'
  • Укажите HTTPS-upstream с именем, совпадающим с сертификатом, например https://gitlab.example.com:9443: внутренний DNS должен вести прямо к GitLab, а Docker — отображать внутренний порт 9443 на порт 443 контейнера. Не направляйте этот адрес обратно на шлюз BusinessProxy.
  • Оставьте проверку TLS внутреннего сервера включённой. Для частного удостоверяющего центра установите его CA в хранилище доверия среды коннектора. Сертификат на DNS-имя не подтверждает адрес с голым IP, если этот IP не включён в сертификат.
2в. GitLab за дополнительным внутренним reverse proxyЕсли коннектор обращается к существующему NGINX или ingress, а не прямо к GitLab, этот прокси должен сохранить публичную схему HTTPS, даже если следующий участок использует HTTP. Пример location NGINX ниже предназначен для отдельного виртуального хоста, обслуживающего только этот защищённый HTTPS-маршрут.
location / {
    proxy_pass http://gitlab.internal:80;
    proxy_set_header Host gitlab.example.com;
    proxy_set_header X-Forwarded-Host gitlab.example.com;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_set_header X-Forwarded-Port 443;
}
  • Не заменяйте исходную схему HTTPS внутренним HTTP-значением $scheme. Принимайте информацию о проксировании только от доверенных адресов коннектора или прокси, а не от произвольных клиентов интернета.
  • Для установки не через Omnibus или через Helm используйте предусмотренные ею настройки публичного URL и доверенного прокси. Примеры gitlab.rb не применяются к другой схеме развёртывания автоматически.
3. Проверьте GitLab с узла коннектораПеред публикацией приложения убедитесь, что узел коннектора достигает GitLab по тому внутреннему адресу, который будет указан как upstream. Так вы отделите проблемы GitLab и сети от проблем маршрутизации BusinessProxy.
curl -I http://gitlab.internal/users/sign_in
curl -I -H "Host: gitlab.example.com" http://gitlab.internal/users/sign_in
  • Ответ должен быть HTTP 200 или штатным редиректом GitLab, а не TLS-ошибкой или таймаутом подключения.
  • Если GitLab редиректит на другой хост, сначала исправьте external_url.
4. Создайте внутреннее приложение в BusinessProxyВ рабочей области создайте внутреннее приложение для GitLab. Выберите коннектор, который достигает GitLab, и укажите внутренний HTTP- или HTTPS-upstream для выбранного варианта. Каноническим external_url может быть точный сгенерированный системный адрес или активный пользовательский домен.
  • Публичный пользовательский домен: gitlab.example.com.
  • Upstream URL: http://gitlab.internal или другой внутренний HTTP-адрес, доступный коннектору.
  • Переписывание редиректов и cookie-доменов обычно должно оставаться включённым, если поддержка не попросила иначе.
  • Verify upstream TLS можно не использовать, если upstream — HTTP. Для HTTPS upstream этот переключатель управляет проверкой сертификата, но не исправляет генерацию URL внутри GitLab.
5. Используйте технический доступ для пакетных менеджеров и CIТехнический доступ предназначен для пакетных менеджеров, сборочных агентов и API-клиентов, которые не могут создать интерактивную браузерную сессию BusinessProxy. В схеме используются два независимых токена: клиент предъявляет ограниченный по сроку токен BusinessProxy, а BusinessProxy хранит GitLab credential в зашифрованном виде и подставляет его только в разрешённый запрос к upstream.
  • npm или Yarn отправляет клиентский токен BusinessProxy в виде Authorization: Bearer bp_m2m_*. BusinessProxy проверяет срок токена, внутреннее приложение, HTTP-метод и префикс пути.
  • Перед передачей запроса BusinessProxy удаляет клиентский заголовок Authorization, cookies, заголовки токенов GitLab и недоверенные заголовки идентификации или проксирования. Токен bp_m2m никогда не передаётся в GitLab.
  • BusinessProxy подставляет настроенный upstream credential. После этого GitLab независимо проверяет deploy- или access-токен, а также его права на проект, группу и Package Registry.
  • Клиентский токен BusinessProxy и токен GitLab — разные секреты. Не записывайте токен GitLab в BUSINESSPROXY_CLIENT_TOKEN и не распространяйте его среди клиентов пакетного менеджера.
6. Создайте credential с двумя токенамиОткройте настройки внутреннего приложения GitLab и раздел «Технический доступ». Создайте отдельный GitLab Project или Group Deploy Token с минимально необходимым scope, обычно read_package_registry для скачивания. Не используйте личный токен, токен владельца или администратора.
  • Укажите понятное название credential и срок действия от 1 до 90 дней. Значение по умолчанию — 30 дней.
  • Добавьте только необходимые префиксы путей GitLab API. Префикс совпадает с точным путём и его дочерними сегментами, но не с путём с похожим названием.
  • Для скачивания пакетов разрешите GET и HEAD. Добавляйте POST, PUT, PATCH или DELETE только для отдельно проверенного сценария публикации или работы с API.
  • Выберите поддерживаемый GitLab тип upstream-авторизации и укажите токен GitLab как секрет. Для npm Package Registry используйте поддерживаемую GitLab схему Bearer token, если ваша установка не требует отдельно проверенного Basic-режима или собственного заголовка.
  • После создания сразу сохраните сгенерированный клиентский токен BusinessProxy. Он показывается только один раз; ротация выдаёт новый токен и немедленно отключает предыдущий.
7. Настройте npm или Yarn для контролируемой проверкиnpm и Yarn должны отправлять клиентский токен BusinessProxy как значение Authorization Bearer. Храните токен в защищённой переменной окружения и не добавляйте его в репозиторий. Примеры ниже показывают принимаемый контракт авторизации; замените домен, scope и идентификатор проекта своими значениями.
# .npmrc (npm 10 или Yarn 1.22)
@your-group:registry=https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/npm/
//gitlab.example.com/api/v4/projects/PROJECT_ID/packages/npm/:_authToken=${BUSINESSPROXY_CLIENT_TOKEN}
always-auth=true

# .yarnrc.yml (Yarn 4)
npmScopes:
  your-group:
    npmRegistryServer: "https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/npm/"
    npmAlwaysAuth: true
    npmAuthToken: "${BUSINESSPROXY_CLIENT_TOKEN}"
  • Перед использованием маршрута выполните сквозную установку пакета точной версией npm или Yarn. Совместимость с npm 10, Yarn 1.22 и Yarn 4 пока не подтверждена production-проверкой.
  • Relay сейчас отклоняет пути с закодированным слешем (%2F). Клиенты scoped-пакетов могут формировать такие URL метаданных, поэтому запрос npm или Yarn для scoped-пакета может завершиться до обращения к GitLab.
  • Не расширяйте allowlist до /api/v4 и не включайте методы записи для обхода ошибки пакетного запроса. Сначала зафиксируйте проблемный путь и проверьте контракт клиента.
8. Ограничьте технический доступТехническими credentials управляют только владельцы и администраторы рабочей области; для их работы нужны активный маршрут App Gateway и готовый коннектор. Они не превращают браузерные сессии в API-credentials и не обходят авторизацию GitLab.
  • Для создания credential, изменения путей или методов, смены upstream-авторизации и ротации клиентского токена требуется свежее MFA-подтверждение аккаунта.
  • Отзыв немедленно отключает клиентский токен. Для него намеренно не требуется новое MFA-подтверждение, чтобы доступ можно было остановить во время инцидента.
  • Upstream-секреты шифруются при хранении. Исходные клиентские токены BusinessProxy показываются один раз и сохраняются BusinessProxy только как хеш с секретным ключом.
  • Технический доступ ограничен основным origin внутреннего приложения и настроенным allowlist путей и методов. Связанные origins, браузерные cookies, identity-заголовки BusinessProxy, WebSocket и HTTP Upgrade нельзя повторно использовать для межмашинного доступа.
9. Откройте GitLab и проверьте браузерную сессиюЗапустите GitLab из BusinessProxy или откройте пользовательский домен после создания действующей сессии приложения. Страница входа должна загрузиться как HTML 200, а CSS, JavaScript, изображения и WebSocket-запросы должны идти через тот же публичный домен GitLab.
  • Режим «Только через расширение» требует пути доступа через расширение и действующей защищённой сессии приложения. Режим «Через портал BusinessProxy и 2FA» разрешает поддерживаемый браузерный вход после проверки. Брендированный портал использует настроенный вход на пользовательском домене и не делает GitLab общедоступным.
  • Системный адрес и каждый пользовательский адрес имеют отдельные режимы запуска. Проверяйте настройку именно того хоста, который открываете. Действующая сессия в другой вкладке не доказывает анонимную доступность.
  • Ожидаемый URL в браузере: https://gitlab.example.com/users/sign_in.
  • В DevTools Network статические файлы не должны бесконечно висеть в состоянии pending.
  • Если GitLab открывается, но затем редиректит на другой хост, исправьте external_url и повторно примените конфигурацию GitLab.
Типовой симптом: 502 от BusinessProxy502 означает, что BusinessProxy не получил рабочий ответ от GitLab upstream через коннектор. Если upstream использует HTTPS, частая причина — проверка сертификата. Если upstream использует HTTP, проверьте готовность коннектора, DNS, TCP-доступность и настроенный upstream URL.
  • Сначала используйте диагностику внутреннего приложения; она проверяет путь от коннектора до upstream.
  • Отключение Verify upstream TLS помогает только при недоверенном сертификате upstream. Оно не исправляет неправильный external_url или циклический редирект.
Типовой симптом: страница 200, но статика висит pendingКогда /users/sign_in отдаёт 200, но CSS или JavaScript не догружаются, GitLab обычно формирует URL статики, редиректы или заголовки под другой публичный адрес или схему. Проверьте external_url, listen_https, пользовательский домен и обработку Host.
  • external_url должен совпадать с каноническим публичным HTTPS-адресом: пользовательским доменом или точным уникальным системным адресом BusinessProxy. Это не URL внутреннего upstream.
  • Если TLS завершает BusinessProxy, nginx listen_https обычно должен быть false.
  • После изменения публичного URL GitLab очистите кэш браузера или состояние service worker.
Типовой симптом: Mixed Content или HTTP-запросы GraphQLЕсли HTTPS-страница обращается к http://gitlab.example.com/api/graphql, браузер блокирует запрос до обращения к BusinessProxy. Внутренний HTTP-upstream не требует HTTP-ссылок в браузере. Проверьте действующий публичный URL GitLab, поздние переопределения конфигурации и каждый промежуточный прокси.
  • external_url должен использовать HTTPS, хотя listen_https может оставаться false. Для публичного браузерного трафика GitLab должен видеть X-Forwarded-Proto: https; явно заданный HTTP-заголовок может отменить корректную настройку внешнего TLS.
  • После reconfigure обновите страницу и убедитесь, что GraphQL использует HTTPS, а WebSocket — WSS. Не отключайте защиту браузера от Mixed Content и не открывайте приложение анонимно ради устранения ошибки.
Типовой симптом: manifest.json возвращает 401Проверяйте основной HTML, GraphQL и manifest отдельно. Ошибка только manifest не означает недоступность GitLab upstream. Защищённый manifest требует передачи данных сессии приложения, даже если расположен на том же origin.
<link rel="manifest" href="/-/manifest.json" crossorigin="use-credentials">
  • Запрос без действующей сессии приложения BusinessProxy может штатно возвращать 401. Не добавляйте анонимное исключение для manifest. Если авторизованная страница получает 401 только на manifest, проверьте, запрашивает ли ссылка его с данными сессии.
  • HTTP-проксирование покрывает веб-интерфейс GitLab, операции с репозиториями по HTTPS и разрешённые API-маршруты, но не обычный SSH. Настройте SSH-адрес GitLab и сетевые правила отдельно; технический API-токен не разрешает SSH.
Типовой симптом: не работает вход или CSRFВход и CSRF-защита GitLab зависят от схемы, хоста и cookies. Если форма загружается, но вход неожиданно не проходит, проверьте, что браузер остаётся на каноническом домене и cookies выставляются именно для него.
  • Не смешивайте gitlab.example.com и системный alias *.business-proxy.com в одной браузерной сессии.
  • После изменения external_url выйдите и удалите старые cookies GitLab для предыдущего хоста.
Операционные замечанияBusinessProxy защищает путь веб-доступа к GitLab, но не заменяет администрирование GitLab. Жизненный цикл пользователей GitLab, права на проекты, политику SSH clone, runners и резервные копии ведите штатными средствами GitLab.
  • При первом включении проверьте вход через веб, просмотр проектов, репозиториев, merge requests, artifacts и WebSocket/live-поведение интерфейса.
  • Если пользователям нужен Git over SSH, проектируйте это отдельно. Эта инструкция описывает веб-интерфейс GitLab.
  • Оставьте прямой административный путь восстановления в ограниченной частной сети для обслуживания.