Sécuriser MariaDB et MySQL : les étapes après l'installation

Publié le 18 min de lecture

Après l'installation du paquet, une base de données n'est pas encore sécurisée. Ce guide parcourt mysql_secure_installation, tranche la question unix_socket et montre comment créer un utilisateur dédié par application.

Une base de données fraîchement installée sur un serveur root est rarement aussi vulnérable que le prétendent les anciens tutoriels, et rarement aussi sûre que le laisse croire le gestionnaire de paquets. Entre ces deux extrêmes se trouvent exactement les gestes décrits dans cet article : ce que fait réellement mysql_secure_installation, pourquoi la question unix_socket appelle aujourd'hui une autre réponse qu'en 2015, à quoi ressemble un utilisateur applicatif doté de droits minimaux et comment garder les mots de passe hors de la liste des processus.

Toutes les commandes s'exécutent en tant que root. Si vous travaillez avec un utilisateur normal, préfixez-les par sudo. Les sorties proviennent de Debian 13 et Debian 12 ainsi que d'Ubuntu 24.04 et Ubuntu 22.04.

Point de départ : quel paquet tourne sur quelle distribution

Le premier piège se présente avant même la première mesure de sécurité. Depuis des années, Debian ne fournit plus de paquet propre nommé mysql-server. Le nom n'y existe plus que comme paquet virtuel sans version propre, visible uniquement à travers les dépendances de mariadb-server :

apt-cache policy mysql-server
mysql-server:
  Installed: (none)
  Candidate: (none)
  Version table:

Cette comparaison de versions ne donne donc un résultat que sous Ubuntu, à savoir 8.0.46 aussi bien sur 24.04 que sur 22.04. Sous Debian, on utilise à la place apt-cache showpkg mysql-server, qui rend visible le caractère virtuel du nom.

Sous Debian, la base de données est donc toujours MariaDB. Sous Ubuntu, les deux existent et il faut choisir. Les versions livrées par les distributions actuelles :

Distributionmariadb-servermysql-server
Debian 1311.8nom virtuel uniquement, aucune version
Debian 1210.11nom virtuel uniquement, aucune version
Ubuntu 24.0410.118.0.46
Ubuntu 22.0410.68.0.46

L'installation se fait comme d'habitude :

apt update
apt install -y mariadb-server

Ce n'est pas la version du paquet seule qui dit si vous avez vraiment obtenu la version attendue, mais le serveur en cours d'exécution :

mariadb -e "SELECT @@version, @@version_comment;"

Le deuxième piège concerne le nom du programme. Depuis MariaDB 11.0, les noms compatibles MySQL ne se trouvent plus dans le paquet principal, mais dans mariadb-client-compat et mariadb-server-compat. Sur Debian 13, un mysql --version peut donc soit répondre par un avertissement, soit ne pas exister du tout :

mysql: Deprecated program name. It will be removed in a future release, use '/usr/bin/mariadb' instead
bash: mysql: command not found

Si vous écrivez des scripts censés fonctionner sur les quatre systèmes, utilisez systématiquement mariadb, mariadb-dump et mariadb-secure-installation sous MariaDB. Ces noms existent depuis MariaDB 10.5, donc également sur Ubuntu 22.04.

mysql_secure_installation étape par étape

L'outil porte un nom différent selon le serveur. Sous MariaDB, le nom canonique est mariadb-secure-installation, sous MySQL 8.0 il reste mysql_secure_installation. Sous MariaDB, l'ancien nom subsiste comme lien symbolique sur Debian 12 ainsi que sur Ubuntu 24.04 et 22.04, mais plus sur Debian 13 : là, seul mariadb-secure-installation existe.

Un coup d'œil aux options vaut la peine, car le programme accepte entre autres --defaults-file, --socket et --protocol. Cet aperçu ne figure toutefois que dans le manuel :

man mariadb-secure-installation

