Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 515 minIntermédiaire

MariaDB sur Debian 13 : installer, sécuriser et créer les comptes

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • installer MariaDB et expliquer l'authentification de root par socket ;
  • sécuriser une installation neuve ;
  • créer la base et le compte limité d'une application ;
  • ouvrir un accès réseau chiffré et restreint à une adresse ;
  • sauvegarder, restaurer et dépanner une connexion.

3 exercices corrigés

MariaDB est un système de gestion de bases de données relationnelles (SGBD) libre, issu de MySQL et compatible avec lui : c'est le SGBD que Debian installe quand une application demande « MySQL ». GLPI, Zabbix, Nextcloud ou WordPress y rangent leurs données. Ce chapitre installe MariaDB 11.8 sur Debian 13, sécurise le compte root, crée la base et le compte d'une application selon le principe du moindre privilège, ouvre un accès réseau chiffré pour un outil de tableaux de bord, puis montre comment sauvegarder et dépanner.

Installer MariaDB 11.8

Sur srv-glpi, qui accueillera la base de GLPI :

bash
sudo apt install mariadb-server
systemctl status mariadb --no-pager
mariadb --version
# mariadb from 11.8.x-MariaDB, client 15.2 for debian-linux-gnu (x86_64) …

MariaDB 11.8 est une version maintenue à long terme (LTS) par la fondation MariaDB. Les commandes portent le nom mariadb (mariadb, mariadb-dump, mariadb-admin) ; les anciens noms en mysql ne sont plus que des alias de compatibilité, à ne plus utiliser dans tes scripts. Le langage SQL et les commandes CREATE USER ou GRANT sont ceux du cours SQL, écrit pour MySQL : un encadré y signale les rares différences avec MariaDB.

CheminRôle
/etc/mysql/mariadb.conf.d/50-server.cnfConfiguration du serveur : adresse d'écoute (bind-address = 127.0.0.1)
/etc/mysql/mariadb.conf.d/Les fichiers sont lus par ordre alphabétique ; un fichier 60-… que tu ajoutes l'emporte sur 50-server.cnf
/var/lib/mysql/Les données (un dossier par base), propriété du compte système mysql
/run/mysqld/mysqld.sockLe socket Unix des connexions locales
journalctl -u mariadbLe journal d'erreurs du serveur

Par défaut, Debian fait écouter MariaDB sur 127.0.0.1 seulement, port TCP 3306 : la base n'est joignable que depuis la machine elle-même. C'est le bon réglage tant qu'aucune autre machine n'en a besoin.

bash
ss -tlnp | grep 3306
# LISTEN 0  80  127.0.0.1:3306  0.0.0.0:*  users:(("mariadbd",pid=1027,fd=21))

Se connecter en root sans mot de passe

bash
sudo mariadb

Aucun mot de passe n'est demandé, et c'est voulu. Sous Debian, le compte root@localhost de MariaDB utilise l'authentification par socket Unix (unix_socket) : MariaDB demande au système quel utilisateur Linux est à l'autre bout du socket, et n'accepte root que si c'est le root du système. Personne ne peut donc se connecter en root à la base sans être déjà administrateur du serveur, et il n'existe aucun mot de passe de root à voler, à oublier ou à écrire dans un script.

sql
SELECT User, Host, plugin FROM mysql.user;
text
+-------------+-----------+-----------------------+
| User        | Host      | plugin                |
+-------------+-----------+-----------------------+
| mariadb.sys | localhost | mysql_native_password |
| root        | localhost | mysql_native_password |
| mysql       | localhost | mysql_native_password |
+-------------+-----------+-----------------------+

La colonne plugin de la vue mysql.user est trompeuse : interroge plutôt SHOW GRANTS FOR 'root'@'localhost';, qui affiche IDENTIFIED VIA mysql_native_password USING 'invalid' OR unix_socket. Le mot de passe invalid ne correspond à aucun mot de passe possible : seule l'authentification par socket fonctionne. Le compte mysql@localhost a le même fonctionnement, pour le compte système mysql ; mariadb.sys est un compte interne verrouillé.

Sécuriser l'installation

Le script mariadb-secure-installation passe en revue les réglages dangereux d'une installation neuve :

