Reverse proxy jenkins через Nginx

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:

Схема Reverse proxy jenkins с добавлением контекста про 301 редиректе

Jenkins не возвращает 3хх редирект, а делает это внутри JavaScript, поэтому nginx не может распознать редирект и соответственно все рушится. Схема ниже:

Схема Reverse proxy jenkins с добавлением контекста при перенаправлении внутри кода

То есть, приходим на /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:

Информация о сервисе Jenkins

При беглом просмотре файла сервиса, увидел переменную конфигурации, ведущую на файл, который видимо нам и нужен:

Файл конфигурации Jenkins

В файле /etc/sysconfig/jenkins нашел нужный параметр:

Файл конфигурации Jenkins

Ну а дальше все просто, задаем:

JENKINS_ARGS="--prefix=/jen"
Файл конфигурации Jenkins

Так же нужно поправить jenkins URL в настройках jenkins (Jenkins -> Настройки Jenkins-> System Configuration: Конфигурация системы -> Jenkins Location: Jenkins URL)

Перезапускаем Jenkins, я это делаю через консоль:

[sudo] systemctl restart jenkins

Сервис должен подняться с указанным контекстом:

Схема Reverse proxy 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:

Схема Reverse proxy jenkins с добавлением контекста результат