La séquence de travaux pratiques ci-dessous est la suite du TP consacré au déploiement d’un serveur web basé sur LAMP (Linux Apache MariaDB & PHP).
Nous allons produire ici un serveur basé sur le service NGINX et non plus Apache. On évoque souvent le nom de LEMP pour cette configuration : Linux EngineX (nginx) MariaDB & PHP.
L’objectif sera de restaurer les fichiers et les bases de données issues du premier serveur LAMP et de retrouver des services fonctionnels.
Nginx est un serveur HTTP et reverse proxy open source hautes performances sur lequel reposent certains des plus grands sites WEB. Nginx peut être utilisé comme serveur Web autonome et comme proxy inverse pour Apache et d'autres serveurs Web. Par rapport à Apache, qui est la solution historique, Nginx peut gérer un très grand nombre de connexions simultanées et a une empreinte mémoire plus petite par connexion. C'est depuis avril 2019, le serveur web le plus utilisé au monde.
On repart de l’environnement initial du mini-lab virtuel personnel pour réaliser cette maquette :
Tout d'abord, sur notre VM debian-gui (cliente), on lance une mise à jour et l'installation des outils wget, curl et dnsutils (qui auront peut-être déjà installés lors du précédent TP) :
sudo apt update && sudo apt upgrade && sudo apt -y install curl wget dnsutils
Ensuite, pour éviter que les prochaines connexions SSH soit refusées, on va supprimer le fichier des hôtes connus :
rm ~/.ssh/known_hosts
Maintenant, occupons-nous du serveur debian-core :
ssh pascal@192.168.1.10
sudo nano /etc/hostname
sudo nano /etc/hosts
qui doit au final ressembler à ceci :
127.0.0.1 localhost
127.0.1.1 debian-lemp
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Et enfin on redémarre le serveur :
sudo reboot
Puis, une fois le serveur relancé, on s'y reconnecte en ssh :
ssh pascal@192.168.1.10
On lance une mise à jour et l'installation des utilitaires wget et tree :
sudo apt update && sudo apt upgrade && sudo apt -y install wget tree
Comme beaucoup des services que nous utilisons, on l’installe tout simplement avec ;
sudo apt install -y nginx
On peut dès lors tester le fonctionnement depuis le navigateur de la machine cliente (gui) :
Ou encore depuis le terminal (toujours sur la VM cliente) :
curl -I 192.168.1.10
On dispose des actions habituelles pour administrer le service nginx, comme par exemple :
systemctl status nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
On peut également utiliser la commande suivante pour lister les ports en écoute sur le serveur :
ss -ntaul
qui nous donne :
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 511 [::]:80 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
Lignes 3 et 5 : service SSH (tcp/22
), en écoute sur toute interface IPv4 (0.0.0.0
) ou IPv6 ([::]
)
Lignes 2 et 4 : service http NGINX (tcp/80
), en écoute lui aussi sur toute interface IPv4 (0.0.0.0
) ou IPv6 ([::]
)
L’installation de NGINX vient avec une configuration de base, qui s’appuie sur la structure du répertoire /etc/nginx dont voici l’arborescence :
tree /etc/nginx
Le fichier de configuration principal est /etc/nginx/nginx.conf
; le voici (filtré par un double grep pour supprimer les lignes de commentaires et les lignes vides) :
cat /etc/nginx/nginx.conf | grep -v ^[[:space:]]*# | grep -v ^[[:space:]]*$
qui affiche :
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Quelles informations importantes peut-on y voir ?
Comme pour apache, les processus de service http seront affecté (ligne 1) à l’utilisateur www-data
(qui a été créé lors de l’installation) ; ce sont les droits de cet utilisateur qui devront être pris en compte sur les fichiers gérés par le serveur http (répertoire racine, fichiers de configuration de site web, ...).
Concernant le service http lui-même, on définit (ligne 17) l’emplacement des fichiers de log pour les accès (connexions au serveur). Ces fichiers sont importants pour l’analyse du trafic et l’analyse d’incidents.
On voit également (ligne 15) le bannissement du protocole de chiffrement SSL v3, à l’origine de la faille de sécurité connue appelée Poodle. Notons au passage que le TLS v1 et v1.1 sont également dépréciés, il faudra affiner ces paramètres lors de la configuration spécifique d'un serveur HTTPS.
Enfin, on voit que le système ira chercher (lignes 19 et 20) des configurations complémentaires dans :
/etc/nginx/conf.d
(fichiers avec une extension .conf
)/etc/nginx/sites-enabled/
La bonne pratique veut que chaque site WEB servi par NGINX soit défini dans le dossier /etc/nginx/sites-available
et qu’il soit activé en créant un lien symbolique du fichier de configuration dans le répertoire /etc/nginx/sites-enabled
. C’est ce qu’on peut voir dans l’arborescence de /etc/nginx
, avec le fichier default -> /etc/nginx/sites-available/default
Les modules sont des applications qui ajoutent des fonctionnalités à NGINX (notamment via les fichiers de configuration). Il y a des modules de base et des modules "tierce partie" qui peuvent être ajoutés.
Le répertoire /etc/nginx/snippets
contient des morceaux de configuration qui peuvent être inclus dans les fichiers de bloc serveur. Si vous utilisez des segments de configuration répétables, vous pouvez regrouper ces segments dans des snippets de code et inclure ces snippets dans les blocs serveur.
Nginx server blocks permet d'exécuter plusieurs sites Web sur une seule machine. Avec server blocks, on peut spécifier la racine du site (le répertoire qui contient les fichiers du site Web), créer une politique de sécurité distincte pour chaque site, utiliser différents certificats SSL pour chaque site et bien plus encore.
NB : dans certaines documentations, vous verrez la notion de blocs serveur appelée "hôte virtuel" ou "virtual host". Un hôte virtuel est un terme issu du monde Apache.
Nous allons d’abord installer le moteur PHP, via le paquet Debian php-fpm :
sudo apt -y install php-fpm
Vérifier (et noter) la version de PHP :
php -v
Nous allons créer un bloc serveur pour notre exemple.
example.com
dans le répertoire des fichiers de configuration de blocs disponibles (sites-available) :sudo nano /etc/nginx/sites-available/example.com
le nom de site choisi est le même que pour le premier TP LAMP.
Voici le contenu de la configuration de notre bloc serveur (les commentaires indiquent le rôle de chaque ligne) :
server {
# écoute sur le port 80 de l'IPv4 du serveur :
listen 80;
# écoute sur le port 80 de l'IPv6 du serveur :
listen [::]:80;
# Définir le répertoire racine du site internet :
root /var/www/example;
# Définir l'ordre d'exécution des index (par priorité)
index index.php index.html index.htm;
# Définir le nom du serveur (virtual host)
server_name example.com;
# Emplacements des fichiers log
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# essaye la requête ($uri) comme fichier, puis comme répertoire
# en cas d’échec, erreur http 404
location / {
try_files $uri $uri/ =404;
}
# on active PHP comme moteur de script du serveur, en mode socket :
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
# on bloque l'accès aux fichiers .htaccess (compatibilité apache)
location ~ /\.ht {
deny all;
}
}
NB : php8.2 est à adapter en fonction de la version de PHP qui a été effectivement installée.
Activons cette nouvelle configuration en créant un lien symbolique du fichier vers le répertoire des sites activés (enabled) :
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Enfin, testons la configuration Nginx pour vérifier si la syntaxe globale est correcte :
sudo nginx -t
La sortie nous indique (normalement) que le fichier de configuration nginx (et ses includes) n'ont pas d'erreur de syntaxe, et que le test de la configuration est ok :
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Il nous reste à redémarrer nginx :
sudo systemctl restart nginx
En nous inspirant du précédent TP LAMP, nous allons maintenant réaliser les étapes suivantes :
/etc/hosts
du client pour intégrer la résolution des noms de domaine example.com
et example.fr
example.fr
, dont le répertoire racine est /var/www/example/wordpress
/var/www/example
sudo mysql -u root < example_db.sql
, sans oublier de recréer les utilisateurs et les droitsLet'go !
Sur la machine cliente, on ajoute (si elle n'est pas déjà présente du premier TP LAMP) la résolution des domaines :
sudo nano /etc/hosts
qui contient donc :
127.0.0.1 localhost
127.0.1.1 debian-gui
192.168.1.10 example.com
192.168.1.10 example.fr
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
example.fr
dans le répertoire des fichiers de configuration de blocs disponibles :sudo nano /etc/nginx/sites-available/example.fr
server {
# écoute sur le port 80 de l'IPv4 du serveur :
listen 80;
# écoute sur le port 80 de l'IPv6 du serveur :
listen [::]:80;
# Définir le répertoire racine du site internet :
root /var/www/example/wordpress;
# Définir l'ordre d'exécution des index (par priorité)
index index.php index.html index.htm;
# Définir le nom du serveur (virtual host)
server_name example.fr;
# Emplacements des fichiers log
access_log /var/log/nginx/example.fr.access.log;
error_log /var/log/nginx/example.fr.error.log;
# essaye la requête ($uri) comme fichier, puis comme répertoire
# en cas d’échec, erreur http 404
location / {
try_files $uri $uri/ =404;
}
# on active PHP comme moteur de script du serveur, en mode socket :
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
# on bloque l'accès aux fichiers .htaccess (compatibilité apache)
location ~ /\.ht {
deny all;
}
}
Les différences par rapport au premier se situent :
example.fr
Activons cette nouvelle configuration :
sudo ln -s /etc/nginx/sites-available/example.fr /etc/nginx/sites-enabled/
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl restart nginx
Par cette commande globale, on installe les modules php dont nous aurons besoin :
sudo apt -y install php-mysql php-mbstring php-bz2 php-zip
Les étapes sont identiques que dans le TP LAMP, à savoir :
Installation :
sudo apt install mariadb-server
Et configuration initiale :
sudo mysql_secure_installation
Dans notre contexte, les réponses à donner sont dans l'ordre : Entrée, n, n, y, y, y, y.
On ne crée pas de bases de données, car nous allons les restaurer depuis les sauvegardes (il faudra cependant créer les utilisateurs)
L'archive de sauvegarde de l'ancien serveur LAMP est normalement dans le répertoire Téléchargements de l'utilisateur de la machine cliente.
Depuis le terminal client, on lance donc le transfert de l’archive sur le serveur:
scp ~/Téléchargements/example.tar.gz pascal@192.168.1.10:~
L'archive est désormais sur le serveur, dans le dossier personnel de l'utilisateur standard, qui en est aussi le propriétaire :
ls -lh ~
Pour restaurer l'archive, on utilise la commande tar. On se positionne à la racine du système de fichiers :
cd /
Puis on lance l'extraction de l'archive :
sudo tar -xvzf ~/example.tar.gz
NB : l'opération conserve les attributs des fichiers, notamments les propriétaires, les droits, les dates, ...
Les "dumps" des bases de données de l'ancien serveur LAMP sont aussi dans le répertoire Téléchargements de l'utilisateur de la machine cliente.
Depuis le terminal client, on lance donc leur transfert vers le serveur:
scp ~/Téléchargements/*.sql pascal@192.168.1.10:~
On retrouve nos deux sauvegardes, qui se situent dans le dossier personnel de l'utilisateur standard :
example_db.sql 100% 750KB 18.2MB/s 00:00
phpmyadmin.sql 100% 13KB 3.9MB/s 00:00
Ce sont en faire des scripts SQL. Lors du processus de dump avec phpMyAdmin, on avait inclus les directives de création des bases de données dans le fichier ; ce qui permet de les créer et les restaurer avec une seule commande pour chacune :
sudo mysql -u root < ~/example_db.sql
puis :
sudo mysql -u root < ~/phpmyadmin.sql
On se connecte au shell mysql :
sudo mysql -u root
On vérifie que les bases sont bien là :
SHOW DATABASES;
en effet :
+--------------------+
| Database |
+--------------------+
| example_db |
| information_schema |
| mysql |
| performance_schema |
| phpmyadmin |
| sys |
+--------------------+
6 rows in set (0,000 sec)
Il ne reste plus qu'à recréer les utilisateurs qui étaient associés à ces bases de données.
Pour la base de wordpress :
GRANT ALL ON example_db.* TO 'example'@'localhost' IDENTIFIED BY 'root';
et pour celle de phpMyAdmin :
GRANT ALL PRIVILEGES ON *.* TO 'pma'@'localhost' IDENTIFIED BY 'pmapass';
On met à jour et on quitte :
FLUSH PRIVILEGES;
EXIT;
Avons-nous bien récupérés des sites fonctionnels ?
Wordpress :
phpMyAdmin :
et bien sûr notre mini formulaire interactif :
Bravo ! Quel chemin parcouru au fil de ces deux TP Serveur WEB... Mais vous aurez pu créer un serveur web LAMP complet de A à Z, installer des applications complexes dessus, et les migrer avec succès sur un autre serveur Web utilisant une autre technologie (NGINX).
Il ne manque plus qu'une partie cruciale malgré tout : la mise en place de la couche cryptographique, qui permet de chiffrer les échanges et de garantir l'authenticité du serveur. La suite au prochain épisode !