Il n'existe en effet pas de --help. Le script n'analyse pas du tout les arguments, il avale l'option inconnue en silence et démarre immédiatement la procédure interactive. S'il manque alors une véritable console, par exemple dans un pipeline ou dans un conteneur (container) sans terminal, il répète indéfiniment la question sur le mot de passe et ne rend jamais la main de lui-même. Appelez-le donc sans argument et depuis un shell interactif :

mariadb-secure-installation

Sur Debian 13, le script fait précéder la procédure d'un avertissement sans ambiguïté :

NOTE: MariaDB is secure by default in Debian. Running this script is useless at best,
and misleading at worst. This script will be removed in a future MariaDB release in Debian.

Debian considère donc cette exécution comme superflue et retirera le script dans une version future, comme l'explique /usr/share/doc/mariadb-server/README.Debian.gz. Les étapes suivantes valent malgré tout la peine, car elles montrent ce qui est vérifié et pourquoi il n'y a presque plus rien à changer sur un système récent.

La procédure commence par la question du mot de passe de root. La formulation dépend de la version du script :

Enter current password for root (enter for none):

Les versions plus récentes demandent plutôt :

Enter root user password or leave blank:

Dans les deux cas, il s'agit de la même chose. Sur une installation neuve, il n'y a pas de mot de passe, vous appuyez simplement sur Entrée.

Viennent ensuite les véritables décisions. L'ordre et la formulation diffèrent entre MariaDB et MySQL, mais il s'agit sur le fond des cinq mêmes points.

La question unix_socket

Sous MariaDB, la question suivante apparaît :

Switch to unix_socket authentication [Y/n]

Cette question sème la confusion, car elle est déjà tranchée sur tous les systèmes traités ici. Depuis MariaDB 10.4, root@localhost est protégé d'origine par le plugin unix_socket, et cela vaut pour 10.6 sur Ubuntu 22.04 comme pour 11.8 sur Debian 13. Sous MySQL 8.0, l'équivalent s'appelle auth_socket, et l'assistant le dit d'ailleurs ouvertement :

Skipping password set for root as authentication with auth_socket is used by default.

Concrètement, cela signifie ceci : si vous êtes connecté en tant qu'utilisateur système root, vous entrez dans la base avec mariadb sans mot de passe. Si vous ne l'êtes pas, vous n'entrez pas du tout, même avec le bon mot de passe. Ce n'est pas une lacune, c'est la variante la plus solide. Il n'existe aucun mot de passe susceptible de fuiter par une sauvegarde, un fichier de configuration ou une capture d'écran. La réponse à la question est donc oui, on conserve, et un mot de passe root supplémentaire est superflu sur un serveur applicatif isolé.

L'état ne se vérifie que sur la vraie table. La requête évidente SELECT user, host, plugin FROM mysql.user induit en effet en erreur : pour root, elle affiche la valeur mysql_native_password alors que c'est en réalité unix_socket qui s'applique. Depuis MariaDB 10.4, mysql.user n'est plus qu'une vue sur mysql.global_priv, et cette vue ne connaît qu'une seule méthode d'authentification par compte. Qui s'y fie croit à tort que le serveur s'authentifie par mot de passe. La règle complète se trouve dans le champ JSON Priv de la vraie table :

mariadb -e "SELECT User, Host, JSON_DETAILED(Priv) FROM mysql.global_priv;"

Pour root sur localhost, on y lit sous MariaDB, en substance :

{"plugin":"mysql_native_password","authentication_string":"invalid","auth_or":[{},{"plugin":"unix_socket"}]}

La première entrée est la méthode par mot de passe, comparée au hash inutilisable de la chaîne invalid, que personne ne peut reproduire. La deuxième entrée, sous auth_or, est l'authentification par socket réellement active. Voici une requête plus compacte pour interroger les deux :

mariadb -e "SELECT User, Host, JSON_VALUE(Priv,'$.plugin') AS plugin, JSON_QUERY(Priv,'$.auth_or') AS auth_or FROM mysql.global_priv;"