bash
sudo mariadb-secure-installation
QuestionRéponsePourquoi
Enter current password for root (enter for none)Entréeroot n'a pas de mot de passe utilisable
Switch to unix_socket authenticationnC'est déjà le cas sous Debian (le script l'indique : you already have your root account protected)
Change the root password?nGarder l'authentification par socket seule
Remove anonymous users?YUn compte sans nom permettrait à n'importe qui de se connecter
Disallow root login remotely?Yroot ne doit jamais se connecter par le réseau
Remove test database and access to it?YLa base test est accessible à tous les comptes
Reload privilege tables now?YAppliquer tout de suite

Sur une Debian neuve, plusieurs de ces points sont déjà réglés ; le script ne fait alors rien de plus. Lance-le quand même : c'est un geste qu'on attend de toi en recette, et il te protège si quelqu'un a modifié les comptes avant toi.

Créer la base et le compte d'une application

Chaque application a sa base et son compte, qui n'a de droits que sur cette base. Pour GLPI :

sql
-- sudo mariadb
CREATE DATABASE glpi CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'glpi'@'localhost' IDENTIFIED BY 'Mot-De-Passe-Long-Et-Unique';
GRANT ALL PRIVILEGES ON glpi.* TO 'glpi'@'localhost';
-- GLPI lit les fuseaux horaires dans la base système
GRANT SELECT ON mysql.time_zone_name TO 'glpi'@'localhost';

utf8mb4 est le vrai UTF-8 de MariaDB : il stocke tous les caractères, émojis compris, contrairement à l'ancien utf8. Le compte est déclaré @'localhost' : il ne peut se connecter que depuis la machine, par le socket. GRANT ALL PRIVILEGES ON glpi.* lui donne tous les droits sur la base glpi seulement, dont la création et la modification de tables, dont GLPI a besoin pour s'installer et se mettre à jour. Il n'a aucun droit sur les autres bases, ni sur la gestion des comptes (GRANT OPTION), ni sur les fichiers du serveur (FILE).

Vérifie :

bash
mariadb -u glpi -p -e "SHOW GRANTS;"

Le mot de passe du compte applicatif se génère, il ne s'invente pas :

bash
openssl rand -base64 24

Il est écrit une seule fois, dans le fichier de configuration de l'application, lisible seulement par le compte qui l'exécute, et rangé dans le gestionnaire de mots de passe de l'équipe.

Donner le moins de droits possible

ALL PRIVILEGES sur sa base convient à une application qui gère elle-même son schéma. Pour les autres usages, on donne seulement ce qu'il faut :

UsageDroitsExemple
Application qui gère son schéma (installation, mises à jour)ALL PRIVILEGES ON base.*GLPI, Zabbix
Application dont le schéma est créé par l'administrateurSELECT, INSERT, UPDATE, DELETE ON base.*Une application métier développée en interne
Lecture pour des tableaux de bordSELECT sur les seules tables ou vues utilesGrafana qui lit les statistiques des tickets
Sauvegarde logiqueSELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT sur les bases sauvegardéesUn compte de sauvegarde (ou root par socket, en local)

Ouvrir un accès réseau, chiffré et restreint

L'équipe veut afficher dans Grafana, sur srv-journaux (192.168.10.180), le nombre de tickets ouverts par catégorie, lu directement dans la base de GLPI. Trois choses changent : MariaDB doit écouter sur le réseau, un compte doit exister pour cette adresse, et la connexion doit être chiffrée.

1. L'adresse d'écoute. Crée /etc/mysql/mariadb.conf.d/60-sorbier.cnf plutôt que de modifier le fichier de Debian, que les mises à jour peuvent remplacer :

ini
[mariadbd]
bind-address = 192.168.10.184
require_secure_transport = ON

