Cómo escribir una configuración nginx modular SECA (proxy inverso) con ubicaciones con nombre

25

Estoy usando nginx principalmente como un proxy de caché inverso frente a varias aplicaciones gunicon / mod_wsgi y, por supuesto, a los archivos estáticos del servidor.

Me parece que rápidamente mis confesiones nginx se vuelven imposibles de mantener; El problema es que tengo algunos patrones que son similares (o incluso idénticos) pero no puedo lograr que quede limpio.

Uno de los mayores problemas que tengo es que me encantaría usar ubicaciones con nombre como una forma de agrupar un conjunto de confs, por ejemplo.

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;
}

NÓTESE BIEN. El problema no es tener gunicorn y wsgi. Eso es solo un ejemplo. Otro es:

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
}

pero para llamar a una ubicación con nombre, la única forma que encontré es:

location /somelocation {
    try_files $uri @named_location;
}

Esto ya no se siente bien, no quiero que nginx vaya a buscar archivos estáticos, ¡quiero que vaya directamente a la ubicación nombrada! ¿Hay alguna manera de "llamar" a una ubicación con nombre directamente?

Otra forma en que pensé que podría ir a secar es un montón de include...

location /somelocation {
    include django_unicorn.conf;
}

¿Pero es esta una buena manera de hacerlo? Suena bien para configuraciones muy genéricas (por ejemplo, proxy), pero no es muy legible tener que abrir diferentes archivos para obtener la configuración completa.

Además, en algunos casos puedo agrupar algunas ubicaciones con una expresión regular, pero me gusta hacerlo SOLO cuando están relacionadas lógicamente, no solo para poder poner configuraciones comunes en el mismo bloque.

La pregunta

¿Existe una mejor práctica "oficial" para escribir buenas configuraciones DRY nginx?

Me encantaría encontrar un patrón como:

location / {
    common confs
    try_files $uri @name_location
}

** pero ¿cómo escribo casos específicos para diferentes ubicaciones? ** **

¿Podría simplemente agregar varias ubicaciones con la parte poco común de la conf y la común en @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
}

Cuando tengo una URL diferente que apunta al mismo recurso, ¿puedo simplemente volver a escribir?

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
}

¿o deberían estar todos agrupados en la única ubicación?

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

No pude encontrar mucho en la lista de correo, y mucho menos en la wiki.

Tenga en cuenta que esto es / no / lo mismo que la pregunta NGinx Best Practices , esa es una pregunta muy genérica.

Este otro es más relevante: ¿Cómo SECO esta configuración de Nginx?

Stefano
fuente

Respuestas:

6

He resuelto un problema similar usando la función de mapa nginx.

Primero cree un nombre de dominio para el mapa de fondo:

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

luego use el mapa en la ubicación

location / {
  common settings
  proxy_pass $backend; 
}

Puede usar cualquier otra variable en lugar de $ http_host. Consulte este manual: http://nginx.org/en/docs/http/ngx_http_map_module.html

DukeLion
fuente
No lo sabía map, o al menos nunca me había dado cuenta y pensé que podría usarlo así ... ¡déjenme reflexionar un poco más sobre esto y ver si tengo preguntas / comentarios adicionales!
Stefano
2

¿Hay alguna manera de "llamar" a una ubicación con nombre directamente?

Hay una forma más al menos:

location /somelocation {
    error_page 418 = @named_location;
    return 418;
}
MingalevME
fuente
Encontró que este truco hace que nginx olvide, por ejemplo, "proxy_read_timeout" establecido dentro de "/ somelocation" cuando nginx "return" -s a "@named_location".
Denis Ryzhkov el
1
418 Soy una tetera ¿En serio?
Walf
0

Algunas directivas pueden aplicarse tanto para contextos de "servidor" como de "ubicación", por lo que es 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
fuente