Pour root et localhost, on attend un unix_socket, soit dans la colonne plugin, soit sous auth_or. Si seule une méthode par mot de passe y figure et que rien n'apparaît sous auth_or, le compte fonctionne uniquement par mot de passe. Sous MySQL 8.0, mysql.global_priv n'existe pas, mysql.user y est une vraie table et la colonne plugin doit indiquer auth_socket. Sur la vue MariaDB, vous pouvez d'ailleurs toujours lire, mais plus écrire.

On ne bascule que si un outil exige impérativement un mot de passe, par exemple un monitoring qui ne tourne pas en root. Il est alors plus judicieux de créer un second utilisateur d'administration plutôt que de détourner root. À partir de MariaDB 11.6, donc aussi en 11.8 sur Debian 13, un compte peut en plus être lié à un utilisateur système précis :

CREATE USER 'dbadmin'@'localhost' IDENTIFIED VIA unix_socket AS 'deploy';

L'utilisateur système deploy peut ainsi se connecter comme utilisateur de base de données dbadmin, sans que les noms doivent correspondre. Sur Debian 12 et sur les versions Ubuntu, la chaîne qui suit AS est encore ignorée, l'utilisateur système et l'utilisateur de base de données doivent y porter le même nom.

Les quatre questions restantes

Le reste ne prête pas à discussion et se répond systématiquement par oui : supprimer les utilisateurs anonymes, interdire la connexion root à distance, supprimer la base test ainsi que ses droits, recharger les tables de droits. Sur un Debian ou un Ubuntu récent, les utilisateurs anonymes et la base de test ne sont de toute façon généralement pas créés, le script signale alors simplement qu'il n'y avait rien à faire.

Sous MySQL 8.0, une question s'ajoute, que MariaDB ne connaît pas :

Would you like to setup VALIDATE PASSWORD component?

Ce composant impose des exigences minimales à tous les mots de passe définis par la suite. Il est utile quand plusieurs personnes créent des utilisateurs. Il devient pénible quand un script de provisionnement génère des mots de passe aléatoires qui, par accident, ne contiennent aucun caractère spécial. Le script s'interrompt alors avec :

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

Si vous l'activez, réglez d'abord votre générateur de mots de passe en conséquence. Le niveau par défaut est MEDIUM et exige au moins huit caractères, des majuscules et des minuscules, un chiffre et un caractère spécial.

En cas de problème : revenir dans la base de données

La façon la plus courante de s'enfermer dehors est le passage bien intentionné de unix_socket à un mot de passe qui finit par se perdre. Ou l'inverse : un vieux script recrée /etc/mysql/debian.cnf et, soudain, plus rien ne concorde. Les messages d'erreur que l'on cherche alors sont les suivants :

ERROR 1698 (28000): Access denied for user 'root'@'localhost'
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
ERROR 1524 (HY000): Plugin 'unix_socket' is not loaded

L'erreur 1698 signifie que le compte attend unix_socket, mais que vous n'êtes pas l'utilisateur système correspondant. Un sudo devant la commande suffit souvent à régler le problème. L'erreur 1045 signifie qu'un mot de passe est attendu et que le vôtre est incorrect.

Si vous n'arrivez plus du tout à entrer, démarrez le serveur sans vérification des droits. Sous MariaDB, cela passe proprement par la variable d'environnement que l'unité systemd fournie prend en compte, sans toucher au moindre fichier de paquet :

systemctl stop mariadb
systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"
systemctl start mariadb

Connectez-vous maintenant avec mariadb -u root et remettez l'état en ordre. Le FLUSH PRIVILEGES préalable est important, car ALTER USER échoue tant que les tables de droits ne sont pas chargées :

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket;

Faites impérativement le ménage ensuite, sinon le serveur démarrera sans protection après chaque redémarrage :

systemctl stop mariadb
systemctl unset-environment MYSQLD_OPTS
systemctl start mariadb

