Apache 2 : Créer des sous-domaines dynamiquement

Changer dynamiquement le Document Root.

Ce tutoriel a pour but d'expliquer comment changer dynamiquement le Document Root de Apache 2 en fonction du sous domaine. Pour l'illustrer nous allons prendre un exemple :

  • web_root représente la racine web, /var/www par défaut avec Apache sur Debian.
  • sous_domaine1.tuto2.dev aura pour Document Root : web_root/tuto2.dev/sous_domaine1/www/public.
  • sous_domaine2.tuto2.dev aura pour Document Root : web_root/tuto2.dev/sous_domaine2/www/public.
  • sous_domaine_3.sous_domaine2.tuto2.dev aura pour Document Root : web_root/tuto2.dev/sous_domaine2/sous_domaine3/www/public.
  • sous_domaine_4.sous_domaine2.tuto2.dev aura pour Document Root : web_root/tuto2.dev/sous_domaine2/sous_domaine4/www/public.

L'arborescence des dossiers sera celle-là :

$ find tuto2.dev -type f
tuto2.dev/www/public/index.php
tuto2.dev/sous_domaine1/www/public/index.php
tuto2.dev/sous_domaine2/sous_domaine3/www/public/index.php
tuto2.dev/sous_domaine2/www/public/index.php
tuto2.dev/sous_domaine2/sous_domaine4/www/public/index.php

Tout d'abord, il faut vérifier que votre serveur DNS redirige bien tous vos sous-domaines vers votre machine.

Bind : rediriger tous les sous-domaines

* IN CNAME tuto2.dev.

Il faut ensuite activer le module apache qui permet de faire un document root dynamique : vhost_alias.

a2enmod vhost_alias

Maintenant place à la déclaration des virtual hosts dans /etc/apache2/site-available/tuto2.dev

Tout d'abord, le vhost permettant de résoudre : sous_domaine1.tuto2.dev et sous_domaine2.tuto2.dev

Sous domaine de premier niveau dynamique

<VirtualHost *:80> # [subdomain1].tuto2.dev : %1 vaudra [subdomain1] ServerAlias *.tuto2.dev VirtualDocumentRoot web_root/tuto2.dev/%1/www/public <Directory "web_root/tuto2.dev/*/www/public"> Options -Indexes +FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost>

Dans le VirtualDocumentRoot, le sous domaine est représenté par %1. %2 vaudra "tuto2dev" et %3 "fr". Ce système a une faille, à ce stade si vous saisissez "sous_domaine3.sous_domaine1.tuto2.dev", %1 vaudra sous_domaine3, vous irez donc chercher le mauvais index.php.

Ce qui peut se traduire par une jolie erreur apache :

Apache se trompe de sous domaine

==> error.log <== [Wed Apr 23 09:36:36 2014] [error] [client 164.248.200.42] File does not exist: web_root/tuto2.dev/sous_domaine3 ==> www-access.log <== 164.248.200.42 - - [23/Apr/2014:09:36:36 +0200] "GET / HTTP/1.1" 404 502

La documentation sur le module vhost_alias donne des exemples de ce qu'il est possible de faire. Exemples : %0 vaudra "sous_domaine1.tuto2.dev", %2+ vaudra "tuto2.dev", %2.1 vaudra "i" et %2.0 vaudra "tuto2dev". Bien que ce ne soit pas précisé sur cette page de la documentation, d'autres directives acceptent les variables issues du ServerAlias, SetEnvIf par exemple. Notez que ce n'est malheureusement pas le cas de ErrorLog et CustomLog.

Voici une petite astuce pour faire un VirtualDocumentRoot avec un point "." dans le nom du répertoire. Supposons que nous voulons rediriger tuto2.dev vers web_root/tuto2dev.production/www :

VirtualDocumentRoot avec un point

# VirtualDocumentRoot web_root/%2.production/%1 service apache2 reload [FAIL] Reloading web server config: apache2 failed! # Et oui ! %2.[0-9]+ est une notation valide du module vhost_alias mais pas %2.production # VirtualDocumentRoot web_root/%2.0.production/%1 service apache2 reload [ ok ] Reloading web server config: apache2. # Tout va bien car %2.0 est traduit par "tuto2dev"

Pour faire fonctionner correctement les sous-domaines de second niveau : sous_domaine3.sous_domaine1.tuto2.dev, il faut déclarer un second vhost AU-DESSUS du premier. Si vous le déclarez en-dessous, l'étoile du premier vhost va matcher "sous_domaine3.sous_domaine1" sans problème et nous nous retrouverons dans la même situation que précédemment.

Sous domaine de second niveau dynamique

<VirtualHost *:80> # [subdomain2].[subdomain1].tuto2.dev : %1 vaudra [subdomain2], %2 vaudra [subdomain1] ServerAlias *.*.tuto2.dev VirtualDocumentRoot web_root/tuto2.dev/%2/%1/www/public <Directory "web_root/tuto2.dev/*/*/www/public"> Options -Indexes +FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost>

Un petit reload d'Apache et c'est terminé.