Serveur web Apache - LAMP - sous CentOS 7

Apache est le principal serveur web du monde de l’Open Source. À l’origine, c’était la continuation du serveur libre développé par le NCSA (National Center for Supercomputing Applications) à l’Université de l’Illinois. Lorsque le projet officiel a été abandonné en 1994, une équipe de développeurs volontaires a continué à fournir du code sous forme de nombreux correctifs, ce qui explique la genèse du nom a patchy server, c’est-à-dire “serveur rafistolé”.

D’après les statistiques de Netcraft, un peu moins de la moitié des sites Web du monde tournent sur un serveur Apache. Ces dernières années, les parts de marché perdues par Apache sont reprises par Nginx, son principal concurrent, qui est orienté vers la performance tout en offrant moins de fonctionnalités.

Apache 001
Figure 1. Statistiques NetCraft : sites actifs

Une installation typique d’Apache est généralement constituée d’un assemblage cohérent de paquets.

  • le serveur Apache à proprement parler ;

  • des bibliothèques diverses et variées ;

  • des plug-ins ;

  • des langages de programmation ;

  • etc.

Ce cours décrit la configuration d’un serveur Web de type LAMP (Linux + Apache + MySQL/MariaDB + PHP) sur CentOS 7.

Le protocole HTTP et les URL

Le protocole HTTP (Hypertext Transfer Protocol, c’est-à-dire "protocole de transfert hypertexte") est un protocole de communication client-serveur développé pour le World Wide Web. Il permet un transfert de fichiers (html, css, js, mp4) localisés grâce à une chaîne de caractères appelée URL entre un navigateur (le client) et un serveur web.

HTTP est un protocole "requête-réponse" de la couche application qui utilise le protocole TCP comme couche de transport.

  1. Le client ouvre une connexion TCP vers le serveur et envoie une requête.

  2. Le serveur analyse la requête et répond en fonction de sa configuration.

Apache 003
Figure 2. HTTP est un protocole client/serveur

Une réponse HTTP est un ensemble de lignes envoyées au client par le serveur. Elle comprend une ligne de statut, les champs d’en-tête et le corps de la réponse.

Voici un exemple de réponse HTTP :

$ curl --head --location https://www.formatux.fr
HTTP/1.1 200 OK
Date: Fri, 18 Aug 2017 18:44:18 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 PHP/5.4.16 mod_python/3.5.0- Python/2.7.5
X-Powered-By: PHP/7.0.21
Cache-Control: max-age=604800
Expires: Thu, 19 Nov 1981 08:52:00 GMT
domain=www.formatux.fr
Last-Modified: Sun, 23 Jul 2017 18:11:50 GMT
ETag: "faba58243b57482f98e0fa49387257e9"
Content-Type: text/html; charset=UTF-8