Sous MySQL 8.0 sur Ubuntu, cette méthode ne fonctionne pas, parce que l'unité ne prend en compte aucune variable de ce type et parce que ALTER USER présente des pièges supplémentaires avec --skip-grant-tables. On y utilise un fichier d'initialisation. Il doit se trouver dans un répertoire qu'AppArmor autorise au processus serveur, faute de quoi le démarrage échoue avec Can't open file. /var/lib/mysql-files est autorisé, /tmp ne l'est pas :

systemctl stop mysql
echo "ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket;" > /var/lib/mysql-files/reset.sql
chown mysql:mysql /var/lib/mysql-files/reset.sql
systemctl edit mysql

Dans l'éditeur, saisissez une surcharge de la commande de démarrage, la première ligne vide étant nécessaire pour effacer la valeur d'origine :

[Service]
ExecStart=
ExecStart=/usr/sbin/mysqld --init-file=/var/lib/mysql-files/reset.sql

Après un systemctl daemon-reload et un démarrage, le compte est réinitialisé. Supprimez ensuite la surcharge avec systemctl revert mysql et effacez le fichier. Si vous exploitez vos bases de données sur des systèmes séparés, vous trouverez des indications complémentaires sur la sécurisation de l'accès dans l'article Sécuriser un serveur SSH.

Un utilisateur dédié par application plutôt que root

L'étape la plus efficace n'apparaît dans aucun assistant. Les applications ne doivent pas se connecter en tant que root, et elles n'ont pas non plus besoin d'un GRANT ALL. Une application web typique lit et écrit des lignes, elle ne crée pas de bases de données et ne lit aucun fichier sur le serveur.

CREATE DATABASE shopdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'shopapp'@'localhost' IDENTIFIED BY 'IciUnLongMotDePasseAleatoire';
GRANT SELECT, INSERT, UPDATE, DELETE ON shopdb.* TO 'shopapp'@'localhost';

Trois points comptent ici. Premièrement, le point dans shopdb.* au lieu de *.* : les droits sur *.* sont des droits globaux et s'appliquent aussi à mysql et à information_schema. Deuxièmement, la mention @'localhost' au lieu de @'%' : le compte n'est ainsi utilisable qu'en local, même si le port venait à être ouvert plus tard. Troisièmement, WITH GRANT OPTION est absent, car un compte capable de transmettre des droits est de fait un administrateur.

Les modifications de schéma passent alors par un second compte, utilisé uniquement lors du déploiement :

CREATE USER 'shopmigrate'@'localhost' IDENTIFIED BY 'UnAutreLongMotDePasseAleatoire';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, REFERENCES ON shopdb.* TO 'shopmigrate'@'localhost';

Cela ressemble à du travail supplémentaire, et c'est précisément ce qui transforme une injection SQL dans l'application en fuite de données agaçante plutôt qu'en perte totale. Un compte sans DROP ne peut supprimer aucune table.

Le contrôle ne porte pas sur la formulation du GRANT, mais sur le résultat :

SHOW GRANTS FOR 'shopapp'@'localhost';

On attend exactement deux lignes : un GRANT USAGE ON *.*, qui représente uniquement le droit de se connecter et n'implique aucun accès aux données, et la ligne portant les quatre droits sur shopdb.*. Si ALL PRIVILEGES ON *.* y apparaît, le point était au mauvais endroit. Le second test, plus parlant, consiste à se connecter avec le nouveau compte et à lancer un SHOW DATABASES;. Seules information_schema et shopdb doivent être visibles.

Une erreur fréquente lors de la création :

ERROR 1396 (HY000): Operation CREATE USER failed for 'shopapp'@'localhost'

Cela signifie presque toujours que le compte existe déjà, souvent comme vestige d'une tentative précédente. DROP USER 'shopapp'@'localhost'; et on recommence depuis le début.

bind-address : où la base de données écoute réellement

Sur les quatre distributions, la base de données n'écoute que sur 127.0.0.1 après l'installation du paquet. La ligne se trouve, pour MariaDB, dans /etc/mysql/mariadb.conf.d/50-server.cnf et, pour MySQL 8.0, dans /etc/mysql/mysql.conf.d/mysqld.cnf. Vérifiez au lieu de supposer :

