{"id":646,"date":"2023-06-19T17:05:00","date_gmt":"2023-06-19T16:05:00","guid":{"rendered":"https:\/\/almic.fr\/blog\/?p=646"},"modified":"2026-01-24T13:18:09","modified_gmt":"2026-01-24T12:18:09","slug":"lamp-debian-bookworm","status":"publish","type":"post","link":"https:\/\/almic.fr\/blog\/2023\/06\/19\/lamp-debian-bookworm\/","title":{"rendered":"LAMP avec Debian bookworm"},"content":{"rendered":"<p style=\"text-align: justify;\">Voici comment installer sur Linux la pile Apache, MariaDB et PHP (plus PhpMyAdmin). C\u2019est une refonte de mes tutoriels pr\u00e9c\u00e9dents <a href=\"https:\/\/almic.fr\/blog\/2006\/09\/25\/apache-2\/\">pour Apache<\/a> et <a href=\"https:\/\/almic.fr\/blog\/2011\/12\/09\/heberger-mysql\/\">pour MySQL<\/a>, qui n\u00e9cessitaient une r\u00e9\u00e9criture plut\u00f4t qu\u2019une \u00e9ni\u00e8me mise \u00e0 jour : je profite de la sortie de bookworm pour tout remettre \u00e0 plat. N\u00e9anmoins, la version de 2006 pour Apache contient quelques informations sur lesquelles je ne reviens pas ici.<\/p>\n<p><!--more--><\/p>\n<h2>Apache et PHP<\/h2>\n<h4>Installation<\/h4>\n<pre>\n# apt install apache2 php-fpm php-mysql\n# a2enmod proxy_fcgi setenvif\n# a2enconf php8.2-fpm\n# a2enmod ssl\n<\/pre>\n<p style=\"text-align: justify;\">Je vous conseille de faire un tour dans <i>\/etc\/apache2\/conf-enabled\/security.conf<\/i>. Je cite ici le commentaire au d\u00e9but de ce fichier\u00a0: \u201cChanging the following options will not really affect the security of the server, but might make attacks slightly more difficult in some cases.\u201d<\/p>\n<p style=\"text-align: justify;\">Voici les param\u00e8tres que j\u2019ai chang\u00e9 :<\/p>\n<pre>\nServerTokens Prod\nServerSignature Off\nHeader set Content-Security-Policy \"frame-ancestors 'self';\"\n<\/pre>\n<p style=\"text-align: justify;\">La derni\u00e8re ligne demande d\u2019activer le module headers :<\/p>\n<pre>\n# a2enmod headers\n<\/pre>\n<p style=\"text-align: justify;\">On relance Apache pour qu\u2019il prenne en compte les modifications :<\/p>\n<pre>\n# systemctl restart apache2.service\n<\/pre>\n<h4>Certificats<\/h4>\n<p style=\"text-align: justify;\">Aujourd&rsquo;hui, le Web est synonyme de https. Vous pouvez regarder <a href=\"https:\/\/almic.fr\/blog\/2016\/01\/07\/certificats-gratuits-avec-lets-encrypt\/\">ce tutoriel<\/a> pour mettre en place des certificats Let\u2019s Encrypt sur un syst\u00e8me Debian.<\/p>\n<h4>Exemple de site web<\/h4>\n<p style=\"text-align: justify;\">On cr\u00e9e un fichier <i>\/etc\/apache2\/sites-available\/domain.tld.conf<\/i> :<\/p>\n<pre>\n&lt;VirtualHost *:443&gt;\n    ServerName almic.fr\n    SSLEngine on\n    SSLCertificateFile \/etc\/letsencrypt\/live\/almic.fr\/fullchain.pem\n    SSLCertificateKeyFile \/etc\/letsencrypt\/live\/almic.fr\/privkey.pem\n    RedirectMatch temp ^\/$ \/blog\n    DocumentRoot \/srv\/www\/almic.fr\n    &lt;Directory \/srv\/www\/almic.fr&gt;\n        Require all granted\n        Options -Indexes +SymLinksIfOwnerMatch +MultiViews\n        AllowOverride None\n    &lt;\/Directory&gt;\n    LogLevel warn\n    CustomLog \/var\/log\/apache2\/almic-access.log combined\n    ErrorLog \/var\/log\/apache2\/almic-access.log\n&lt;\/VirtualHost&gt;\n<\/pre>\n<p style=\"text-align: justify;\">Dans ce m\u00eame fichier, on peut rajouter une redirection pour le http, et \u00e9ventuellement une pour https:\/\/www.domain.tld.<\/p>\n<pre>\n&lt;VirtualHost *:80&gt;\n    ServerName almic.fr\n    ServerAlias www.almic.fr\n    RedirectMatch temp ^(.*)$ https:\/\/almic.fr$1\n&lt;\/VirtualHost&gt;\n&lt;VirtualHost *:443&gt;\n    ServerName www.almic.fr\n    SSLEngine on\n    SSLCertificateFile \/etc\/letsencrypt\/live\/www.almic.fr\/fullchain.pem\n    SSLCertificateKeyFile \/etc\/letsencrypt\/live\/www.almic.fr\/privkey.pem\n    RedirectMatch temp ^(.*)$ https:\/\/almic.fr$1\n&lt;\/VirtualHost&gt;\n<\/pre>\n<p style=\"text-align: justify;\">La <a href=\"https:\/\/httpd.apache.org\/docs\/2.4\/fr\/rewrite\/avoid.html\">documentation d\u2019Apache<\/a> explique qu\u2019il vaut mieux utiliser RedirectMatch \u00e0 la place de RewriteRule.<\/p>\n<p style=\"text-align: justify;\">On recharge la configuration d\u2019Apache :<\/p>\n<pre>\n# a2ensite almic.fr\n# systemctl reload apache2.service\n<\/pre>\n<h4>Last resort host : pour les domaines inconnus d\u2019Apache<\/h4>\n<p style=\"text-align: justify;\">Si un petit malin tente de charger l&rsquo;adresse IP de votre serveur, ou alors tente de charger un domaine qui pointe sur son IP, mais que vous utilisez pour d&rsquo;autres services (typiquement mx.domain.tld), c\u2019est-\u00e0-dire un domaine pour lequel il n\u2019existe pas de configuration, \u00e0 la place Apache va servir le premier domaine se trouvant dans <i>\/etc\/apache2\/sites-enabled<\/i>. Si vous g\u00e9rez plusieurs domaines sur le m\u00eame serveur et la m\u00eame IP, il est pr\u00e9f\u00e9rable de g\u00e9rer ce cas sp\u00e9cifiquement, plut\u00f4t que servir un domaine qui ne correspond pas \u00e0 l&rsquo;URL entr\u00e9e dans le navigateur.<\/p>\n<p style=\"text-align: justify;\">La configuration par d\u00e9faut d\u2019Apache inclue un last resort host pour le http. Bien que \u00e7a ne soit pas n\u00e9cessaire, j\u2019ai modifi\u00e9 \/etc\/apache2\/sites-enabled\/000-default.conf de la mani\u00e8re suivante :<\/p>\n<pre>\n&lt;VirtualHost *:80&gt;\n    DocumentRoot \/srv\/www\/403_verboten\n    &lt;Directory \/srv\/www\/403_verboten&gt;\n        Require all granted\n    &lt;\/Directory&gt;\n    ErrorLog ${APACHE_LOG_DIR}\/default-error.log\n    CustomLog ${APACHE_LOG_DIR}\/default-access.log combined\n&lt;\/VirtualHost&gt;\n<\/pre>\n<p style=\"text-align: justify;\">R\u00e9sultat :<\/p>\n<p><center><img decoding=\"async\" src=\"https:\/\/almic.fr\/blog\/wp-uploads\/2023\/07\/Verboten.png\"><\/center><\/p>\n<p style=\"text-align: justify;\">Si quelqu\u2019un voit \u00e7a, c\u2019est qu\u2019il est de toute fa\u00e7on en train de jouer au plus malin\u2026 alors autant m\u2019amuser un peu moi aussi. Je rappelle que c\u2019est mon serveur perso, pas un serveur de prod ;-)<\/p>\n<p style=\"text-align: justify;\">La configuration par d\u00e9faut d\u2019Apache n\u2019inclue pas de last resort host pour le https. La solution propre serait de g\u00e9n\u00e9rer des certificats pour tous les domaines qui pointent vers ce serveur, et qui sont inconnus d\u2019Apache. Mais pour un serveur perso, je trouve que \u00e7a serait abuser des services de Let\u2019s Encrypt. Donc \u00e0 choisir, je pr\u00e9f\u00e8re encore une erreur \u00e0 cause d\u2019un certificat auto-sign\u00e9, plut\u00f4t qu\u2019une erreur \u00e0 cause d\u2019un certificat qui ne correspond pas au domaine demand\u00e9.<\/p>\n<p style=\"text-align: justify;\">On cr\u00e9\u00e9 \/etc\/apache2\/sites-available\/100-default-tls.conf :<\/p>\n<pre>\n&lt;VirtualHost _default_:443&gt;\n    ServerName default.local\n    SSLEngine on\n    SSLCertificateFile \/etc\/ssl\/private\/Self_signed.pem\n    RewriteEngine On\n    RewriteRule ^(.*)$ http:\/\/%{HTTP_HOST} [R=302,L]\n    ErrorLog ${APACHE_LOG_DIR}\/default-tls-error.log\n    CustomLog ${APACHE_LOG_DIR}\/default-tls-access.log combined\n&lt;\/VirtualHost&gt;\n<\/pre>\n<p style=\"text-align: justify;\">Si la cl\u00e9 et le certificat sont stock\u00e9s ensemble dans le m\u00eame fichier, seule la directive <i>SSLCertificateFile<\/i> est n\u00e9cessaire. Ici on est oblig\u00e9 d\u2019utiliser <i>RewriteRule<\/i>, parce qu\u2019on ne sait pas quel domaine sera vis\u00e9. Il faut donc utiliser <nobr><i>%{HTTP_HOST}<\/i><\/nobr>, qui n\u2019est pas g\u00e9r\u00e9 par <i>RedirectMatch<\/i>.<\/p>\n<p style=\"text-align: justify;\">On cr\u00e9e le certificat auto-sign\u00e9, puis on recharge la configuration d\u2019Apache :<\/p>\n<pre>\n# 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\"\n# chmod 600 \/etc\/ssl\/private\/Self_signed.pem\n# a2ensite 100-default-tls\n# systemctl reload apache2.service\n<\/pre>\n<h2>MariaDB<\/h2>\n<h4>Installation<\/h4>\n<p style=\"text-align: justify;\">On installe le paquet :<\/p>\n<pre>\n# apt install mariadb-server\n<\/pre>\n<p style=\"text-align: justify;\">Je pr\u00e9f\u00e8re changer le jeu de caract\u00e8res par d\u00e9faut. \u00c7a se passe dans le fichier <i>\/etc\/mysql\/mariadb.conf.d\/50-server.cnf<\/i> :<\/p>\n<pre>\ncollation-server      = utf8mb4_unicode_520_ci\n<\/pre>\n<p style=\"text-align: justify;\">Sous Debian, la version d\u2019Unicode la plus r\u00e9cente support\u00e9e 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\u00e9 sans ces classements UCA9.<\/p>\n<p style=\"text-align: justify;\">Sur mon serveur, la pile LAMP est dans un conteneur LXC d\u00e9di\u00e9. J\u2019ai d\u2019autres conteneurs qui ont besoin d\u2019acc\u00e9der au serveur MariaDB, donc ce dernier doit \u00e9couter sur l\u2019interface du r\u00e9seau des conteneurs LXC. Toujours dans <i>\/etc\/mysql\/mariadb.conf.d\/50-server.cnf<\/i> :<\/p>\n<pre>\nbind-address            = 192.168.XXX.Y\n<\/pre>\n<p style=\"text-align: justify;\">On relance MariaDB :<\/p>\n<pre>\n# systemctl restart mariadb.service\n<\/pre>\n<p style=\"text-align: justify;\">MariaDB fournit un script pour le configurer avec un niveau minimal de s\u00e9curit\u00e9.<\/p>\n<pre>\n# mysql_secure_installation\nSwitch to unix_socket authentication [Y\/n] n\nChange the root password? [Y\/n] y\nRemove anonymous users? [Y\/n] y\nDisallow root login remotely? [Y\/n] y\nRemove test database and access to it? [Y\/n] y\nReload privilege tables now? [Y\/n] y\n<\/pre>\n<h4>PhpMyAdmin<\/h4>\n<p style=\"text-align: justify;\">On installe le paquet :<\/p>\n<pre>\n# apt install phpmyadmin\n<\/pre>\n<p style=\"text-align: justify;\">dpkg va vous demander si vous voulez configurer un serveur web :<\/p>\n<pre>\nPlease choose the web server that should be automatically configured to run phpMyAdmin. Web server to reconfigure automatically:\n<\/pre>\n<p style=\"text-align: justify;\">Je pr\u00e9f\u00e8re ne pas activer le fichier de configuration Apache fourni avec le paquet (<i>\/etc\/phpmyadmin\/apache.conf<\/i>) via cette bo\u00eete de dialogue debconf. En effet, il s\u2019ajouterait alors \u00e0 la config g\u00e9n\u00e9rale d\u2019Apache, donc \u00e7a s&rsquo;appliquerait \u00e0 tous les <i>VirtualHost<\/i>. Donc n\u2019importe qui pourrait acc\u00e9der au PhpMyAdmin sur ce serveur, il suffirait d\u2019ajouter <i>\/phpmyadmin<\/i> \u00e0 la fin d\u2019un domaine servi par Apache. Certes, un attaquant n\u2019aurait acc\u00e8s qu&rsquo;\u00e0 la page de login, et il ne pourrait pas aller plus loin sans identifiant. Mais des failles de s\u00e9curit\u00e9 pourraient \u00eatre exploitables juste en ayant acc\u00e8s aux fichiers de PhpMyAdmin. Ce dernier n\u2019a \u00e9videmment rien \u00e0 faire en prod, mais m\u00eame sur des serveurs de test ou sur un serveur perso, je pense qu\u2019il vaut mieux charger la config Apache pour PhpMyAdmin dans un <i>VirtualHost<\/i> accessible uniquement \u00e0 partir du r\u00e9seau local ou d\u2019un VPN.<\/p>\n<p style=\"text-align: justify;\">Dans le fichier de configuration du domaine que vous utilisez pour acc\u00e9der \u00e0 votre serveur en local (ou alors dans la config du last resort host), rajoutez les lignes suivantes :<\/p>\n<pre>\n&lt;Location \"\/\"&gt;\n    Require ip ::1 127.0.0.1\n    Require ip 192.168.XXX.0\/24\n&lt;\/Location&gt;\n\n# PhpMyAdmin\nInclude \/etc\/phpmyadmin\/apache.conf\n<\/pre>\n<p style=\"text-align: justify;\">On recharge la configuration d\u2019Apache :<\/p>\n<pre>\n# systemctl reload apache2.service\n<\/pre>\n<h4>Importer vos bases<\/h4>\n<p style=\"text-align: justify;\">Quand on exporte une base \u00e0 partir du menu Exporter dans PhpMyAdmin, par d\u00e9faut le fichier ne contiendra pas les instructions <i>CREATE DATABASE base<\/i> et <i>USE base<\/i>. Si vous essayez d&rsquo;importer ce fichier tel quel, \u00e7a ne marchera pas.<\/p>\n<p style=\"text-align: justify;\">Si vous voulez g\u00e9n\u00e9rer un fichier qui peut \u00eatre import\u00e9 directement, il faut activer l&rsquo;option correspondante :<\/p>\n<pre>\nM\u00e9thode d'exportation : Personnalis\u00e9e, afficher toutes les options possibles\n&gt; Options sp\u00e9cifiques au format\n&gt; Options de cr\u00e9ation d'objets\net s\u00e9lectionnez Ajouter une instruction CREATE DATABASE \/ USE\n<\/pre>\n<p style=\"text-align: justify;\">Si vous avez d\u00e9j\u00e0 g\u00e9n\u00e9r\u00e9 le fichier, il faut rajouter les lignes suivantes au d\u00e9but :<\/p>\n<pre>\nCREATE DATABASE table;\nUSE table;\n<\/pre>\n<p style=\"text-align: justify;\">Il ne reste plus qu\u2019\u00e0 cr\u00e9er les utilisateurs SQL dont vous avez besoin, et \u00e0 importer <i>toutes vos base<\/i> sur votre nouveau serveur.<\/p>\n<pre>\n# mysql -u root < BD.sql\n<\/pre>\n<p><center><img decoding=\"async\" src=\"https:\/\/almic.fr\/blog\/wp-uploads\/2023\/07\/All_your_bases_are_belong_to_us.png\"><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Voici comment installer sur Linux la pile Apache, MariaDB et PHP (plus PhpMyAdmin). C\u2019est une refonte de mes tutoriels pr\u00e9c\u00e9dents pour Apache et pour MySQL, qui n\u00e9cessitaient une r\u00e9\u00e9criture plut\u00f4t qu\u2019une \u00e9ni\u00e8me mise \u00e0 jour : je profite de la sortie de bookworm pour tout remettre \u00e0 plat. N\u00e9anmoins, la version de 2006 pour Apache&hellip; <a class=\"continue\" href=\"https:\/\/almic.fr\/blog\/2023\/06\/19\/lamp-debian-bookworm\/\">Continue Reading LAMP avec Debian bookworm<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-646","post","type-post","status-publish","format-standard","hentry","category-hebergement","radius"],"_links":{"self":[{"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/posts\/646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/comments?post=646"}],"version-history":[{"count":84,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/posts\/646\/revisions"}],"predecessor-version":[{"id":862,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/posts\/646\/revisions\/862"}],"wp:attachment":[{"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/media?parent=646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/categories?post=646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/almic.fr\/blog\/wp-json\/wp\/v2\/tags?post=646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}