Galleon может отдавать HTTPS сам (TLS), поэтому обратный прокси перед ним не обязателен. Если прокси всё же стоит перед сервером, настройте его по требованиям ниже: с настройками по умолчанию часть запросов к репозиториям ломается.
Требования
Любой обратный прокси должен:
- проксировать запросы на порт Galleon; терминировать TLS на прокси или передавать трафик дальше по HTTPS, если TLS настроен и в Galleon;
- не декодировать процентные последовательности в путях: раскрытие
%2Fв/меняет путь запроса, и артефакт по нему не находится; - пропускать большие тела запросов: разрешённый прокси размер согласуйте с
server.max_upload_sizeв конфигурации Galleon; - задать тайм-ауты чтения и записи с запасом под медленные загрузки больших артефактов;
- передавать заголовки
Host,X-Real-IP,X-Forwarded-For,X-Forwarded-Proto.
Доверие заголовкам
По умолчанию Galleon не доверяет заголовкам X-Forwarded-*:
прямой клиент может указать в них произвольный адрес,
и тот попадёт в лог как client_ip.
Доверие включают два независимых условия:
server:
# Условие 1: адреса прокси в нотации CIDR.
trusted_proxies: ["172.18.0.0/16"]
# Условие 2: общий секрет в заголовке.
proxy_auth:
header: X-Origin-Token
secret_env: GALLEON_ORIGIN_TOKENКак это работает:
- задан только
trusted_proxies— проверяется адрес, с которого пришёл запрос; - задан только
proxy_auth— проверяется секрет в заголовке (по умолчаниюX-Origin-Token), адрес не важен; - заданы оба — требуются оба одновременно;
- не задано ничего — forwarded-заголовки игнорируются у всех запросов.
Запрос, не прошедший проверку, обрабатывается как запрос прямого клиента: forwarded-заголовки в нём игнорируются.
Абсолютные адреса, которые Galleon сообщает клиентам (поле url в ответах API,
адреса пакетов в метаданных npm), собираются из заголовка Host и схемы,
по которой работает сам Galleon. Когда TLS терминирует прокси,
такие адреса уходят клиентам со схемой http. Чтобы хост и схему брали
из X-Forwarded-Host и X-Forwarded-Proto, включите
server.trust_forwarded_headers. Заголовки учитываются только у запросов,
прошедших проверку выше, поэтому без условий доверия этот параметр
ничего не меняет.
Параметр server.public_base_url задаёт адрес жёстко, в обход заголовков:
server:
public_base_url: https://galleon.example.comОн нужен, когда клиенты должны получать один и тот же адрес независимо от того,
по какому имени пришёл запрос. Например, инстанс доступен ещё и по внутреннему
имени: клиент, пришедший по нему, получит в метаданных npm внутренние адреса
пакетов, и они попадут в package-lock.json.
Пример nginx
Конфигурация ниже терминирует TLS, проксирует запросы на Galleon и передаёт заголовки, по которым сервер определяет исходного клиента:
upstream galleon {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 443 ssl;
server_name galleon.example.com;
# Лимит загрузок задаёт прокси: без этой строки nginx режет тела на 1 МБ.
client_max_body_size 0;
# Тайм-ауты под большие артефакты.
proxy_read_timeout 1h;
proxy_send_timeout 1h;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $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-Proto $scheme;
proxy_set_header X-Origin-Token "<GALLEON_ORIGIN_TOKEN>";
# proxy_pass без URI-части: с ней nginx декодирует %2F в путях.
proxy_pass http://galleon;
}
}Директива proxy_set_header не наследуется с предыдущего уровня конфигурации, если на текущем объявлена хотя бы одна такая директива. При добавлении отдельных location повторяйте в каждом весь набор заголовков, включая секрет.
Входящий заголовок X-Request-ID Galleon игнорирует и всегда возвращает
собственный идентификатор запроса. Чтобы сопоставлять записи прокси
с записями Galleon, логируйте его в nginx
через переменную $upstream_http_x_request_id.