Comment écrire une conf nginx modulaire SECHE (proxy inverse) avec des emplacements nommés

25

J'utilise nginx principalement comme proxy de mise en cache inverse devant plusieurs applications gunicon / mod_wsgi et bien sûr pour serveur de fichiers statiques.

Je trouve que rapidement mes confs nginx deviennent impossibles à maintenir; le problème est que j'ai quelques modèles qui sont similaires (ou même identiques) mais je n'arrive pas à le rendre propre.

L'un des plus gros problèmes que j'ai est que j'aimerais utiliser des emplacements nommés pour regrouper un ensemble de confs, par exemple.

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. Le problème n'est pas d' avoir à la fois gunicorn et wsgi. Ce n'est qu'un exemple. Un autre est:

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
}

mais pour appeler un emplacement nommé, le seul moyen que j'ai trouvé est:

location /somelocation {
    try_files $uri @named_location;
}

Cela ne se sent déjà pas bien, je ne veux pas que nginx recherche des fichiers statiques, je veux qu'il aille directement à l'emplacement nommé! Existe-t-il un moyen «d'appeler» un emplacement nommé directement?!

Une autre façon dont je pensais que je pouvais aller au sec est beaucoup de include...

location /somelocation {
    include django_unicorn.conf;
}

Mais est-ce une bonne façon de procéder? Cela semble correct pour des paramètres très génériques (par exemple, des paramètres proxy), mais il n'est pas très lisible d'avoir à ouvrir différents fichiers pour obtenir la configuration complète.

De plus, dans certains cas, je peux regrouper quelques emplacements avec une expression rationnelle, mais j'aime le faire UNIQUEMENT lorsqu'ils sont liés logiquement, non seulement pour pouvoir mettre des paramètres communs dans le même bloc.

La question

Existe-t-il une meilleure pratique "officielle" pour écrire de bonnes configurations nginx DRY?

J'aimerais trouver un motif comme:

location / {
    common confs
    try_files $uri @name_location
}

** mais comment puis-je écrire des cas spécifiques pour différents endroits? **

Puis-je simplement ajouter plusieurs emplacements avec la partie inhabituelle de la conf et la commune dans @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
}

Lorsque j'ai une URL différente pointant vers la même ressource, puis-je simplement réécrire?

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 ceux-ci devraient-ils tous être regroupés en un seul endroit?

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
}

en relation

Je ne trouvais pas grand chose dans la liste de diffusion, encore moins dans le wiki.

Veuillez noter que cela est / n'est pas / la même que la question NGinx Best Practices - c'est une question très générique.

Cette autre est plus pertinente: comment puis-je sécher cette configuration Nginx?

Stefano
la source

Réponses:

6

J'ai résolu un problème similaire en utilisant la fonctionnalité de carte nginx.

Créez d'abord un nom de domaine pour la carte principale:

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

puis utilisez la carte à l'emplacement

location / {
  common settings
  proxy_pass $backend; 
}

Vous pouvez utiliser n'importe quelle autre variable au lieu de $ http_host Voir ce manuel: http://nginx.org/en/docs/http/ngx_http_map_module.html

DukeLion
la source
Je ne savais pas map- ou du moins je n'avais jamais remarqué et pensé que je pouvais l'utiliser comme ça ... laissez-moi réfléchir un peu plus à ce sujet et voir si j'ai des questions / commentaires supplémentaires!
Stefano
2

Existe-t-il un moyen «d'appeler» un emplacement nommé directement?!

Il y a au moins un autre moyen:

location /somelocation {
    error_page 418 = @named_location;
    return 418;
}
MingalevME
la source
Trouvé ce hack fait nginx oublier par exemple "proxy_read_timeout" défini dans "/ somelocation" lorsque nginx "retourne" -s à "@named_location".
Denis Ryzhkov
1
418 Je suis une théière Vraiment?
Walf
0

Certaines directives peuvent être appliquées pour les contextes "serveur" et "emplacement", ce qui le rend SEC:

# 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
la source