require_secure_transport refuse toute connexion TCP qui n'est pas chiffrée en TLS ; les connexions locales par le socket restent possibles. Depuis la version 11.4, MariaDB active TLS sans configuration : s'il n'a pas de certificat, il en génère un autosigné au démarrage, et le client vérifie par défaut le certificat du serveur, à l'aide du mot de passe du compte (pour les méthodes d'authentification qui le permettent, comme mysql_native_password ou ed25519). Pour un service en production, installe plutôt un certificat signé par l'autorité interne (ssl_cert, ssl_key, ssl_ca dans la même section), obtenu comme au chapitre 6.

bash
sudo systemctl restart mariadb
ss -tlnp | grep 3306
# LISTEN 0  80  192.168.10.184:3306  0.0.0.0:*  users:(("mariadbd",…))

2. Le compte, lié à l'adresse du client, avec les seuls droits utiles.

sql
CREATE USER 'grafana_lecture'@'192.168.10.180'
    IDENTIFIED BY 'Autre-Mot-De-Passe-Long' REQUIRE SSL;
GRANT SELECT ON glpi.glpi_tickets TO 'grafana_lecture'@'192.168.10.180';
GRANT SELECT ON glpi.glpi_itilcategories TO 'grafana_lecture'@'192.168.10.180';
GRANT SELECT ON glpi.glpi_entities TO 'grafana_lecture'@'192.168.10.180';

Le compte ne peut se connecter que depuis srv-journaux, en TLS, et ne lit que trois tables. Il ne voit pas la table glpi_users, qui contient les empreintes des mots de passe des comptes locaux de GLPI. Un GRANT SELECT ON glpi.* aurait été plus simple, et beaucoup trop large.

3. Le pare-feu local n'accepte le port 3306 que de cette adresse (le pare-feu nftables est configuré au chapitre 13) :

text
ip saddr 192.168.10.180 tcp dport 3306 accept

Le test, depuis srv-journaux :

bash
mariadb -h srv-glpi.ad.sorbier.example -u grafana_lecture -p glpi \
  -e "SELECT COUNT(*) FROM glpi_tickets WHERE status < 5;"
mariadb -h srv-glpi.ad.sorbier.example -u grafana_lecture -p -e "\s" | grep -i ssl
# SSL:                    Cipher in use is TLS_AES_256_GCM_SHA384

Les deux serveurs sont dans le même VLAN : ce flux ne traverse pas le pare-feu pfSense, et le filtrage local de srv-glpi est la seule barrière entre eux. Ne l'oublie pas.

Sauvegarder et restaurer une base

mariadb-dump produit une sauvegarde logique : un fichier SQL qui recrée les tables et leurs données. Pour une base InnoDB comme celle de GLPI, l'option --single-transaction prend une image cohérente de la base sans bloquer l'application.

bash
sudo mariadb-dump --single-transaction --routines --triggers --events glpi \
  | gzip > /var/backups/glpi-$(date +%F).sql.gz

La restauration se fait dans une base vide :

bash
sudo mariadb -e "CREATE DATABASE glpi_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
gunzip -c /var/backups/glpi-2026-10-21.sql.gz | sudo mariadb glpi_test

Restaurer dans une base de test, et non dans la base de production, permet de vérifier la sauvegarde sans rien risquer : une sauvegarde qu'on n'a jamais restaurée n'est qu'un espoir. Pour une grosse base, mariadb-backup fait une sauvegarde physique (une copie des fichiers de données, cohérente), plus rapide à restaurer. La planification, la rétention, la copie hors du serveur et le test de restauration sont l'objet du cours Sauvegarde, PCA et PRA ; le chapitre 9 envoie ces fichiers sur un partage NFS.

Dépanner une connexion

MessageCauseCorrection
Access denied for user 'glpi'@'localhost' (using password: YES)Mauvais mot de passe, ou le compte n'existe pas pour cet hôteVérifier avec SELECT User, Host FROM mysql.user; ; changer le mot de passe avec ALTER USER
Can't connect to server on 'srv-glpi.ad.sorbier.example' (111)Rien n'écoute sur cette adresse : bind-address est resté à 127.0.0.1Fichier 60-sorbier.cnf, puis systemctl restart mariadb et ss -tlnp
Délai dépassé, sans réponseUn pare-feu bloque le port 3306nft list ruleset sur le serveur, règles du pare-feu central
Host '192.168.10.180' is not allowed to connect to this MariaDB serverLe serveur répond, mais aucun compte ne correspond à l'adresse du clientCréer le compte pour cette adresse ; ne jamais « corriger » avec '%'
Connections using insecure transport are prohibited while --require_secure_transport=ONLe client a désactivé TLSRetirer l'option --skip-ssl ou --disable-ssl du client
Too many connectionsL'application ouvre plus de connexions que max_connections (151 par défaut)Chercher la fuite de connexions dans l'application ; augmenter la limite en dernier recours
bash
sudo mariadb-admin status
# Uptime: 86400  Threads: 3  Questions: 51234  Slow queries: 0  Opens: 312 …
sudo mariadb -e "SHOW PROCESSLIST;"

Exercices

Exercice 1 sur 3 Les comptes de Zabbix Réussi À revoir

L'équipe installe Zabbix sur srv-journaux avec sa base MariaDB locale, et veut aussi qu'un script de rapport, lancé sur le poste d'administration 192.168.10.209, puisse lire la table hosts de cette base. Écris les instructions SQL pour créer la base zabbix et les deux comptes, et précise les réglages du serveur MariaDB nécessaires pour le second.

Voir la réponseMasquer la réponse de l'exercice 1
sql
CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'zabbix'@'localhost' IDENTIFIED BY 'Mot-De-Passe-Genere-1';
GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost';

CREATE USER 'rapport'@'192.168.10.209' IDENTIFIED BY 'Mot-De-Passe-Genere-2' REQUIRE SSL;
GRANT SELECT ON zabbix.hosts TO 'rapport'@'192.168.10.209';

Le serveur Zabbix se connecte en local : son compte est lié à localhost et a tous les droits sur sa base, qu'il crée et met à jour. Le compte de rapport est lié à l'adresse du poste d'administration, chiffré, et limité à SELECT sur une table. Côté serveur : bind-address = 192.168.10.180 (et require_secure_transport = ON) dans un fichier 60-….cnf, un redémarrage de MariaDB, une règle du pare-feu local qui n'accepte le port 3306 que de 192.168.10.209, et la règle correspondante sur le pare-feu pfSense, puisque ce flux va du VLAN 99 au VLAN 20. La documentation de Zabbix demande l'interclassement utf8mb4_bin, sensible à la casse.

Tu avais trouvé ?

Exercice 2 sur 3 Trois erreurs de connexion Réussi À revoir

Depuis srv-journaux, la commande mariadb -h srv-glpi.ad.sorbier.example -u grafana_lecture -p donne successivement trois messages, après chaque correction. Pour chacun, donne la cause et la correction.

  1. ERROR 2002 (HY000): Can't connect to server on 'srv-glpi.ad.sorbier.example' (111)
  2. ERROR 1130 (HY000): Host '192.168.10.180' is not allowed to connect to this MariaDB server
  3. ERROR 1045 (28000): Access denied for user 'grafana_lecture'@'192.168.10.180' (using password: YES)
Voir la réponseMasquer la réponse de l'exercice 2
  1. Connexion refusée (code 111) : la machine répond, mais rien n'écoute sur 192.168.10.184:3306. MariaDB écoute encore sur 127.0.0.1. Correction : bind-address = 192.168.10.184 dans 60-sorbier.cnf, redémarrage, vérification avec ss -tlnp.
  2. Le serveur répond, mais aucun compte n'existe pour cette adresse. Le compte a peut-être été créé pour localhost ou pour une autre adresse. Correction : CREATE USER 'grafana_lecture'@'192.168.10.180' … (ou RENAME USER si l'hôte était faux).
  3. Le compte existe pour cette adresse, mais le mot de passe est faux. Correction : ALTER USER 'grafana_lecture'@'192.168.10.180' IDENTIFIED BY '…'; puis mettre le même mot de passe dans la source de données de Grafana.

