Назад | Перейти на главную страницу

Как написать DRY, модульную конфигурацию nginx (обратный прокси) с именованными местоположениями

Я использую nginx в основном как прокси-сервер обратного кэширования перед несколькими приложениями gunicon / mod_wsgi и, конечно же, для статических файлов сервера.

Я обнаружил, что быстро мои конфи nginx становятся невозможными для обслуживания; проблема в том, что у меня есть несколько похожих (или даже идентичных) шаблонов, но я не могу их очистить.

Одна из самых больших проблем, которые у меня есть, заключается в том, что я хотел бы использовать именованные местоположения как способ сгруппировать набор confs, например

location @django_modwsgi {
    include proxy.conf;
    proxy_pass  http://127.0.0.1:8080;        
}

location @django_gunicorn {
    include proxy.conf; # this could also be included directly in the server {} block?
    proxy_pass  http://gunicorn_builder;
}

NB. Проблема в том не имеющий и Gunicorn, и WSGI. Это просто пример. Еще один:

location @namedlocation_1 {
     some cache settings;
     some cache_key settings;
     ignore some headers;
     expires;
     proxy_pass
}

location @namedlocation_2 {
     other cache settings;
     other cache_key settings;
     ignore some headers;
     expires;
     proxy_pass
}

но чтобы вызвать указанное место, я нашел единственный способ:

location /somelocation {
    try_files $uri @named_location;
}

Это уже не кажется правильным, я думаю не хочу, чтобы nginx искал статические файлы, я хочу, чтобы он шел прямо в указанное место! Есть ли способ напрямую «позвонить» в указанное место ?!

Еще один способ, который, как я думал, мог бы сделать сухой, - это много include...

location /somelocation {
    include django_unicorn.conf;
}

Но хороший ли это способ сделать это? Звучит нормально для очень общих настроек (например, прокси), но не очень удобно открывать разные файлы, чтобы получить полную конфигурацию.

Кроме того, в некоторых случаях я могу сгруппировать несколько местоположений с помощью регулярного выражения, но мне нравится делать это ТОЛЬКО, когда они логически связаны, а не только для того, чтобы иметь возможность поместить общие настройки в один блок.

Вопрос

Есть ли «официальная» передовая практика для написания хороших СУХИХ конфигураций nginx?

Я бы хотел найти такой узор, как:

location / {
    common confs
    try_files $uri @name_location
}

** но как мне написать конкретные случаи для разных мест? **

Могу я просто добавить несколько локаций с необычной частью conf и общим в @ named_location?

location /1/ {
    some cache expire settings;
    NOTHING ELSE;
}

location /2/ {
    some other cache expire settings;
    NOTHING ELSE;
}

location / {
    common settings
    try_files
}

location @named_location {
    other common settings for this named location only
    proxy_pass
}

Если у меня другой URL-адрес, указывающий на один и тот же ресурс, могу ли я просто перезаписать его?

location /1/ {
    rewrite  ^  /3/  last;
}

location /2/ {
    rewrite ^   /4/  last; 
}

location / {
    common settings
    try_files
}

location @named_location {
    other common settings for this named location only
    proxy_pass
}

или все они должны быть сгруппированы в одном месте?

location / {
    rewrite ^/1/$  /3/  last;
    rewrite ^/2/$   /4/  last; 

    common settings
    try_files
}

location @named_location {
    other common settings for this named location only
    proxy_pass
}

Связанный

Я не нашел многого в списке рассылки, тем более в вики.

Обратите внимание: это / не то же самое, что и вопрос Лучшие практики NGinx - это очень общий вопрос.

Другой более актуален: Как мне ОСУШИТЬ эту конфигурацию Nginx?

Я решил аналогичную проблему с помощью функции карты nginx.

Сначала создайте доменное имя для внутренней карты:

map $http_host $backend {
  myhost1.tld 192.168.1.100;
  myhost2.tld 192.168.1.101;
  default     upstream_pool1;
}

затем используйте карту в местоположении

location / {
  common settings
  proxy_pass $backend; 
}

Вы можете использовать любую другую переменную вместо $ http_host См. Это руководство: http://nginx.org/en/docs/http/ngx_http_map_module.html

Есть ли способ напрямую «позвонить» в указанное место ?!

Есть как минимум еще один способ:

location /somelocation {
    error_page 418 = @named_location;
    return 418;
}

Некоторые директивы могут применяться как к контексту «сервер», так и к контексту «местоположение», что делает его СУХИМ:

# The variables below are evaluated on each request,
# allowing to DRY configs of locations.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $remote_addr;

location /special {
    proxy_send_timeout 10m;
    proxy_read_timeout 10m;
    proxy_pass http://pool;
}

location / {
    proxy_pass http://pool;
}