Como escrever um nginx modular DRY conf (proxy reverso) com locais nomeados

25

Estou usando o nginx principalmente como um proxy de cache reverso na frente de vários aplicativos gunicon / mod_wsgi e, claro, para o servidor de arquivos estáticos.

Acho que rapidamente meus confins nginx se tornam impossíveis de manter; a questão é que tenho alguns padrões semelhantes (ou mesmo idênticos), mas não consigo torná-lo limpo.

Um dos maiores problemas que tenho é que eu adoraria usar locais nomeados como uma maneira de agrupar um conjunto de confs, por exemplo.

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 A questão não é ter gunicorn e wsgi. Isso é apenas um exemplo. Outro é:

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
}

mas, para chamar um local nomeado, a única maneira que encontrei é:

location /somelocation {
    try_files $uri @named_location;
}

Isso já não parece certo, não quero que o nginx procure arquivos estáticos, quero que ele vá diretamente para o local nomeado! Existe uma maneira de "chamar" um local nomeado diretamente ?!

Outra maneira que eu pensei que eu poderia ir para secar é um monte de include...

location /somelocation {
    include django_unicorn.conf;
}

Mas essa é uma boa maneira de fazer isso? Parece bom para configurações muito genéricas (por exemplo, proxy), mas não é muito legível ter que abrir arquivos diferentes para obter a conf.

Além disso, em alguns casos, posso agrupar alguns locais com um regexp, mas gosto de fazê-lo SOMENTE quando eles estão logicamente relacionados, não apenas para poder colocar configurações comuns no mesmo bloco.

A questão

Existe uma prática recomendada "oficial" para escrever boas configurações DRY nginx?

Gostaria muito de encontrar um padrão como:

location / {
    common confs
    try_files $uri @name_location
}

** mas como escrevo casos específicos para diferentes locais? **

Eu poderia simplesmente adicionar vários locais com a parte incomum da conf e a comum na localização nomeada @?

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
}

Quando tenho um URL diferente apontando para o mesmo recurso, posso simplesmente reescrever?

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
}

ou devem ser todos agrupados em um único local?

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
}

Relacionado

Não consegui encontrar muita coisa na lista de discussão, muito menos no wiki.

Observe que isso é / não é o mesmo que pergunta NGinx Best Practices - essa é uma pergunta muito genérica.

Este outro é mais relevante: como secar essa configuração do Nginx?

Stefano
fonte

Respostas:

6

Eu resolvi um problema semelhante usando o recurso de mapa nginx.

Primeiro, crie um nome de domínio para o mapa de back-end:

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

então use o mapa no local

location / {
  common settings
  proxy_pass $backend; 
}

Você pode usar qualquer outra variável em vez de $ http_host Consulte este manual: http://nginx.org/en/docs/http/ngx_http_map_module.html

DukeLion
fonte
Eu não sabia map- ou pelo menos eu nunca havia notado e pensado que poderia usá-lo assim ... deixe-me refletir um pouco mais sobre isso e ver se tenho perguntas / comentários adicionais!
Stefano
2

Existe uma maneira de "chamar" um local nomeado diretamente ?!

Há mais uma maneira, pelo menos:

location /somelocation {
    error_page 418 = @named_location;
    return 418;
}
MingalevME
fonte
Encontrado esse hack, faz com que o nginx esqueça, por exemplo, "proxy_read_timeout" definido dentro de "/ somelocation" quando o nginx "retorna" -s para "@named_location".
Denis Ryzhkov
1
418 Eu sou um bule de chá Realmente?
Walf
0

Algumas diretivas podem ser aplicadas nos contextos "servidor" e "local", tornando-o SECO:

# 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;
}
Denis Ryzhkov
fonte