LAMP avec Debian bookworm
Voici comment installer Apache, PHP, MariaDB (et PhpMyAdmin) sur un système Debian bookworm. C’est une refonte de mes tutoriels précédents pour Apache et pour MySQL, qui nécessitaient une réécriture plutôt qu’une énième mise à jour. Néanmoins, la version de 2006 pour Apache contient quelques informations sur lesquelles je ne reviens pas ici.
Apache et PHP
Installation
# apt install apache2 php-fpm php-mysql # a2enmod proxy_fcgi setenvif # a2enconf php8.2-fpm # a2enmod ssl
Je vous conseille de faire un tour dans /etc/apache2/conf-enabled/security.conf. Je cite ici le commentaire au début de ce fichier : “Changing the following options will not really affect the security of the server, but might make attacks slightly more difficult in some cases.”
Voici les paramètres que j’ai changé :
ServerTokens Prod ServerSignature Off Header set Content-Security-Policy "frame-ancestors 'self';"
La dernière ligne demande d’activer le module headers :
# a2enmod headers
On relance Apache pour qu’il prenne en compte les modifications :
# systemctl restart apache2.service
Certificats
Aujourd’hui, le Web est synonyme de https. Vous pouvez regarder ce tutoriel pour mettre en place des certificats Let’s Encrypt sur un système Debian.
Exemple de site web
On crée un fichier /etc/apache2/sites-available/domain.tld.conf. Note : il ne faut pas d’espaces entre les < > et VirtualHost ou Directory, mais je dois les mettre ici sinon WordPress confond ces mots entre crochets avec des tags HTML.
< VirtualHost *:443>
ServerName almic.fr
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/almic.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/almic.fr/privkey.pem
RedirectMatch temp ^/$ /blog
DocumentRoot /srv/www/almic.fr
< Directory /srv/www/almic.fr>
Require all granted
Options -Indexes +SymLinksIfOwnerMatch +MultiViews
AllowOverride None
< /Directory>
LogLevel warn
CustomLog /var/log/apache2/almic-access.log combined
ErrorLog /var/log/apache2/almic-access.log
< /VirtualHost>
Dans ce même fichier, on peut rajouter une redirection pour le http, et éventuellement une pour https://www.domain.tld.
< VirtualHost *:80>
ServerName almic.fr
ServerAlias www.almic.fr
RedirectMatch temp ^(.*)$ https://almic.fr$1
< /VirtualHost>
< VirtualHost *:443>
ServerName www.almic.fr
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.almic.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.almic.fr/privkey.pem
RedirectMatch temp ^(.*)$ https://almic.fr$1
< /VirtualHost>
La documentation d’Apache explique qu’il vaut mieux utiliser RedirectMatch à la place de RewriteRule.
On recharge la configuration d’Apache :
# a2ensite almic.fr # systemctl reload apache2.service
Last resort host : pour les domaines inconnus d’Apache
Si un petit malin tente de charger l’adresse IP de votre serveur, ou alors tente de charger un domaine qui pointe sur son IP, mais que vous utilisez pour d’autres services (typiquement mx.domain.tld), c’est-à-dire un domaine pour lequel il n’existe pas de configuration, à la place Apache va servir le premier domaine se trouvant dans /etc/apache2/sites-enabled. Si vous gérez plusieurs domaines sur le même serveur et la même IP, il est préférable de gérer ce cas spécifiquement, plutôt que servir un domaine qui ne correspond pas à l’URL entrée dans le navigateur.
La configuration par défaut d’Apache inclue un last resort host pour le http. Bien que ça ne soit pas nécessaire, j’ai modifié /etc/apache2/sites-enabled/000-default.conf de la manière suivante :
< VirtualHost *:80>
DocumentRoot /srv/www/403_verboten
< Directory /srv/www/403_verboten>
Require all granted
< /Directory>
ErrorLog ${APACHE_LOG_DIR}/default-error.log
CustomLog ${APACHE_LOG_DIR}/default-access.log combined
< /VirtualHost>
Résultat :