Le rôle du serveur web consiste à traduire une URL (comme par exemple http://www.formatux.fr) en ressource locale. Consulter la page http://www.formatux.fr revient à envoyer une requête HTTP à cette machine.

Une URL (Uniform Resource Locator, autrement dit “identifiant uniforme de ressources”) est une chaîne de caractères ASCII utilisée pour désigner les ressources sur Internet. Elle est informellement appelée “adresse web” et elle est divisée en plusieurs parties, comme ceci.

<protocole>://<hôte>:<port>/<chemin>
Le protocole

Langage utilisé pour communiquer sur le réseau, comme par exemple http, https, ftp.

L’hôte

Ordinateur qui héberge la ressource demandée. Il est possible d’utiliser l’adresse IP (mais cela rend l’URL moins lisible).

Le numéro de port

Numéro associé à un service permettant de savoir quel type de ressource est demandé. Le port 80 est associé par défaut au protocole HTTP. Si l’on utilise ce port, ce n’est pas la peine de le spécifier explicitement.

Le chemin d’accès

Le chemin d’accès à la ressource permet au serveur de connaître l’emplacement du fichier demandé.

Ports et pare-feu

Apache utilise le port 80 en TCP pour le protocole HTTP. Il faudra donc songer à ouvrir ce port dans le pare-feu.

Notons que théoriquement, l’administrateur peut choisir librement le port d’écoute du serveur.

Installation

Le serveur Apache est fourni par le paquet httpd.

# yum install httpd

L’installation du paquet crée un utilisateur système apache et un groupe système apache correspondant.

# grep apache /etc/passwd
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
# grep apache /etc/group
apache:x:48:
# grep apache /etc/shadow
apache:!!:17352::::::

Premier lancement du serveur

Sous Red Hat et CentOS, Apache est préconfiguré pour afficher une page statique par défaut. Il suffit d’activer et de lancer le service.

# systemctl enable httpd
# systemctl start httpd

Tester le bon fonctionnement du serveur.

$ links http://localhost

On doit voir quelque chose de ce genre.

=================================================================
                           Testing 123..
This page is used to test the proper operation of the Apache HTTP
server after it has been installed. If you can read this page it
means that this site is working properly. This server is powered
by CentOS.
=================================================================

Dans le réseau local, ouvrir l’adresse IP du serveur avec un navigateur.

On peut également invoquer le nom d’hôte.

Sur un serveur dédié, on essaiera successivement l’adresse IP, le nom de domaine et l’alias associé.

Voici à quoi ressemble la page par défaut dans un navigateur graphique.

061 001
Figure 3. La page de test Apache

Les fichiers de configuration

Initialement, la configuration du serveur Apache s’effectuait dans un seul fichier /etc/httpd/conf/httpd.conf. Avec le temps, ce fichier est devenu de plus en plus volumineux et de moins en moins lisible.

Les distributions modernes ont donc tendance à répartir la configuration d’Apache sur une série de fichiers *.conf répartis dans les répertoires /etc/httpd/conf.d et /etc/httpd/conf.modules.d, rattachés au fichier principal /etc/httpd/conf/httpd.conf par la directive Include.

Le fichier /etc/httpd/conf/httpd.conf est amplement documenté. Pour commencer, nous allons sauvegarder ce fichier par défaut et créer une version dépourvue de commentaires et plus lisible. Ici, la commande egrep filtre les lignes qui commencent soit par un commentaire (^#), soit par un espace (^$), soit par quatre espaces suivis d’un commentaire.

# cd /etc/httpd/conf
# cp httpd.conf httpd.conf.orig
# grep -Ev '^#|^$|^    #' httpd.conf.orig > httpd.conf

La configuration par défaut

Jetons un oeil sur le fichier httpd.conf par défaut et regardons de plus près les principales directives qui le constituent.

La directive ServerRoot permet de définir le répertoire dans lequel le serveur est installé.

ServerRoot "/etc/httpd"

La directive Listen permet à Apache d’écouter sur des adresses ou des ports spécifiques. Notons que cette directive est requise. Si elle est absente du fichier de configuration, Apache refuse de démarrer.

Listen 80

Comme nous l’avons vu un peu plus haut, la directive Include permet l’inclusion d’autres fichiers de configuration dans le fichier de configuration principal du serveur. IncludeOptional fonctionne comme Include, au détail près que la directive ne produira pas une erreur au cas où le métacaractère * ne correspond à aucun fichier. Le chemin est relatif par rapport à l’emplacement spécifié dans la directive ServerRoot.

Include conf.modules.d/*.conf
...
IncludeOptional conf.d/*.conf

Apache ne doit pas être lancé en tant que root, mais en tant qu’utilisateur spécial défini par les directives User et Group dans /etc/httpd/conf/httpd.conf. Plus précisément, le processus principal est lancé par root qui lance ensuite des processus enfant avec l’utilisateur et le groupe configurés.

User apache
Group apache

L’adresse mail de l’administrateur, définie par la directive ServerAdmin, apparaîtra sur certaines pages générées par le serveur, notamment les pages d’erreur.

ServerAdmin root@localhost

Les balises <Directory> et </Directory> permettent de regrouper un ensemble de directives qui ne s’appliquent qu’au répertoire précisé, à ses sous-répertoires et aux fichiers situés dans ces sous-répertoires.

<Directory />
  AllowOverride none
  Require all denied
</Directory>
...
<Directory "/var/www">
  AllowOverride None
  Require all granted
</Directory>
<Directory "/var/www/html">
  Options Indexes FollowSymLinks
  AllowOverride None
  Require all granted
</Directory>

La directive DocumentRoot permet de définir le répertoire à partir duquel Apache va servir des fichiers.

DocumentRoot "/var/www/html"

Lorsque le serveur trouve un fichier .htaccess, il doit savoir quelles directives placées dans ce fichier sont autorisées à modifier la configuration préexistante. Le traitement des fichiers .htaccess est contrôlé par la directive AllowOverride, qui ne peut être utilisée que dans les sections <Directory>. À partir du moment où elle est définie à none, les fichiers .htaccess sont totalement ignorés.

<Directory />
  AllowOverride none
  Require all denied
</Directory>

La directive Require permet de contrôler l’accès au système de fichiers du serveur. Require all denied bloque l’accès pour tous les utilisateurs, Require all granted autorise tout le monde.

<Directory />
  AllowOverride none
  Require all denied
</Directory>
...
<Directory "/var/www">
  AllowOverride None
  Require all granted
</Directory>

Comme son nom l’indique, la directive Options permet d’activer ou de désactiver une série d’options (ou de comportements) pour un répertoire donné. Ici par exemple, l’option Indexes affiche la liste des fichiers d’un répertoire en cas d’absence de fichier index.html. FollowSymlinks permet de suivre les liens symboliques.

<Directory "/var/www/html">
  Options Indexes FollowSymLinks
  AllowOverride None
  Require all granted
</Directory>

Les balises <IfModule> et </IfModule> contiennent des directives qui ne s’appliquent qu’en fonction de la présence ou de l’absence d’un module spécifique. La directive DirectoryIndex spécifie le fichier à envoyer par Apache lorsqu’une URL se termine par / et concerne un répertoire entier.

<IfModule dir_module>
  DirectoryIndex index.html
</IfModule>

Les balises <Files> et </Files> contiennent des directives qui s’appliquent aux fichiers précisés. Ici par exemple, on interdit l’accès à tous les fichiers dont le nom commence par .ht, notamment .htaccess.

<Files ".ht*">
  Require all denied
</Files>

La directive ErrorLog définit le chemin vers le journal des erreurs. La verbosité de ce journal est contrôlée par la directive LogLevel.

ErrorLog "logs/error_log"
LogLevel warn

La directive CustomLog permet de contrôler la journalisation des requêtes destinées au serveur. Elle définit le nom et le format du fichier journal.

CustomLog "logs/access_log" combined

La directive AddDefaultCharset paramètre le jeu de caractères par défaut pour les pages de texte. Lorsqu’elle est désactivée (AddDefaultCharset off), Apache prend en compte l’encodage spécifié dans la balise <meta> des fichiers HTML à envoyer au navigateur.

meta http-equiv="Content-Type" content="text/html; charset=utf-8"

Ici en revanche, Apache utilise d’emblée le jeu de caractères spécifié en ignorant la balise <meta>.

AddDefaultCharset UTF-8

Configuration de base

Apache est immédiatement utilisable dans sa configuration par défaut. Avant d’héberger notre premier site, nous allons procéder à quelques ajustements.

Pour commencer, renseigner l’adresse mail de l’administrateur du serveur.

ServerAdmin contact@formatux.fr

Le nom du serveur peut être déterminé automatiquement, mais il vaut mieux le spécifier explicitement grâce à la directive ServerName.

ServerName stagiaire.formatux.fr

Sur un serveur dédié, on aura ceci.

ServerName sd-100246.dedibox.fr

Pour la journalisation, on choisira un format un peu moins bavard.

CustomLog "logs/access_log" common

Enfin, on permettra aux pages hébergées de spécifier leur propre encodage.

AddDefaultCharset off

Tester la nouvelle configuration :

# apachectl configtest
Syntax OK

Prendre en compte les modifications :

# systemctl reload httpd

Héberger un site statique

Dans la configuration par défaut, Apache est censé servir le contenu de /var/www/html. En l’absence de contenu, la page de test s’affiche, en fonction de la configuration prédéfinie dans /etc/httpd/conf.d/welcome.conf.

Pour nous épargner la corvée de créer du contenu fictif, nous pouvons récupérer un site web existant. On choisira la documentation de Slackware, qui vient sous forme d’une série de pages HTML statiques.

# cd /var/www/html/
# wget -r -np -nH --cut-dirs=1 http://www.slackbook.org/html/

Ouvrir le site dans un navigateur (Firefox, Links, Lynx) et apprécier le résultat.

Apache et les permissions de fichiers

Apache ne doit pas être lancé en tant que root, mais en tant qu’utilisateur spécial défini par les directives User et Group dans /etc/httpd/conf/httpd.conf.

User apache
Group apache

La règle de sécurité générale veut que les contenus du serveur web ne doivent pas appartenir au processus qui fait tourner le serveur.

Ici, nous attribuons les contenus à l’utilisateur non privilégié stagiaire1 et au groupe associé stagiaires. En passant, nous en profitons pour restreindre les droits d’accès du groupe.

# cd /var/www/html
# chown -R stagiaire1:stagiaire ./*
# find ./ -type d -exec chmod 0755 \{} \;
# find ./ -type f -exec chmod 0644 \{} \;

Héberger plusieurs sites sur le même serveur

Le principe des hôtes virtuels (Virtual Hosts) consiste à faire fonctionner un ou plusieurs sites Web sur une même machine. L’utilisateur final ne perçoit pas qu’en fait il s’agit d’un même serveur physique.

Nous allons héberger trois sites :

Pour commencer, on va déplacer le site existant dans un nouveau répertoire slackware/html.

# cd /var/www/
# mkdir -pv ./slackware/html
mkdir: création du répertoire « ../slackware »
mkdir: création du répertoire « ../slackware/html »
# mv ./html/* ./slackware/html/

Puis, on va créer un autre répertoire freebsd/html, dans lequel on va télécharger un autre site, en l’occurrence la documentation de FreeBSD.

# mkdir -pv freebsd/html
mkdir: création du répertoire « freebsd »
mkdir: création du répertoire « freebsd/html »
# cd freebsd/html
# wget -r -p -np -nH --cut-dirs=4 \
  http://www.freebsd.org/doc/fr_FR.ISO8859-1/books/handbook/

Enfin, on va mettre en place une page par défaut dans le répertoire default/html. Pour ce faire, on va utiliser la page qui s’affiche lorsqu’il n’y a pas de contenu.

# cd /var/www/
# mkdir -pv default/html
mkdir: création du répertoire « default »
mkdir: création du répertoire « default/html »
# cp -R /usr/share/httpd/noindex/* default/html/

Au total, nous avons donc :

# ls -l
total 12
drwxr-xr-x 3 root root 4096 23 févr. 06:36 default
drwxr-xr-x 3 root root 4096 23 févr. 06:21 freebsd
drwxr-xr-x 3 root root 4096 23 févr. 06:19 slackware

Nous allons redéfinir les permissions :

# chown -R stagiaire:stagiaire ./*
# find . -type d -exec chmod 0755 \{} \;
# find . -type f -exec chmod 0644 \{} \;

Créer un fichier /etc/httpd/conf.d/00-formatux.fr.conf. Ce fichier définira le site affiché par défaut, c’est-à-dire lorsqu’on invoque l’adresse IP ou le nom d’hôte de la machine :

# Page par défaut
<VirtualHost *:80>
  ServerAdmin info@formatux.fr
  DocumentRoot "/var/www/default/html"
  ServerName www.formatux.fr
  ServerAlias formatux.fr
  ErrorLog logs/formatux.fr-error_log
  CustomLog logs/formatux.fr-access_log common
</VirtualHost>

Prendre en compte les modifications :

# systemctl reload httpd

Vérifier si la page par défaut du serveur s’affiche comme prévu :

$ links http://www.formatux.fr

À présent, nous pouvons ajouter les deux autres sites. Le site http://slackware.formatux.fr sera configuré comme ceci :

# http://slackware.formatux.fr
<VirtualHost *:80>
  ServerAdmin info@formatux.fr
  DocumentRoot "/var/www/slackware/html"
  ServerName slackware.formatux.fr
  ErrorLog logs/slackware.formatux.fr-error_log
  CustomLog logs/slackware.formatux.fr-access_log common
</VirtualHost>

La configuration de http://freebsd.formatux.fr suivra la même logique :

# http://freebsd.formatux.fr
<VirtualHost *:80>
  ServerAdmin info@formatux.fr
  DocumentRoot "/var/www/freebsd/html"
  ServerName freebsd.formatux.fr
  ErrorLog logs/freebsd.formatux.fr-error_log
  CustomLog logs/freebsd.formatux.fr-access_log common
</VirtualHost>

Pour l’instant, les noms d’hôtes slackware.formatux.fr et freebsd.formatux.fr ne correspondent à rien dans notre réseau local. Nous devons les ajouter à /etc/hosts sur le serveur.

192.168.2.5 www.formatux.fr formatux.fr  freebsd.formatux.fr slackware.formatux.fr

Redémarrer Dnsmasq pour propager l’info DNS.

# systemctl restart dnsmasq

Prendre en compte la nouvelle configuration d’Apache.

# systemctl reload httpd

Tester les deux sites en local avec Links ou Firefox sur une machine du réseau local.

Héberger des sites dynamiques avec PHP

Installer PHP :

# yum install php

Mettre en place un hôte virtuel http://phpinfo.formatux.fr et éditer la configuration correspondante. L’hôte virtuel contiendra une seule page index.php que l’on éditera comme ceci :

<?php
 echo phpinfo();
?>

Ajouter une entrée correspondante dans la configuration DNS ou dans le fichier /etc/hosts et redémarrer Apache :

# systemctl restart httpd

Afficher la page http://phpinfo.formatux.fr dans un navigateur. On doit obtenir quelque chose qui ressemble grosso modo à ceci :

061 002
Figure 4. La page phpinfo() de PHP

Le fichier /etc/php.ini contient la configuration de PHP. On peut commencer par définir le fuseau horaire du serveur, nécessaire pour le bon fonctionnement de certaines applications :

[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Europe/Paris

Redémarrer Apache et vérifier les données correspondantes dans la page qui affiche les infos PHP.

Vous pouvez en apprendre plus sur PHP en suivant notre cours SVR-121-Php-fpm.

Utiliser MySQL/MariaDB à partir de PHP

Pour utiliser MySQL/MariaDB à partir de PHP, il suffit d’installer le module correspondant et de redémarrer Apache.

# yum install php-mysql
# systemctl restart httpd

La gestion d’une base de données MariaDB/MySQL est abordée dans le cours SVR-131-MySQL.