L'ordre des messages suit le chemin de la connexion : le réseau et l'écoute, puis l'hôte du compte, puis le mot de passe.

Tu avais trouvé ?

Exercice 3 sur 3 Restaurer sans casser Réussi À revoir

Un technicien a supprimé par erreur une catégorie de tickets dans GLPI ce matin. La sauvegarde de la nuit est /var/backups/glpi-2026-10-21.sql.gz. Pourquoi ne faut-il pas la restaurer directement dans la base glpi ? Décris la démarche.

Voir la réponseMasquer la réponse de l'exercice 3

Restaurer la sauvegarde de la nuit dans glpi écraserait tout le travail de la journée : tickets créés, suivis, interventions. Une erreur sur une ligne ne justifie pas de perdre des heures de données.

Démarche : restaurer la sauvegarde dans une base temporaire (CREATE DATABASE glpi_restau … puis gunzip -c … | sudo mariadb glpi_restau), retrouver la ligne supprimée (SELECT * FROM glpi_restau.glpi_itilcategories WHERE …), puis la recréer dans la base de production, de préférence depuis l'interface de GLPI ou avec un INSERT … SELECT vérifié, enfin supprimer la base temporaire. On note l'incident et on se demande s'il faut retirer ce droit de suppression au profil du technicien.

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : HTTPS sur Nginx : Let's Encrypt, Certbot et certificats internesRevoir le sommaire du cours