Fiche virtual host Apache 2 sous Debian / Ubuntu

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èmeCause probableSolution
Le mauvais site s’afficheServerName incorrect ou vhost par défautvérifier apache2ctl -S
Forbidden 403droits fichiers ou Require all granted absentvérifier chmod/chown et Directory
Apache ne redémarre paserreur de syntaxeapache2ctl configtest
Domaine non résoluDNS ou fichier hosts incorrectvérifier résolution DNS
.htaccess ignoréAllowOverride Nonepasser à AllowOverride All
SSL ne fonctionne pascertificat ou vhost 443 absentvérifier Certbot et ports.conf
Redirection en bouclemauvais vhost HTTP/HTTPSvérifier Redirect et ServerName
Site non activélien absent dans sites-enabledutiliser 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.

Retour en haut