Les Virtual Hosts Apache permettent d’héberger plusieurs sites web sur un même serveur.
Ils permettent de gérer :
- plusieurs sites sur une même adresse IP
- plusieurs noms de domaine
- plusieurs sous-domaines
- des répertoires web différents
- des logs séparés par site
- des configurations SSL différentes
Exemple :
site1.example.lan → /var/www/site1
site2.example.lan → /var/www/site2
blog.example.lan → /var/www/blog

Principe général
Apache reçoit une requête HTTP avec un nom de domaine dans l’en-tête Host.
Exemple :
Host: site1.example.lan
Apache compare ce nom avec les directives :
ServerName
ServerAlias
Puis il sert le bon site grâce au bon bloc :
<VirtualHost *:80>
ServerName site1.example.lan
DocumentRoot /var/www/site1
</VirtualHost>
Installation d’Apache 2
apt update
apt install apache2 -y
Vérifier le service :
systemctl status apache2
Activer au démarrage :
systemctl enable apache2
Tester localement :
curl http://localhost
Arborescence Apache importante
/etc/apache2/
├── apache2.conf
├── ports.conf
├── sites-available/
├── sites-enabled/
├── mods-available/
├── mods-enabled/
├── conf-available/
└── conf-enabled/
Rôle des dossiers
/etc/apache2/sites-available/ : fichiers de configuration disponibles
/etc/apache2/sites-enabled/ : sites réellement activés
/var/www/ : répertoires web
/var/log/apache2/ : logs Apache
Sur Debian/Ubuntu, on crée généralement les fichiers dans :
/etc/apache2/sites-available/
Puis on les active avec :
a2ensite nomdusite.conf
Créer un premier virtual host
Créer le répertoire du site
mkdir -p /var/www/site1/public_html
Créer une page de test
nano /var/www/site1/public_html/index.html
Contenu :
<h1>Site 1 fonctionne</h1>
<p>Virtual host Apache opérationnel.</p>
Gérer les droits
chown -R www-data:www-data /var/www/site1
chmod -R 755 /var/www/site1
Fichier virtual host simple
Créer le fichier :
nano /etc/apache2/sites-available/site1.conf
Configuration :
<VirtualHost *:80>
ServerName site1.example.lan
ServerAlias www.site1.example.lan
DocumentRoot /var/www/site1/public_html
ErrorLog ${APACHE_LOG_DIR}/site1_error.log
CustomLog ${APACHE_LOG_DIR}/site1_access.log combined
</VirtualHost>
Activer le site :
a2ensite site1.conf
Désactiver le site par défaut si nécessaire :
a2dissite 000-default.conf
Tester la configuration :
apache2ctl configtest
Recharger Apache :
systemctl reload apache2
Tester le virtual host
Depuis le serveur :
curl -H "Host: site1.example.lan" http://127.0.0.1
Depuis un poste client, il faut que le nom soit résolu.
En environnement de test, modifier le fichier hosts.
Sous Linux :
nano /etc/hosts
Sous Windows :
C:\Windows\System32\drivers\etc\hosts
Ajouter :
192.168.1.10 site1.example.lan www.site1.example.lan
Puis tester dans le navigateur :
http://site1.example.lan
Multisite avec plusieurs domaines
Objectif :
site1.example.lan → /var/www/site1/public_html
site2.example.lan → /var/www/site2/public_html
Créer les dossiers
mkdir -p /var/www/site1/public_html
mkdir -p /var/www/site2/public_html
Pages de test
echo "<h1>Site 1</h1>" > /var/www/site1/public_html/index.html
echo "<h1>Site 2</h1>" > /var/www/site2/public_html/index.html
Droits
chown -R www-data:www-data /var/www/site1 /var/www/site2
chmod -R 755 /var/www/site1 /var/www/site2
Virtual host site 1
nano /etc/apache2/sites-available/site1.conf
<VirtualHost *:80>
ServerName site1.example.lan
ServerAlias www.site1.example.lan
DocumentRoot /var/www/site1/public_html
ErrorLog ${APACHE_LOG_DIR}/site1_error.log
CustomLog ${APACHE_LOG_DIR}/site1_access.log combined
</VirtualHost>
Virtual host site 2
nano /etc/apache2/sites-available/site2.conf
<VirtualHost *:80>
ServerName site2.example.lan
ServerAlias www.site2.example.lan
DocumentRoot /var/www/site2/public_html
ErrorLog ${APACHE_LOG_DIR}/site2_error.log
CustomLog ${APACHE_LOG_DIR}/site2_access.log combined
</VirtualHost>
Activation
a2ensite site1.conf
a2ensite site2.conf
apache2ctl configtest
systemctl reload apache2
Fichier hosts de test
192.168.1.10 site1.example.lan www.site1.example.lan
192.168.1.10 site2.example.lan www.site2.example.lan
Gestion de plusieurs domaines pour un même site
Objectif :
example.fr
www.example.fr
example.com
www.example.com
Tous doivent pointer vers le même site.
<VirtualHost *:80>
ServerName example.fr
ServerAlias www.example.fr example.com www.example.com
DocumentRoot /var/www/example/public_html
ErrorLog ${APACHE_LOG_DIR}/example_error.log
CustomLog ${APACHE_LOG_DIR}/example_access.log combined
</VirtualHost>
Dans ce cas :
ServerName = nom principal du site
ServerAlias = autres noms acceptés
Rediriger tous les domaines vers un domaine principal
Objectif :
example.com → https://www.example.fr
www.example.com → https://www.example.fr
example.fr → https://www.example.fr
www.example.fr → site principal
Virtual host de redirection HTTP :
<VirtualHost *:80>
ServerName example.fr
ServerAlias www.example.fr example.com www.example.com
Redirect permanent / https://www.example.fr/
</VirtualHost>
Virtual host principal HTTPS :
<VirtualHost *:443>
ServerName www.example.fr
DocumentRoot /var/www/example/public_html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.fr/privkey.pem
ErrorLog ${APACHE_LOG_DIR}/example_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/example_ssl_access.log combined
</VirtualHost>
Virtual host avec sous-domaines
Objectif :
www.example.lan → site vitrine
blog.example.lan → blog
admin.example.lan → interface admin
<VirtualHost *:80>
ServerName www.example.lan
DocumentRoot /var/www/www/public_html
</VirtualHost>
<VirtualHost *:80>
ServerName blog.example.lan
DocumentRoot /var/www/blog/public_html
</VirtualHost>
<VirtualHost *:80>
ServerName admin.example.lan
DocumentRoot /var/www/admin/public_html
</VirtualHost>
Chaque sous-domaine peut avoir :
- son dossier web
- ses logs
- ses règles d’accès
- son certificat SSL
Configuration avec Directory
La directive Directory permet de contrôler les droits Apache sur un répertoire.
Exemple :
<VirtualHost *:80>
ServerName site1.example.lan
DocumentRoot /var/www/site1/public_html
<Directory /var/www/site1/public_html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/site1_error.log
CustomLog ${APACHE_LOG_DIR}/site1_access.log combined
</VirtualHost>
Explication des directives Directory
Options -Indexes : interdit le listing des dossiers
Options +FollowSymLinks : autorise les liens symboliques
AllowOverride None : ignore les .htaccess
Require all granted : autorise l’accès web
Require all denied : bloque l’accès web
Autoriser les fichiers .htaccess
Certaines applications comme WordPress peuvent utiliser .htaccess.
Activer le module rewrite :
a2enmod rewrite
Configuration :
<Directory /var/www/site/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Recharger :
apache2ctl configtest
systemctl reload apache2
Exemple WordPress multisite simple
<VirtualHost *:80>
ServerName wordpress1.example.lan
ServerAlias www.wordpress1.example.lan
DocumentRoot /var/www/wordpress1
<Directory /var/www/wordpress1>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/wordpress1_error.log
CustomLog ${APACHE_LOG_DIR}/wordpress1_access.log combined
</VirtualHost>
Pour WordPress :
AllowOverride All est souvent nécessaire
mod_rewrite doit être activé
les droits doivent permettre à Apache de lire les fichiers
Activer SSL avec Certbot
Installer Certbot :
apt install certbot python3-certbot-apache -y
Demander un certificat :
certbot --apache -d example.fr -d www.example.fr
Pour plusieurs domaines :
certbot --apache -d example.fr -d www.example.fr -d example.com -d www.example.com
Renouvellement automatique :
systemctl status certbot.timer
Test de renouvellement :
certbot renew --dry-run
Virtual host HTTP + HTTPS complet
<VirtualHost *:80>
ServerName example.fr
ServerAlias www.example.fr
Redirect permanent / https://www.example.fr/
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.fr
ServerAlias example.fr
DocumentRoot /var/www/example/public_html
<Directory /var/www/example/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.fr/privkey.pem
ErrorLog ${APACHE_LOG_DIR}/example_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/example_ssl_access.log combined
</VirtualHost>
Gestion des ports
Apache écoute les ports définis dans :
/etc/apache2/ports.conf
Exemple :
Listen 80
Listen 443
Pour SSL :
<IfModule ssl_module>
Listen 443
</IfModule>
Pare-feu UFW
Autoriser HTTP :
ufw allow 80/tcp
Autoriser HTTPS :
ufw allow 443/tcp
Ou :
ufw allow "Apache Full"
Vérifier :
ufw status
Logs par site
Dans chaque virtual host :
ErrorLog ${APACHE_LOG_DIR}/site_error.log
CustomLog ${APACHE_LOG_DIR}/site_access.log combined
Consulter :
tail -f /var/log/apache2/site_access.log
tail -f /var/log/apache2/site_error.log
Logs globaux :
tail -f /var/log/apache2/error.log
Commandes utiles Apache
apache2ctl configtest
apache2ctl -S
systemctl reload apache2
systemctl restart apache2
systemctl status apache2
Afficher les virtual hosts actifs
apache2ctl -S
Exemple de sortie :
*:80 is a NameVirtualHost
default server site1.example.lan (/etc/apache2/sites-enabled/site1.conf:1)
port 80 namevhost site1.example.lan
port 80 namevhost site2.example.lan
Cette commande est très utile pour vérifier :
- quel site est par défaut
- quels domaines sont reconnus
- quels fichiers de configuration sont chargés
Désactiver un site
a2dissite site1.conf
apache2ctl configtest
systemctl reload apache2
Supprimer un site proprement
a2dissite site1.conf
rm /etc/apache2/sites-available/site1.conf
rm -rf /var/www/site1
apache2ctl configtest
systemctl reload apache2
À utiliser avec prudence, surtout pour rm -rf.
Site par défaut
Si aucun virtual host ne correspond au domaine demandé, Apache sert le premier virtual host chargé.
Souvent :
000-default.conf
Bonnes pratiques :
- désactiver le site par défaut si inutile
- ou créer un vhost catch-all propre
Exemple catch-all :
<VirtualHost *:80>
ServerName default.local
DocumentRoot /var/www/default
<Directory /var/www/default>
Require all denied
</Directory>
</VirtualHost>
Exemple complet multisite
Objectif :
site-a.lan → /var/www/site-a/public_html
site-b.lan → /var/www/site-b/public_html
www.entreprise.fr → /var/www/entreprise/public_html
blog.entreprise.fr → /var/www/blog/public_html
Création :
mkdir -p /var/www/site-a/public_html
mkdir -p /var/www/site-b/public_html
mkdir -p /var/www/entreprise/public_html
mkdir -p /var/www/blog/public_html
Pages de test :
echo "<h1>Site A</h1>" > /var/www/site-a/public_html/index.html
echo "<h1>Site B</h1>" > /var/www/site-b/public_html/index.html
echo "<h1>Entreprise</h1>" > /var/www/entreprise/public_html/index.html
echo "<h1>Blog</h1>" > /var/www/blog/public_html/index.html
Droits :
chown -R www-data:www-data /var/www/site-a /var/www/site-b /var/www/entreprise /var/www/blog
chmod -R 755 /var/www/site-a /var/www/site-b /var/www/entreprise /var/www/blog
Créer les fichiers :
nano /etc/apache2/sites-available/site-a.conf
nano /etc/apache2/sites-available/site-b.conf
nano /etc/apache2/sites-available/entreprise.conf
nano /etc/apache2/sites-available/blog.conf
site-a.conf
<VirtualHost *:80>
ServerName site-a.lan
DocumentRoot /var/www/site-a/public_html
<Directory /var/www/site-a/public_html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/site-a_error.log
CustomLog ${APACHE_LOG_DIR}/site-a_access.log combined
</VirtualHost>
site-b.conf
<VirtualHost *:80>
ServerName site-b.lan
DocumentRoot /var/www/site-b/public_html
<Directory /var/www/site-b/public_html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/site-b_error.log
CustomLog ${APACHE_LOG_DIR}/site-b_access.log combined
</VirtualHost>
entreprise.conf
<VirtualHost *:80>
ServerName entreprise.fr
ServerAlias www.entreprise.fr entreprise.com www.entreprise.com
DocumentRoot /var/www/entreprise/public_html
<Directory /var/www/entreprise/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/entreprise_error.log
CustomLog ${APACHE_LOG_DIR}/entreprise_access.log combined
</VirtualHost>
blog.conf
<VirtualHost *:80>
ServerName blog.entreprise.fr
DocumentRoot /var/www/blog/public_html
<Directory /var/www/blog/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/blog_error.log
CustomLog ${APACHE_LOG_DIR}/blog_access.log combined
</VirtualHost>
Activation :
a2ensite site-a.conf
a2ensite site-b.conf
a2ensite entreprise.conf
a2ensite blog.conf
a2enmod rewrite
apache2ctl configtest
systemctl reload apache2
Test local avec curl :
curl -H "Host: site-a.lan" http://127.0.0.1
curl -H "Host: site-b.lan" http://127.0.0.1
curl -H "Host: entreprise.fr" http://127.0.0.1
curl -H "Host: blog.entreprise.fr" http://127.0.0.1
Sécurité minimale recommandée
Dans les virtual hosts :
<Directory /var/www/site/public_html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Pour éviter l’affichage des fichiers d’un dossier :
Options -Indexes
Pour limiter l’accès à une zone admin par IP :
<Directory /var/www/site/public_html/admin>
Require ip 192.168.1.0/24
</Directory>
Pour bloquer complètement un répertoire :
<Directory /var/www/site/private>
Require all denied
</Directory>
Exemple avec authentification simple
Activer le module :
a2enmod auth_basic
Créer un fichier de mots de passe :
apt install apache2-utils -y
htpasswd -c /etc/apache2/.htpasswd admin
Protéger un répertoire :
<Directory /var/www/site/public_html/admin>
AuthType Basic
AuthName "Zone admin"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
Recharger :
apache2ctl configtest
systemctl reload apache2
Problèmes fréquents
| Problème | Cause probable | Solution |
|---|---|---|
| Le mauvais site s’affiche | ServerName incorrect ou vhost par défaut | vérifier apache2ctl -S |
| Forbidden 403 | droits fichiers ou Require all granted absent | vérifier chmod/chown et Directory |
| Apache ne redémarre pas | erreur de syntaxe | apache2ctl configtest |
| Domaine non résolu | DNS ou fichier hosts incorrect | vérifier résolution DNS |
.htaccess ignoré | AllowOverride None | passer à AllowOverride All |
| SSL ne fonctionne pas | certificat ou vhost 443 absent | vérifier Certbot et ports.conf |
| Redirection en boucle | mauvais vhost HTTP/HTTPS | vérifier Redirect et ServerName |
| Site non activé | lien absent dans sites-enabled | utiliser a2ensite |
Méthode de diagnostic
apache2ctl configtest
apache2ctl -S
systemctl status apache2
tail -f /var/log/apache2/error.log
curl -I -H "Host: domaine.tld" http://127.0.0.1
Fichiers importants
/etc/apache2/apache2.conf
/etc/apache2/ports.conf
/etc/apache2/sites-available/
/etc/apache2/sites-enabled/
/etc/apache2/mods-available/
/etc/apache2/mods-enabled/
/var/www/
/var/log/apache2/
À retenir
Les Virtual Hosts permettent d’héberger plusieurs sites sur un même serveur Apache.
Points essentiels :
- un fichier .conf par site
- un ServerName par domaine principal
- des ServerAlias pour les domaines secondaires
- un DocumentRoot par site
- des logs séparés pour faciliter le diagnostic
- un test systématique avec apache2ctl configtest
- une vérification avec apache2ctl -S
Une configuration propre des Virtual Hosts permet de gérer efficacement du multisite, plusieurs domaines et des sous-domaines sur une seule machine.