Si quelqu’un voit ça, c’est qu’il est de toute façon en train de jouer au plus malin… alors autant m’amuser un peu moi aussi. Je rappelle que c’est mon serveur perso, pas un serveur de prod ;-)
La configuration par défaut d’Apache n’inclue pas de last resort host pour le https. La solution propre serait de générer des certificats pour tous les domaines qui pointent vers ce serveur, et qui sont inconnus d’Apache. Mais pour un serveur perso, je trouve que ça serait abuser des services de Let’s Encrypt. Donc à choisir, je préfère encore une erreur à cause d’un certificat auto-signé, plutôt qu’une erreur à cause d’un certificat qui ne correspond pas au domaine demandé.
On créé /etc/apache2/sites-available/100-default-tls.conf :
< VirtualHost _default_:443>
ServerName default.local
SSLEngine on
SSLCertificateFile /etc/ssl/private/Self_signed.pem
RewriteEngine On
RewriteRule ^(.*)$ http://%{HTTP_HOST} [R=302,L]
ErrorLog ${APACHE_LOG_DIR}/default-tls-error.log
CustomLog ${APACHE_LOG_DIR}/default-tls-access.log combined
< /VirtualHost>
Si la clé et le certificat sont stockés ensemble dans le même fichier, seule la directive SSLCertificateFile est nécessaire. Ici on est obligé d’utiliser RewriteRule, parce qu’on ne sait pas quel domaine sera visé. Il faut donc utiliser
On crée le certificat auto-signé, puis on recharge la configuration d’Apache :
# openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -sha256 -keyout /etc/ssl/private/Self_signed.pem -out /etc/ssl/private/Self_signed.pem -subj "/C=US/ST=Nowhere/L=Nowhere/O=No_server/CN=default.local" # chmod 600 /etc/ssl/private/Self_signed.pem # a2ensite 100-default-tls # systemctl reload apache2.service
MariaDB
Installation
On installe le paquet :
# apt install mariadb-server
Je préfère changer le jeu de caractères par défaut. Ça se passe dans le fichier /etc/mysql/mariadb.conf.d/50-server.cnf :
collation-server = utf8mb4_unicode_520_ci
Sous Debian, la version d’Unicode la plus récente supportée par MariaDB est utf8mb4_unicode_520_ci. MariaDB a introduit les classements utf8mb4_900_* depuis la version 10.6, mais le paquet Debian est compilé sans ces classements UCA9.
Sur mon serveur, la pile LAMP est dans un conteneur LXC dédié. J’ai d’autres conteneurs qui ont besoin d’accéder au serveur MariaDB, donc ce dernier doit écouter sur l’interface du réseau des conteneurs LXC. Toujours dans /etc/mysql/mariadb.conf.d/50-server.cnf :
bind-address = 192.168.XXX.Y
On relance MariaDB :
# systemctl restart mariadb.service
MariaDB fournit un script pour le configurer avec un niveau minimal de sécurité.
# mysql_secure_installation Switch to unix_socket authentication [Y/n] n Change the root password? [Y/n] y Remove anonymous users? [Y/n] y Disallow root login remotely? [Y/n] y Remove test database and access to it? [Y/n] y Reload privilege tables now? [Y/n] y
PhpMyAdmin
On installe le paquet :
# apt install phpmyadmin
dpkg va vous demander si vous voulez configurer un serveur web :
Please choose the web server that should be automatically configured to run phpMyAdmin. Web server to reconfigure automatically:
Je préfère ne pas activer le fichier de configuration Apache fourni avec le paquet (/etc/phpmyadmin/apache.conf) via cette boîte de dialogue debconf. En effet, il s’ajouterait alors à la config générale d’Apache, donc ça s’appliquerait à tous les VirtualHost. Donc n’importe qui pourrait accéder au PhpMyAdmin sur ce serveur, il suffirait d’ajouter /phpmyadmin à la fin d’un domaine servi par Apache. Certes, un attaquant n’aurait accès qu’à la page de login, et il ne pourrait pas aller plus loin sans identifiant. Mais des failles de sécurité pourraient être exploitables juste en ayant accès aux fichiers de PhpMyAdmin. Ce dernier n’a évidemment rien à faire en prod, mais même sur des serveurs de test ou sur un serveur perso, je pense qu’il vaut mieux charger la config Apache pour PhpMyAdmin dans un VirtualHost accessible uniquement à partir du réseau local ou d’un VPN.
Dans le fichier de configuration du domaine que vous utilisez pour accéder à votre serveur en local (ou alors dans la config du last resort host), rajoutez les lignes suivantes :
< Location "/" >
Require ip ::1 127.0.0.1
Require ip 192.168.XXX.0/24
< /Location >
# PhpMyAdmin
Include /etc/phpmyadmin/apache.conf
On recharge la configuration d’Apache :
# systemctl reload apache2.service
Importer vos bases
Quand on exporte une base à partir du menu Exporter dans PhpMyAdmin, par défaut le fichier ne contiendra pas les instructions CREATE DATABASE base et USE base. Si vous essayez d’importer ce fichier tel quel, ça ne marchera pas.
Si vous voulez générer un fichier qui peut être importé directement, il faut activer l’option correspondante :
Méthode d'exportation : Personnalisée, afficher toutes les options possibles > Options spécifiques au format > Options de création d'objets et sélectionnez Ajouter une instruction CREATE DATABASE / USE
Si vous avez déjà généré le fichier, il faut rajouter les lignes suivantes au début :
CREATE DATABASE table; USE table;
Il ne reste plus qu’à créer les utilisateurs SQL dont vous avez besoin, et à importer toutes vos base sur votre nouveau serveur.
# mysql -u root < BD.sql