grep -R "bind-address" /etc/mysql/

Sous MySQL 8.0, une deuxième ligne passe volontiers inaperçue : mysqlx-bind-address pilote le protocole X sur le port 33060. Si vous ne modifiez que bind-address, vous n'ouvrez parfois que la moitié de l'accès, ou vous laissez le second port ouvert.

La vérification la plus fiable ne passe pas par le fichier de configuration, mais par le noyau :

ss -lntp
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=712,fd=22))

Si 0.0.0.0:3306 ou *:3306 y figure, le service est joignable depuis le réseau. En complément, le serveur livre son propre point de vue :

mariadb -e "SELECT @@bind_address, @@port, @@skip_networking;"

Deux pièges sont répandus ici. Le premier : les fichiers de mariadb.conf.d sont lus par ordre alphabétique, et c'est la dernière valeur lue qui l'emporte. Si vous écrivez votre modification dans un fichier séparé, nommez-le donc 99-eigene.cnf et non 10-eigene.cnf. C'est exactement là que butent la plupart des rapports dans lesquels MariaDB ignorerait bind-address. L'avantage d'un fichier séparé : les mises à jour de paquets ne demandent pas de résoudre un conflit, puisque le fichier fourni reste intact.

Le second piège : si vous n'avez pas du tout besoin de l'accès réseau, allez un cran plus loin que bind-address et posez skip-networking. Il n'existe alors plus aucun port TCP, seulement le socket Unix. C'est le bon réglage pour le cas standard, à savoir application web et base de données sur le même serveur, mais cela coûte des nerfs quand une application a 127.0.0.1 dans sa configuration au lieu de localhost : avec 127.0.0.1, les bibliothèques clientes imposent TCP.

Un accès depuis l'extérieur seulement en cas de réelle nécessité

Un port de base de données exposé sur le réseau ouvert est trouvé en quelques heures et testé en continu. La meilleure réponse à la question de l'accès externe consiste donc à l'éviter. Pour une maintenance occasionnelle, un tunnel SSH suffit, qui place sur votre propre machine un port local sur le socket de base de données de la machine distante. L'outil de base de données se connecte alors sur 127.0.0.1, sans que le serveur ouvre quoi que ce soit sur le réseau.

Pour des connexions permanentes entre plusieurs serveurs, un tunnel WireGuard est la solution propre. La base de données ne se lie alors qu'à l'adresse du tunnel, pas à l'adresse IP publique.

S'il faut malgré tout un port ouvert, quatre mesures se combinent. Le serveur se lie à exactement une adresse interne. Le pare-feu ne laisse passer que l'adresse source connue. Le compte de base de données est lié à cette même adresse, donc 'shopapp'@'10.0.0.5' et jamais 'shopapp'@'%'. Et la connexion est imposée en mode chiffré :

ALTER USER 'shopapp'@'10.0.0.5' REQUIRE SSL;

Lors des tests depuis l'extérieur, on rencontre deux erreurs souvent confondues. La première signifie que personne ne répond, donc pare-feu ou bind-address :

ERROR 2003 (HY000): Can't connect to MySQL server on '203.0.113.10:3306' (110)

La seconde signifie que le serveur répond et refuse délibérément la connexion, autrement dit il manque le compte correspondant à cette provenance :

ERROR 1130 (HY000): Host '203.0.113.55' is not allowed to connect to this MariaDB server

En local, le grand classique est que le service ne tourne tout simplement pas :

ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)

Pas de mots de passe sur la ligne de commande

L'appel mariadb -u shopapp -pGeheim123 fonctionne et reste malgré tout une faute. Le serveur le dit lui-même :

Warning: Using a password on the command line interface can be insecure.

Deux raisons expliquent cela. Premièrement, la ligne atterrit dans l'historique du shell. Deuxièmement, sur un système standard, la ligne de commande d'un processus est visible via ps pour tout utilisateur connecté. Sur un serveur hébergeant plusieurs clients ou plusieurs services, c'est une récolte de mots de passe sans le moindre effort.

La bonne méthode pour un être humain est -p sans suffixe. La question est alors posée de façon interactive et rien ne reste dans l'historique :

mariadb -u shopapp -p shopdb

La bonne méthode pour les scripts et les tâches cron est un fichier d'options aux droits restreints. Création avec le bon mode en une seule étape :

install -m 600 /dev/null /root/.my.cnf

Contenu :

[client]
user=backup
password=IciUnLongMotDePasseAleatoire

Chaque client trouve ensuite tout seul les identifiants. Pour des tâches distinctes, créez plusieurs fichiers et pointez explicitement dessus. Une règle s'applique alors, sur laquelle beaucoup butent : --defaults-extra-file et --defaults-file doivent être la première option de l'appel, sinon elles sont ignorées sans le moindre message.

mariadb-dump --defaults-extra-file=/root/.my-backup.cnf --single-transaction shopdb

La variable d'environnement MYSQL_PWD n'est pas une solution. Elle figure dans /proc et se trouve donc à peu près aussi exposée que la ligne de commande. Sous MySQL 8.0, il existe en plus mysql_config_editor, qui écrit un fichier ~/.mylogin.cnf. Le contenu est masqué, mais pas chiffré, et MariaDB ne connaît pas cet outil. Dans les environnements mixtes, le simple fichier d'options en mode 600 reste le choix le plus fiable.

Un dernier point concerne les sauvegardes. Un dump contient tout ce que voit l'application, et un compte de sauvegarde n'a besoin d'aucun droit d'écriture pour cela. Pour mariadb-dump avec --single-transaction, ceci suffit en règle générale :

GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES ON shopdb.* TO 'backup'@'localhost';
GRANT PROCESS ON *.* TO 'backup'@'localhost';

Recette : comment savoir que tout est en place

Une commande qui s'exécute sans erreur ne prouve rien. Ces six tests, eux, prouvent quelque chose :

  1. Le compte root utilise l'authentification par socket : mariadb -e "SELECT User, Host, JSON_VALUE(Priv,'$.plugin') AS plugin, JSON_QUERY(Priv,'$.auth_or') AS auth_or FROM mysql.global_priv;" affiche pour root un unix_socket, soit dans la colonne plugin, soit sous auth_or. La vue mysql.user ne convient pas pour cela, elle ne restitue que la première méthode. Sous MySQL 8.0, c'est au contraire la colonne plugin de mysql.user qui fait foi, et auth_socket doit y figurer.
  2. Il n'existe aucun compte anonyme : mariadb -e "SELECT user, host FROM mysql.user WHERE user = '';" renvoie un jeu de résultats vide.
  3. La base de test a disparu : mariadb -e "SHOW DATABASES LIKE 'test';" ne renvoie rien.
  4. Le port est fermé : ss -lntp n'affiche pour 3306 soit rien du tout, soit uniquement 127.0.0.1.
  5. Le compte applicatif est restreint : une connexion avec ce compte n'affiche, sur SHOW DATABASES;, que sa propre base de données, et un DROP TABLE échoue.
  6. Aucun mot de passe ne circule en clair : grep -rs "password" /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/ ne trouve rien, pas davantage que crontab -l pour root et un coup d'œil dans /var/spool/cron/crontabs/, et les fichiers d'options sont en mode 600. L'option -s fait partie de la commande, car un répertoire manquant interromprait sinon l'appel avec le code de sortie 2 : sur Debian 13, /etc/cron.d n'existe pas après une installation purement base de données, aucun paquet cron n'y étant encore installé.

Si vous traitez ces six points sur un nouveau serveur, vous avez déjà écarté la grande majorité des attaques visant les bases de données, sans installer un seul logiciel supplémentaire. Le reste tient à la discipline des mises à jour et à une sauvegarde fonctionnelle dont la restauration a été répétée au moins une fois.

Questions fréquentes

