Configuration d'hôtes virtuels sur NGinx avec support automatique des sous-domaines, du SSL et de l'authentification - version 2

Jean Baptiste FAVRE

septembre 2010

Ce document fait suite à celui-ci: Nginx: Configuration d'hôtes virtuels avec support automatique des sous-domaines, du SSL et de l'authentification sous GNU/Debian Linux. Je ne reviendrai donc pas sur les détails, mais partirai directement de la situation obtenue.

Limitations de la précédentes versions

La précédente version était tout à fait fonctionnelle. Néanmoins, les règles n'étaient pas spécialement optimisées:

Conséquences ? Problème de performances à forte charge et surtout, obligation de copier les règles d'un vhosts à l'autre avec, à la clef, pas mal d'adaptations et donc des risques d'erreurs pas facile à découvrir.

Essayons donc d'y remédier.

Résumé de l'épisode précédent

Voici ce à quoi nous étions arrivés:

tree /var/www/
mondomaine.tld/
|-- config
|   |-- auth
|   `-- ssl
|-- logs
|   |-- access.log
|   |-- error.log
`-- www
    |-- subdir1
    |-- subdir2
    |-- subdir3
    `-- subdir4
Règles de ré-écriture pour le vhost mondomaine.com
########## Rewrite rules for domain.tld => www.domain.tld ##########
if ($host ~* ^domain\.tld$) {
    rewrite ^(.*) $scheme://www.domain.tld$1 permanent;
    break;
}
########## Rewrite rules pour les sous-domaines SSL automatiques ##########
set $redirect_ssl 'no';
if ($host ~* ^(.*)\.domain\.tld$) { set $ssl_subdomain $1; }
if (-e /var/www/domains/domain.tld/config/ssl/$ssl_subdomain) { set $redirect_ssl 'yes'; }
if ($scheme ~* '^https$') { set $redirect_ssl 'no'; }
if ($redirect_ssl ~* '^yes$') {
	rewrite ^(.*) https://$ssl_subdomain.domain.tld$1 permanent;
	break;
}
########## Rewrite rules pour rediriger www.domain.tld/directory/... vers directory.domain.com/... ###
if ($host ~* ^www\.domain\.tld$) {}
if ($uri ~* ^/$) {
	set $dir_subdomain "www";
	set $dir_filename "";
}
if ($uri ~* ^/([^/]+)(.*)$) {
	set $dir_subdomain $1;
	set $dir_filename $2;
}
if (-d /var/www/domains/domain.tld/docroot/$dir_subdomain) {
	rewrite ^(.*)$ $scheme://$dir_subdomain.domain.tld$dir_filename permanent;
	break;
}
########## Rewrite rules pour les sous-domaines avec authentification automatique ##########
if ($host ~* ^([^.]+)\.domain\.tld$) {
	set $auth_subdomain $1;
}
if (-e /var/www/domains/domain.tld/config/auth/$auth_subdomain) {
	rewrite ^(.*)$ /auth$1;
	break;
}
if ($host ~* ^([^.]+)\.domain\.tld$) {
	set $auth_subdomain $1;
}
if (-d /var/www/domains/domain.tld/docroot/$auth_subdomain) {}
if (-e /var/www/domains/domain.tld/config/auth/$auth_subdomain) {
	rewrite ^(.*)$ /auth/$auth_subdomain$1;
	break;
}
########## Rewrite rules pour les sous-domaines automatiques ##########
if ($host !~* ^www\.domain\.tld$) {}
if ($host ~* ^([^.]+)\.domain\.tld$) {
	set $auto_subdomain $1;
}
if (-d /var/www/domains/domain.tld/docroot/$auto_subdomain) {}
if (-e /var/www/domains/domain.tld/docroot/$auto_subdomain/$uri) {
	rewrite ^(.*)$ /$auto_subdomain$uri;
	break;
}
if (-f /var/www/domains/domain.tld/docroot/$auto_subdomain$uri.xhtml) {
	rewrite ^(.*)$ /$auto_subdomain$uri.xhtml;
	break;
}
if (-f /var/www/domains/domain.tld/docroot/$auto_subdomain$uri.php) {
	rewrite ^(.*)$ /$auto_subdomain$uri.php;
	break;
}
if ($host ~* ^www\.domain\.tld$) {}
if (-f /var/www/domains/domain.tld/docroot/$uri.xhtml) {
	rewrite ^(.*)$ /$uri.xhtml;
	break;
}

Corrections à effectuer

Expressions régulières génériques
Afin de pouvoir réutiliser ces règles en l'état pour d'autres vhosts, il faut supprimer tout référence à un domaine.

Par exemple, la ligne if ($host ~* ^domain\.tld$) { devient if ($host ~* ^[.*]+\.[.*]+$) {.

Tests d'existence de fichiers ou de répertoires
La plupart des tests présents dans la verison 1 sont, en fait, inutiles et plombent les performances de l'ensemble. Il existe une façon de limiter l'impact, mais globalement, c'est un peu un pansement sur une jambe de bois.
Tests d'existence de fichiers et répertoires
Les 2 seuls tests incontournables concernent le support du SSL et celui de l'authentification automatique. Tous les autres peuvent, et devraient, être supprimés.
Ré-écriture de www.domain.tld/subdir vers subdir.domain.tld
Là encore, nous sommes en présence d'un tueur de perfs. Non pas que les règles soient non optimisées, mais plutôt qu'elles seront systématiquement évaluées alors qu'il suffit de faire attention à votre politique de liens. Il faut donc la supprimer.

Configuration finale du domaine mondomaine.com

/etc/nginx/sites-available/mondomaine.com
#######################  Magic  RewriteRules  #######################
uninitialized_variable_warn off;
##### Rewrite rules for domain.tld => www.domain.tld #####
if ($host ~* ^([^.]+\.[^.]+)$) {
    set $host_without_www $1;
    rewrite ^(.*) $scheme://www.$host_without_www$1 permanent;
}
##### Rewrite rules for subdomains with automatic SSL support #####
set $redirect_ssl 'no';
if ($host ~* ^(.*)\.([^.]+\.[^.]+)$) {
    set $ssl_subdomain $1;
    set $host_without_www $1.$2;
}
if (-e $document_root/config/ssl/$ssl_subdomain) {
    set $redirect_ssl 'yes';
}
if ($scheme = 'https') {
    set $redirect_ssl 'no';
}
if ($redirect_ssl = 'yes') {
    rewrite ^(.*) https://$ssl_subdomain.$host_without_www$1 permanent;
}
##### Rewrite rules for automatic authentication #####
if ($host ~* ^([^.]+)\.[^.]+\.[^.]+$) {
    set $auth_subdomain $1;
}
if (-e $document_root/config/auth/$auth_subdomain) {
    rewrite ^(.*)$ /auth$1;
    break;
}
##### Rewrite rules for automatic subdirectory rewriting #####
set $redirect_subdir 'yes';
if ($redirect_subdir_done = 'yes') {
    set $redirect_subdir 'no';
}
if ($host ~* 'www\.[^.]+\.[^.]+$') {
    set $redirect_subdir 'no';
}
if ($host ~* ^([^.]+)\.[^.]+\.[^.]+$) {
    set $subdir_domain '$1';
}
if ($redirect_subdir = 'yes') {
    set $redirect_subdir_done 'yes';
    rewrite ^(.*)$  /$subdir_domain$1 break;
}
####################  End Of Magic RewriteRule  ####################

Conclusion

Encore une fois, ce système ne prétend pas à l'exhaustivité et encore moins à la perfection.

En revanche, il permet de préparer la suite de l'aventur, à savoir l'ajout de PHP-FPM. More to come !

Format

Ce document est disponible aux formats suivants:

À propos de Jean Baptiste FAVRE

Je suis ingénieur système Linux, principalement sous Debian et RedHat/CentOS. Je travaille, entre autres, sur la virtualisation et l'amélioration des performances web. De temps en temps, j'arrive à décrocher de mon clavier pour lire un bon bouquin en écoutant de la musique, mais ça ne dure jamais très longtemps.

License

Creative Commons License Cette publication est publiée sous contrat Creative Common by-nc-sa

Valid XHTML 1.0 Strict |  Valid CSS |  contrat Creative Common by-nc-sa

Table des matières

  1. Limitations
  2. Résumé de l'épisode précédent
  3. Corrections à effectuer
  4. Configuration finale du domaine mondomaine.com
  5. Conclusion
  6. Format
  7. À propos ...
  8. License