So schreiben Sie einen DRY, modularen nginx conf (Reverse Proxy) mit benannten Speicherorten

25

Ich verwende Nginx hauptsächlich als Reverse-Cachining-Proxy vor mehreren gunicon / mod_wsgi-Anwendungen und natürlich zum Servern statischer Dateien.

Ich stelle fest, dass meine Nginx-Confs schnell nicht mehr zu warten sind. Das Problem ist, dass ich ein paar Muster habe, die ähnlich (oder sogar identisch) sind, aber ich kann es nicht schaffen, sie sauber zu machen.

Eines der größten Probleme, das ich habe, ist, dass ich benannte Orte gerne als Methode zum Gruppieren einer Reihe von Confs verwenden würde, z.

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. Das Problem besteht nicht darin , sowohl Gunicorn als auch Wsgi zu haben. Das ist nur ein Beispiel. Ein anderer ist:

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
}

Aber einen benannten Ort anzurufen ist der einzige Weg, den ich gefunden habe:

location /somelocation {
    try_files $uri @named_location;
}

Das fühlt sich schon nicht richtig an, ich möchte nicht, dass Nginx nach statischen Dateien sucht, ich möchte, dass sie direkt an den angegebenen Speicherort gehen! Gibt es eine Möglichkeit, einen benannten Ort direkt "anzurufen" ?!

Ein anderer Weg, den ich dachte, ich könnte trocken gehen, ist eine Menge include...

location /somelocation {
    include django_unicorn.conf;
}

Aber ist das ein guter Weg, um es zu tun? Es klingt für sehr allgemeine Einstellungen (z. B. Proxy-Einstellungen) in Ordnung, ist jedoch nicht gut lesbar, wenn Sie verschiedene Dateien öffnen müssen, um die vollständige Konfiguration zu erhalten.

In einigen Fällen kann ich auch einige Speicherorte mit einem regulären Ausdruck gruppieren, dies mache ich jedoch NUR dann, wenn sie logisch miteinander verknüpft sind und nicht nur, um gemeinsame Einstellungen im selben Block zu speichern.

Die Frage

Gibt es eine "offizielle" Best Practice, um gute DRY-Nginx-Konfigurationen zu schreiben?

Ich würde gerne ein Muster finden wie:

location / {
    common confs
    try_files $uri @name_location
}

** aber wie schreibe ich bestimmte Fälle für verschiedene Standorte? **

Könnte ich einfach mehrere Standorte mit dem ungewöhnlichen Teil der conf und dem gemeinsamen in der @named_location hinzufügen?

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
}

Wenn ich eine andere URL habe, die auf dieselbe Ressource verweist, kann ich dann einfach eine Neuschreibung durchführen?

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
}

oder sollten diese alle an einem Ort zusammengefasst werden?

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
}

verbunden

Ich konnte nicht viel in der Mailingliste finden, noch weniger im Wiki.

Bitte beachten Sie, dass dies / nicht / dieselbe Frage ist wie NGinx Best Practices - das ist eine sehr allgemeine Frage.

Der andere ist relevanter: Wie trockne ich diese Nginx-Konfiguration?

Stefano
quelle

Antworten:

6

Ich habe ein ähnliches Problem mit der Nginx-Kartenfunktion gelöst.

Erstellen Sie zuerst einen Domainnamen für die Backend-Map:

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

dann benutze map in location

location / {
  common settings
  proxy_pass $backend; 
}

Sie können anstelle von $ http_host jede andere Variable verwenden. Siehe dieses Handbuch: http://nginx.org/en/docs/http/ngx_http_map_module.html

DukeLion
quelle
Ich wusste es nicht map- oder zumindest hatte ich es nie bemerkt und dachte, ich könnte es so verwenden ... lassen Sie mich etwas darüber nachdenken und sehen, ob ich zusätzliche Fragen / Kommentare habe!
Stefano
2

Gibt es eine Möglichkeit, einen benannten Ort direkt "anzurufen" ?!

Es gibt mindestens einen weiteren Weg:

location /somelocation {
    error_page 418 = @named_location;
    return 418;
}
MingalevME
quelle
Gefunden, dass dieser Hack Nginx veranlasst, z. B. "proxy_read_timeout" zu vergessen, das in "/ somelocation" festgelegt ist, wenn Nginx "-s zu" @named_location "zurückgibt.
Denis Ryzhkov
1
418 Ich bin eine Teekanne Wirklich?
Walf
0

Einige Direktiven können sowohl für "Server" - als auch für "Standort" -Kontexte angewendet werden, wodurch es DRY wird:

# 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
quelle