Ai-je encore besoin d'un mot de passe root sous MariaDB ?
Sur Debian 12 et 13 ainsi que sur Ubuntu 22.04 et 24.04, non. Le compte root@localhost y utilise par défaut le plugin unix_socket, la connexion repose donc sur l'identité de l'utilisateur système. Un mot de passe supplémentaire n'augmente pas la sécurité, il crée un secret de plus, susceptible d'être perdu ou de fuiter. Uniquement si un outil exige impérativement une connexion par mot de passe, créez un compte dédié pour lui plutôt que de modifier root.
Pourquoi mon Debian dit-il que le paquet mysql-server n'existe pas ?
Depuis plusieurs versions, Debian ne livre plus de paquet mysql-server propre. Ni sur Debian 12 ni sur Debian 13 il n'existe de version installable : apt-cache policy mysql-server y indique Candidate: (none) et une Version table vide, car le nom n'existe plus que virtuellement, à travers mariadb-server. C'est apt-cache showpkg mysql-server qui le rend visible. La commande d'installation est apt install -y mariadb-server. Sur Ubuntu 22.04 et 24.04, les deux sont disponibles, MySQL en version 8.0.46 et MariaDB en 10.6 ou 10.11 selon la distribution.
Comment revenir dans la base de données quand je me suis enfermé dehors ?
Sous MariaDB, arrêtez le service, positionnez la variable MYSQLD_OPTS sur --skip-grant-tables --skip-networking avec systemctl set-environment, puis redémarrez. Après la connexion, un FLUSH PRIVILEGES est d'abord nécessaire, le compte se réinitialise ensuite avec ALTER USER. Retirez enfin la variable avec systemctl unset-environment. Sous MySQL 8.0, cela ne fonctionne pas, on y passe par un fichier d'initialisation via --init-file, qui doit se trouver dans /var/lib/mysql-files à cause d'AppArmor.
Que signifie ERROR 1698 par rapport à ERROR 1045 ?
ERROR 1698 (28000) signifie que le compte attend une authentification par socket et que l'utilisateur système appelant ne correspond pas. Un sudo devant la commande suffit généralement. ERROR 1045 (28000) avec la mention (using password: YES) signifie au contraire qu'une connexion par mot de passe a été tentée et que le mot de passe est incorrect. Les deux erreurs ont donc des causes et des solutions totalement différentes.
bind-address = 127.0.0.1 suffit-il à sécuriser la base de données ?
C'est l'étape la plus importante, mais pas la seule. Sous MySQL 8.0, il existe en plus mysqlx-bind-address pour le port 33060, qui doit être défini séparément. Par ailleurs, dans /etc/mysql/mariadb.conf.d, c'est le dernier fichier lu qui l'emporte, vos propres modifications doivent donc aller dans un fichier à numéro élevé, par exemple 99-eigene.cnf. Le résultat se vérifie toujours avec ss -lntp, jamais dans le fichier de configuration.
Pourquoi l'application ne doit-elle pas accéder à la base de données en tant que root ?
Parce que la moindre faille dans l'application donnerait alors un accès complet à toutes les bases de données, tables de droits comprises. Un compte disposant de GRANT SELECT, INSERT, UPDATE, DELETE ON mabase.* ne peut supprimer aucune table, lire aucune base étrangère ni attribuer de droits. Les modifications de schéma passent par un compte distinct, utilisé uniquement lors du déploiement.
Comment transmettre un mot de passe de base de données à une tâche cron en toute sécurité ?
Via un fichier d'options en mode 600, créé par exemple avec install -m 600 /dev/null /root/.my.cnf et contenant une section [client] avec user et password. L'appel y renvoie ensuite avec --defaults-extra-file, impérativement en première option, sinon l'argument est ignoré sans avertissement. Les mots de passe placés directement derrière -p sur la ligne de commande sont visibles par tout utilisateur via ps, et MYSQL_PWD est tout aussi consultable via /proc.

MariaDB MySQL Base de données Sécurité serveur Debian Ubuntu Administration Linux