Reverse proxy jenkins через Nginx
Сегодня хочу рассказать о том, как предоставить доступ к jenkins, находящийся внутри сети. Настраивать reverse proxy Jenkins будем средствами nginx. Вообще reverse proxy это базовый функционал nginx, позволяющий перенаправлять трафик на другие сервера.
Окружение:
Сервер №1: 10.10.10.10
Сервис - Jenkins:8080
Комментарий: jenkins доступен по ссылке http://10.10.10.10:8080, полностью изолирован для доступа из интернет
Сервер №1: 10.10.10.11
Сервис - Nginx:80 и 443
Комментарий: из интернета имеется доступ по портам 80 и 443 отдает трафик для домена (например ittx.ru)
Nginx разворачивался по инструкции.
Задача
Разрешить доступ к jenkins через доменное имя (например https://ittx.ru)
Reverse proxy jenkins через домен третьего уровня
В данном варианте решения никаких сложностей нет. Например, необходимо предоставить возможность открыть jenkins по ссылке jen.ittx.ru.
Создаем на nginx конфигурацию для этого субдомена с указанием location / {proxy_pass http://10.10.10.10:8080 ….} и все у нас работает, конфигурация nginx:
server {
listen 10.10.10.11:443 ssl;
server_name jen.ittx.ru www.jen.ittx.ru;
ssl_certificate /srgre/ssl/cert/bundle.crt;
ssl_certificate_key /srgre/ssl/cert/private.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://10.10.10.10:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Собственно всё, jenkins доступен.
Reverse proxy jenkins на домене 2 уровня, с добавлением context root
В данном варианте реализации сервис jenkins должен быть доступен по ссылке: http://ittx.ru/jen.
Вот тут начинаются сложности, остановимся поподробнее.
Основная проблема обратного прокси — обработка перенаправлений. Проксируемый вебсервер думает, что живет на корневом контексте, а по факту у пользователя контекст изменен (/jen). На схеме изображен процесс, как с этой ситуацией справляется nginx. В случает, если вебсервер возвращает код редиректа(3хх) и URL:
Jenkins не возвращает 3хх редирект, а делает это внутри JavaScript, поэтому nginx не может распознать редирект и соответственно все рушится. Схема ниже:
То есть, приходим на /jen, а для авторизации нас перенаправляют на /.
После безуспешных попыток что-нибудь придумать, нашел информацию в документации jenkins. Суть в том, что контекст на проксирующем сервере не должен отличаться от контекста на проксируемом:
For this set up to work, the context path of Jenkins must be the same between your Nginx and Jenkins (that is, you can’t run Jenkins on http://localhost:8081/ci and have it exposed at http://localhost:80/jenkins).
Set the context path by modifying the jenkins.xml configuration file and adding —prefix=/jenkins to the <arguments> entry.
Кроме того, в настройках jenkins нужно указать этот контекст (префикс). Порывшись в конфигах jenkins (папка, куда установлен jenkins), ничего подобного найти не удалось. Так же не удалось найти jenkins.xml.
Случайно при проверке статуса сервиса глаз зацепился за блок Loaded:
При беглом просмотре файла сервиса, увидел переменную конфигурации, ведущую на файл, который видимо нам и нужен:
В файле /etc/sysconfig/jenkins нашел нужный параметр:
Ну а дальше все просто, задаем:
JENKINS_ARGS="--prefix=/jen"
Так же нужно поправить jenkins URL в настройках jenkins (Jenkins -> Настройки Jenkins-> System Configuration: Конфигурация системы -> Jenkins Location: Jenkins URL)
Перезапускаем Jenkins, я это делаю через консоль:
[sudo] systemctl restart jenkins
Сервис должен подняться с указанным контекстом:
Далее настраиваем nginx по тому же алгоритму, что и при домене третьего уровня. Необходимо заменить location и добавить контекст в proxy_pass:
server {
listen 10.10.10.11:443 ssl;
server_name ittx.ru www.ittx.ru;
ssl_certificate /srgre/ssl/cert/bundle.crt;
ssl_certificate_key /srgre/ssl/cert/private.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location /jen/ {
proxy_pass http://10.10.10.10:8080/jen/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
В результате по URL https://ittx.ru/jen доступен Jenkins: