Sauvegarder chaque jour vos bases MySQL sous Debian, Ubuntu et Linux
Un petit script et une tâche cron suffisent pour sauvegarder chaque nuit toutes vos bases MySQL et MariaDB sous forme compressée. Y compris les points où Debian et Ubuntu divergent et où une sauvegarde échoue en silence.
Vous utilisez Debian, Ubuntu ou une autre distribution Linux sur votre vServer, votre serveur root ou votre serveur dédié, et vous souhaitez sauvegarder automatiquement toutes vos bases de données MySQL et MariaDB chaque jour ? Vous êtes au bon endroit. Dans ce guide, vous mettez en place un script de sauvegarde qui exporte chaque nuit toutes les bases dans un fichier SQL compressé et supprime automatiquement les anciennes sauvegardes.
La procédure est identique sur toutes les distributions et fonctionne aussi bien sous Debian et Ubuntu que sous AlmaLinux, Rocky Linux et RHEL. Les différences ne se cachent pas dans le script, mais dans le serveur de base de données qui tourne chez vous et dans la façon dont il gère la connexion. Une section entière y est consacrée plus bas : Debian face à Ubuntu.
Prérequis
Il vous faut un accès SSH avec les droits root ainsi qu'un serveur MySQL ou MariaDB installé. Nous recommandons les versions actuelles des distributions : Debian 13 « Trixie » et Debian 12 « Bookworm », Ubuntu 24.04 LTS « Noble Numbat » et Ubuntu 22.04 LTS « Jammy Jellyfish », ainsi qu'AlmaLinux et Rocky Linux en versions 9 et 10. Les systèmes plus anciens ne devraient plus servir en production : Debian 10 a atteint sa fin de support en juin 2024, Ubuntu 20.04 LTS en mai 2025, et CentOS 7 ne reçoit lui non plus de mises à jour de sécurité régulières.
Commencez par mettre le système à jour et installez l'éditeur de texte Nano s'il manque encore.
Pour Debian et Ubuntu :
apt update && apt upgrade -y
apt install nano -y
Pour AlmaLinux, Rocky Linux et RHEL :
dnf update -y
dnf install nano -y
Sur les systèmes récents de la famille RHEL, dnf succède à yum. L'ancienne commande y fonctionne encore le plus souvent comme un lien, mais c'est bien dnf qu'il faut employer.
Prévoyez également assez d'espace de stockage. Une semaine de sauvegardes compressées atteint vite plusieurs gigaoctets selon la taille des bases. Vous vérifiez l'espace libre avec df -h.
Enregistrer les identifiants en toute sécurité
Le mot de passe n'a rien à faire directement dans l'appel de mysqldump, car les lignes de commande sont visibles par tous les utilisateurs du système via ps. Créez plutôt un fichier d'identifiants que seul root peut lire :
nano /root/.my.cnf
Contenu du fichier :
[client]
user=root
password=VOTRE_MOT_DE_PASSE_BASE_DE_DONNEES
Ajustez ensuite les droits pour que seul root y ait accès :
chmod 600 /root/.my.cnf
Quand il n'existe aucun mot de passe root
Sous Debian et Ubuntu, le compte de base de données root n'est en règle générale pas protégé par un mot de passe, mais par l'identité de l'utilisateur système. MariaDB appelle ce mécanisme unix_socket, MySQL l'appelle auth_socket. Aucun mot de passe n'existe alors, et une entrée dans le fichier d'identifiants reste sans effet. Cette requête vous dit si c'est votre cas :
mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user='root';"
Si vous y lisez unix_socket ou auth_socket, deux possibilités s'offrent à vous : soit vous exécutez le script en tant qu'utilisateur système root et vous vous passez entièrement du fichier d'identifiants, soit vous créez un utilisateur de sauvegarde dédié. La seconde solution est la meilleure, car elle se passe des pleins droits du compte root :
CREATE USER 'kh_backup'@'localhost' IDENTIFIED BY 'VOTRE_MOT_DE_PASSE_SAUVEGARDE';
GRANT SELECT, SHOW VIEW, EVENT, TRIGGER, LOCK TABLES, RELOAD, PROCESS ON *.* TO 'kh_backup'@'localhost';
FLUSH PRIVILEGES;
Dans le fichier d'identifiants, vous indiquez alors user=kh_backup. Les droits sont volontairement réduits : lecture, vues, events, triggers et, en solution de repli, le verrouillage des tables qui n'utilisent pas InnoDB. RELOAD et PROCESS ne peuvent être attribués que globalement, d'où ON *.*. MySQL 8 a besoin de PROCESS pour lire au passage les informations de tablespace. Si vous préférez ne pas l'accorder, ajoutez plutôt --no-tablespaces dans le script. Et si vous n'arrivez plus du tout à vous connecter, l'article Réinitialiser le mot de passe root de MySQL et MariaDB vous aidera.
Créer le script de sauvegarde
Nous créons maintenant un script Bash qui se charge de l'export et supprime les anciennes sauvegardes. Dans notre exemple, il s'appelle mysql_export_all.sh et se trouve dans le répertoire /opt/mysqlbackups :
mkdir -p /opt/mysqlbackups
nano /opt/mysqlbackups/mysql_export_all.sh
Dans ce script, vous écrivez le contenu suivant :
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/mysqlbackups"
KEEP_DAYS=7
DATE=$(date +%Y-%m-%d-%H-%M)
mkdir -p "$BACKUP_DIR"
mysqldump --defaults-extra-file=/root/.my.cnf --all-databases --single-transaction --routines --events | gzip > "$BACKUP_DIR/alldbs_$DATE.sql.gz"
find "$BACKUP_DIR" -type f -name "alldbs_*.sql.gz" -mtime +$KEEP_DAYS -delete
Les options les plus importantes en un coup d'œil :
--defaults-extra-filelit l'utilisateur et le mot de passe dans le fichier que vous venez de créer. Cette option doit figurer en première position.--single-transactionproduit un état cohérent des tables InnoDB, sans verrouiller la base.--routineset--eventsintègrent les procédures stockées et les events planifiés dans la sauvegarde. Les triggers,mysqldumples enregistre de lui-même.gzipcompresse l'export et économise ainsi beaucoup d'espace de stockage.- La commande
findne supprime que les fichiers de sauvegarde plus vieux que sept jours. La variableKEEP_DAYSvous permet d'ajuster la durée de conservation.
La ligne set -euo pipefail compte davantage qu'il n'y paraît. Sans pipefail, le shell n'évalue que le code de retour de gzip, et celui-ci vaut zéro même quand mysqldump s'est interrompu avant. Vous vous retrouveriez avec une archive techniquement irréprochable au contenu incomplet, et personne ne s'en apercevrait.
Le serveur de base de données qui tourne chez vous dépend de la distribution. Debian ne contient aucun paquet mysql-server et mise entièrement sur MariaDB, alors qu'Ubuntu propose les deux. Le script fonctionne sans la moindre modification dans tous les cas :
| Système | mysql-server | mariadb-server |
|---|---|---|
| Debian 13 | absent | 11.8 |
| Debian 12 | absent | 10.11 |
| Ubuntu 24.04 LTS | 8.0 | 10.11 |
| Ubuntu 22.04 LTS | 8.0 | 10.6 |
Rendre le script exécutable et le tester
Rendez le script exécutable :
chmod +x /opt/mysqlbackups/mysql_export_all.sh
Lancez-le une fois à la main et vérifiez le résultat avant de l'automatiser :
/opt/mysqlbackups/mysql_export_all.sh
ls -lh /opt/mysqlbackups/
Le fichier produit doit faire nettement plus de zéro octet. Mais la fin du fichier est plus parlante que son début. Vérifiez donc que l'archive est intacte et que l'export est réellement allé jusqu'au bout :
gzip -t /opt/mysqlbackups/alldbs_*.sql.gz
zcat /opt/mysqlbackups/alldbs_*.sql.gz | tail -n 1
La dernière ligne d'un export complet commence par -- Dump completed on. Si elle manque, l'export a été interrompu et le fichier ne vaut rien comme sauvegarde, même s'il pèse plusieurs centaines de mégaoctets. Cette seule ligne est le test fiable le plus rapide dont vous disposez.
Mettre en place la tâche cron de la sauvegarde quotidienne
Ouvrez l'éditeur de crontab :
export VISUAL=nano; crontab -e
Pour une sauvegarde quotidienne à 5 heures du matin, ajoutez la ligne suivante :
0 5 * * * /opt/mysqlbackups/mysql_export_all.sh >> /var/log/mysql-backup.log 2>&1
La sortie atterrit ainsi dans un fichier journal, ce qui vous permet de retracer les erreurs plus tard. Vous vérifiez avec crontab -l que la tâche cron a bien été enregistrée. Elle doit se trouver dans la crontab de root. Sur beaucoup d'images Ubuntu, la connexion en tant que root est désactivée, et la commande y devient sudo crontab -e. En simple utilisateur, vous créeriez sinon votre propre crontab, et le script échouerait plus tard sur le fichier d'identifiants placé sous /root.
Sur les installations minimales de la famille RHEL, le service cron manque parfois. Vous l'installez et l'activez ainsi :
dnf install cronie -y
systemctl enable --now crond
À partir de maintenant, toutes les bases sont exportées chaque nuit à 5 heures, et les sauvegardes de plus de sept jours disparaissent automatiquement. Pour en savoir plus sur les plannings et les pièges classiques, voyez Mettre en place une tâche cron sous Linux.
Restaurer une sauvegarde
Une sauvegarde ne vaut quelque chose que si vous savez aussi la restaurer. Testez donc la restauration une fois de façon délibérée, de préférence sur un système de test :
zcat /opt/mysqlbackups/alldbs_2026-07-26-05-00.sql.gz | mysql --defaults-extra-file=/root/.my.cnf
Si vous ne voulez récupérer qu'une seule base, décompressez d'abord la sauvegarde et extrayez-en la section correspondante, ou sauvegardez en plus certaines bases séparément avec mysqldump --databases mabase. Il est plus pratique d'écrire tout de suite un fichier par base. Pour cela, remplacez dans le script la ligne mysqldump par cette boucle :
for DB in $(mysql --defaults-extra-file=/root/.my.cnf -N -B -e "SHOW DATABASES;" | grep -Ev '^(information_schema|performance_schema|sys)$'); do
mysqldump --defaults-extra-file=/root/.my.cnf --single-transaction --routines --events "$DB" | gzip > "$BACKUP_DIR/${DB}_$DATE.sql.gz"
done
Les trois bases exclues sont des vues sur l'état interne du serveur et ne se restaurent pas utilement. Adaptez également le motif de recherche de la commande find, sinon elle ne fera plus le ménage dans les nouveaux noms de fichiers. Pour un déménagement complet vers un autre serveur, Migrer WordPress vers un nouveau serveur déroule la marche à suivre sur un exemple concret.
Stocker les sauvegardes en dehors du serveur
Des sauvegardes qui se trouvent uniquement sur le même serveur n'aident en rien lors d'une perte de données de tout le système. Transférez donc les fichiers vers une seconde destination, par exemple avec rsync ou scp vers un autre serveur ou vers un espace de sauvegarde :
rsync -avz /opt/mysqlbackups/ utilisateur@cible-sauvegarde:/chemin/vers/sauvegarde/
Ajoutez simplement cette commande à la fin de votre script, et le transfert suivra automatiquement. Pour que cela fonctionne sans question dans la tâche cron, root a besoin d'une clé SSH sans passphrase dont la partie publique est déposée sur le système cible. La création de cette clé est décrite dans Se connecter au serveur en SSH.
Différences entre Debian et Ubuntu
Les deux systèmes utilisent apt, tous deux rangent la configuration sous /etc/mysql/, et le script ci-dessus tourne sur les deux sans modification. Il reste malgré tout six points de divergence, et chacun d'eux peut faire échouer une sauvegarde en silence :
| Sujet | Debian | Ubuntu |
|---|---|---|
| Serveur de base de données | MariaDB uniquement | MySQL 8.0 ou MariaDB |
| Paquet client | mariadb-client | mysql-client-8.0 ou mariadb-client |
| Outil de sauvegarde | mariadb-dump, mysqldump comme lien | avec MySQL, uniquement mysqldump |
| Connexion de root | unix_socket | auth_socket avec le MySQL du paquet |
| Compte de maintenance | plus créé depuis MariaDB 10.4 | debian-sys-maint dans /etc/mysql/debian.cnf |
| Journal d'erreurs | journal systemd, journalctl -u mariadb | avec MySQL, /var/log/mysql/error.log |
Noms de paquets et outils
Si vous sauvegardez la base depuis une autre machine, vous n'y avez besoin que du paquet client. Sous Debian il s'appelle mariadb-client, sous Ubuntu avec MySQL 8 il s'appelle mysql-client-8.0. Pour un script censé tourner sur les deux systèmes, il existe le métapaquet default-mysql-client : il pointe vers le client MariaDB sous Debian et vers le client MySQL sous Ubuntu.
Depuis MariaDB 10.5, les outils portent en plus un nom préfixé par mariadb-, et depuis MariaDB 11 ce nom est le nom réel, mysqldump n'étant plus qu'un lien vers lui. Les deux appels y fonctionnent. Sur un système Ubuntu avec MySQL 8, en revanche, seul mysqldump existe, et un script utilisant mariadb-dump s'y termine par command not found. Pour les scripts destinés à tourner dans les deux mondes, mysqldump est donc le bon appel.
Compte de maintenance et authentification
Sous Ubuntu, le paquet mysql-server crée toujours le compte de maintenance debian-sys-maint et écrit ses identifiants dans /etc/mysql/debian.cnf. Ce fichier n'est lisible que par root et s'utilise directement pour une sauvegarde, sans autre préparation :
mysqldump --defaults-file=/etc/mysql/debian.cnf --all-databases --single-transaction --routines --events | gzip > /opt/mysqlbackups/alldbs.sql.gz
Sous Debian avec MariaDB à partir de la version 10.4, ce compte n'est plus créé. Le fichier existe encore le plus souvent, mais il ne renvoie en général qu'à root via le socket. Ne partez donc pas du principe qu'un script qui passe par ce fichier sous Ubuntu fera la même chose sous Debian. Vous le vérifiez en une seule étape :
mysql --defaults-file=/etc/mysql/debian.cnf -e "SELECT current_user();"
MySQL 8 crée les nouveaux comptes avec le mécanisme caching_sha2_password, MariaDB avec mysql_native_password. Pour l'export via le socket local, cela n'a aucune importance, mais cela en prend beaucoup si vous sauvegardez à travers le réseau depuis un client plus ancien. Si celui-ci renvoie « The server requested authentication method unknown to the client », c'est que le client est trop vieux pour MySQL 8 et qu'il faut le mettre à jour.
AppArmor sous Ubuntu
Sous Ubuntu, AppArmor est actif d'origine et restreint le serveur de base de données, c'est-à-dire le processus mysqld ou mariadbd. Il ne restreint pas l'outil mysqldump, et c'est cette différence qui décide si vous tomberez dans le piège.
L'export de ce guide écrit le fichier via le shell (| gzip > ...), donc sous l'utilisateur qui exécute le script. Cette voie n'est pas concernée par AppArmor et fonctionne dans n'importe quel répertoire où l'utilisateur a le droit d'écrire. Dès que le serveur écrit lui-même, en revanche, d'autres règles s'appliquent. C'est le cas avec mysqldump --tab=/chemin et avec chaque SELECT ... INTO OUTFILE, car c'est alors le processus serveur qui crée le fichier, pas votre shell. Deux verrous indépendants l'un de l'autre entrent alors en jeu : la variable serveur secure_file_priv et le profil AppArmor du serveur. Sous Ubuntu, la variable pointe d'origine sur /var/lib/mysql-files/, et c'est exactement ce répertoire qui est autorisé dans le profil AppArmor. Un chemin cible comme /opt/mysqlbackups échoue donc deux fois.
Le diagnostic, lui, est retors. Le premier verrou se signale clairement avec ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement. Le second apparaît au contraire comme un simple Errcode: 13 "Permission denied", alors que le propriétaire et les droits du répertoire cible semblent parfaitement corrects au premier coup d'œil. Celui qui se met alors à distribuer des droits sur les fichiers cherche au mauvais endroit. Dans ce cas, vérifiez les deux :
mysql -e "SHOW VARIABLES LIKE 'secure_file_priv';"
aa-status | grep -Ei 'mysqld|mariadbd'
journalctl -k | grep -i 'apparmor.*DENIED' | tail -n 20
Si la dernière commande fait apparaître une ligne avec apparmor="DENIED" et votre chemin cible, vous tenez la cause. Le plus simple est de ne pas en arriver là et de rester sur l'export par pipe. Si vous avez réellement besoin d'écritures côté serveur, écrivez dans /var/lib/mysql-files/ puis déplacez ensuite le fichier. Ce n'est que si aucune de ces deux voies n'est possible que vous étendez le profil au chemin supplémentaire. Le fichier /etc/apparmor.d/local/usr.sbin.mysqld est prévu pour cela, et usr.sbin.mariadbd pour MariaDB, suivi de systemctl reload apparmor. Désactiver AppArmor n'est pas une solution, c'est retirer une couche de protection qui sécurise précisément ce serveur.
Erreurs fréquentes et solutions
La sauvegarde fait 0 octet : le plus souvent, les identifiants dans /root/.my.cnf ne sont pas les bons. Testez la connexion avec mysql --defaults-extra-file=/root/.my.cnf -e "SHOW DATABASES;". Derrière se cache fréquemment le cas décrit plus haut : le compte passe par le socket, et un mot de passe enregistré ne correspond donc à rien.
« Access denied » dans cron, mais pas dans la console : la tâche cron tourne sous un autre utilisateur que celui attendu. Inscrivez-la dans la crontab de root et n'utilisez que des chemins absolus dans le script. D'autres causes sont rassemblées dans Corriger MySQL Access denied for user.
Unknown table 'COLUMN_STATISTICS' in information_schema : vous sauvegardez une base MariaDB avec le mysqldump de MySQL 8, par exemple depuis une machine Ubuntu. À l'export, MySQL 8 interroge une table qui n'existe pas dans MariaDB. Ajoutez --column-statistics=0 à l'appel. Seul le client MySQL connaît cette option, et sur un système purement MariaDB vous ne devez pas la définir.
Access denied; you need (at least one of) the PROCESS privilege(s) for this operation : sous MySQL 8, l'utilisateur de sauvegarde n'a pas le droit de lire les informations de tablespace. Attribuez PROCESS comme décrit plus haut, ou ajoutez --no-tablespaces.
mariadb-dump: command not found : le script vient d'un système Debian avec MariaDB 11 et tourne désormais sur Ubuntu avec MySQL 8. Ce nom n'y existe pas. Écrivez mysqldump, cela fonctionne sur les deux systèmes.
Can't connect to local MySQL server through socket : le serveur ne tourne pas, ou le socket se trouve à un autre emplacement que celui attendu. Les causes possibles sont décrites dans Corriger les erreurs de socket MySQL.
SELinux bloque le script (AlmaLinux, Rocky Linux, RHEL) : vérifiez avec ausearch -m avc -ts recent si un refus d'accès a été consigné, et adaptez le cas échéant le contexte du répertoire de sauvegarde.
Le stockage se remplit : réduisez KEEP_DAYS, ou déplacez les anciennes sauvegardes vers un stockage externe. Ce qui dévore la place par ailleurs, Libérer de l'espace de stockage sous Linux vous le montre.
Message d'erreur au sujet de --single-transaction avec des tables MyISAM : cette option n'agit que sur InnoDB. Pour des tables MyISAM, vous pouvez utiliser --lock-tables à la place, les tables étant alors verrouillées pendant toute la durée de l'export. Notez également que sous MariaDB les tables système reposent sur le moteur Aria et ne sont pas prises en compte par --single-transaction.
Puisque vous travaillez de toute façon sur la base, autant faire le reste dans la foulée : supprimer les utilisateurs anonymes, effacer la base de test et désactiver l'accès distant pour root. La marche à suivre est décrite dans Sécuriser MariaDB et MySQL.
Questions fréquentes
Pourquoi le mot de passe de la base ne doit-il pas figurer dans la commande mysqldump ?
Qu'est-ce qui distingue Debian et Ubuntu pour la sauvegarde des bases MySQL ?
Sous Ubuntu, AppArmor empêche l'écriture du fichier de sauvegarde. Que faire ?
Ce guide fonctionne-t-il sur toutes les distributions Linux ?
Que faire si le compte de base de données root n'a aucun mot de passe ?
Combien de temps les sauvegardes sont-elles conservées ?
Suffit-il de garder les sauvegardes sur le même serveur ?
Comment restaurer une sauvegarde ?
La tâche cron ne s'exécute pas ou renvoie Access denied. Que puis-je vérifier ?
La sauvegarde fait 0 octet. D'où cela vient-il ?
2024-2026 KernelHost GmbH. Tous droits réservés. Ce guide est protégé par le droit d'auteur. Sa republication sur d'autres sites web, même partielle ou sous une forme modifiée, n'est pas autorisée sans notre accord écrit. Les citations accompagnées de la source et d'un lien sont expressément les bienvenues.

