Une sauvegarde jamais restaurée est un espoir, pas une stratégie - et dans GLPI, la partie qui casse le plus souvent la restauration n'est pas le dump de la base, c'est glpicrypt.key. En maintenance d'environnements clients, nous avons déjà vu une restauration "parfaite" de la base où plus personne ne pouvait se connecter en LDAP ni envoyer d'e-mail : les données étaient revenues, mais la clé qui déchiffre les mots de passe LDAP, SMTP et collecteur d'e-mail était restée en arrière. Ce guide consolide la routine de sauvegarde, rotation, test de restauration et disaster recovery que nous exécutons en production, en insistant sur les points où les choses cassent réellement.
Ce qui doit vraiment entrer dans la sauvegarde
GLPI a trois couches d'état, et les trois doivent revenir ensemble et cohérentes :
- Base de données - tickets, actifs, utilisateurs, règles et configurations. C'est le cœur, mais seule elle ne reconstruit pas l'environnement.
- Répertoire de fichiers (
files/) - documents joints (files/_documents), images, inventaires XML et données de plugins. Si la base a la ligne du document mais que le fichier n'est pas revenu, l'utilisateur clique et reçoit une erreur. - Configuration (
config/) - leconfig_db.php(hôte, base et identifiants) et surtoutglpicrypt.key. Cette clé déchiffre les mots de passe stockés en base : bind LDAP, collecteur d'e-mail, SMTP des notifications et secrets OAuth. Restaurer la base sans elle laisse tous ces mots de passe comme une bouillie indéchiffrable.
Dans files/, tout n'a pas besoin de sauvegarde. Les répertoires volatils comme _cache, _tmp, _sessions, _cron et _lock se régénèrent seuls et ne font qu'alourdir la sauvegarde - excluez-les. Ce qui compte, c'est de préserver _documents, _pictures, _uploads, _inventories et _plugins.
Un dump cohérent de la base
GLPI 10 et 11 utilisent InnoDB sur toutes les tables, donc --single-transaction prend un snapshot cohérent sans bloquer l'application - les utilisateurs continuent d'ouvrir des tickets pendant la sauvegarde. --quick évite de charger d'énormes tables en mémoire et --default-character-set=utf8mb4 empêche la corruption des accents et des emojis. Ne passez jamais le mot de passe en ligne de commande (il apparaît dans ps et dans les logs) ; utilisez un fichier d'identifiants restreint :
# ~/.my.cnf (chmod 600) - evite le mot de passe dans 'ps' et les logs
[client]
host = 127.0.0.1
user = glpi
password = ...mot_de_passe_glpi...
La sauvegarde native de GLPI (Administration > Maintenance) écrit un .sql dans files/_dumps, mais sur de grosses bases elle dépasse souvent les limites de temps et de mémoire de PHP. Pour la production, un mysqldump planifié est plus fiable.
Script de sauvegarde avec rotation
Un script unique qui gère base, fichiers et config dans le bon ordre et nettoie en plus tout ce qui dépasse 30 jours :
#!/usr/bin/env bash
set -euo pipefail
# Identifiants dans ~/.my.cnf (chmod 600), jamais en ligne de commande
DATA=$(date +%F)
DEST="/backup/glpi/${DATA}"
mkdir -p "${DEST}"
# Base : snapshot coherent d'InnoDB sans bloquer l'application
mysqldump --single-transaction --quick --routines --triggers \
--default-character-set=utf8mb4 glpi \
| gzip -6 > "${DEST}/glpi_db.sql.gz"
# Fichiers + config APRES le dump (un fichier en trop est inoffensif ;
# une ligne en base pointant vers un fichier absent, non)
tar -czf "${DEST}/glpi_files.tar.gz" \
--exclude='files/_cache' --exclude='files/_tmp' \
--exclude='files/_sessions' --exclude='files/_lock' \
-C /var/www/glpi files config
# Rotation : conserver 30 jours
find /backup/glpi -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
echo "Backup OK: ${DEST}"
Notez l'ordre : le dump vient avant le tar. Un fichier arrivé sur le disque après le dump est inoffensif à la restauration ; l'inverse - une ligne en base pointant vers un fichier qui n'existait pas encore quand tar a tourné - devient une pièce jointe cassée. Planifiez-le dans cron :
# /etc/cron.d/glpi-backup - quotidien a 02h15
15 2 * * * root /opt/scripts/backup-glpi.sh >> /var/log/glpi-backup.log 2>&1
Matrice de décision : RPO vs RTO
Avant de fixer fréquence et rétention, répondez à deux questions : combien de données l'entreprise peut se permettre de perdre (RPO) et en combien de temps elle doit être de nouveau debout (RTO). La réponse change selon la criticité :
| Profil d'environnement | RPO cible | RTO cible | Fréquence de la base | Rétention | Hors site |
|---|---|---|---|---|---|
| Préproduction / test | 24 h | jours | quotidien | 7 jours | optionnel |
| Production standard | 24 h | 4 h | quotidien | 14-30 jours | oui (cloud) |
| Production critique (SLA) | 15 min | 1 h | quotidien + binlog ou réplica | 30-90 jours | oui, chiffré |
Ce sont des fourchettes honnêtes, pas des promesses. Un RPO de 15 minutes exige le binlog de MariaDB/MySQL ou un réplica - le dump quotidien seul ne le fournit pas.
Test de restauration : l'étape que presque personne ne fait
Une sauvegarde jamais restaurée est un chiffre dans un rapport, pas une garantie. Répétez la restauration régulièrement dans un environnement jetable - Docker est idéal - et jamais par-dessus la production :
# Environnement JETABLE (Docker). Ne jamais repeter sur la production.
mysql -u root -e "CREATE DATABASE glpi_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
# 1) Base de donnees
zcat glpi_db.sql.gz | mysql --default-character-set=utf8mb4 -u root glpi_restore
# 2) Fichiers + config (INCLUT config/glpicrypt.key)
tar -xzf glpi_files.tar.gz -C /var/www/glpi
# 3) Code plus recent que le dump ? applique la migration de schema
php bin/console db:update --no-interaction
# 4) Vide le cache et demarre pour valider login/LDAP/e-mail
php bin/console cache:clear
Après la restauration, vérifiez que l'état correspond à la réalité avant de faire confiance. Deux requêtes rapides attrapent déjà les problèmes les plus courants :
-- Version enregistree en base (doit correspondre a celle du code avant db:update)
SELECT value AS version_bdd
FROM glpi_configs
WHERE context = 'core' AND name = 'version';
-- Combien de documents pointent vers un fichier physique dans files/_documents
SELECT COUNT(*) AS docs_avec_fichier
FROM glpi_documents
WHERE filepath <> '';
La première montre la version enregistrée en base : si elle est inférieure à celle du code, c'est db:update qui réconcilie le schéma. La seconde compte les documents qui attendent un fichier sur le disque - comparez-la à ce qui est réellement arrivé dans files/_documents. En Docker, les mêmes étapes tournent avec docker exec -u www-data glpi php bin/console ....
Un vrai disaster recovery
Une sauvegarde est une commande ; le disaster recovery est un plan. Le minimum sain est la règle 3-2-1 : trois copies, sur deux supports différents, l'une hors site. Et voici l'erreur courante : jeter le dump de la base et config/ (avec glpicrypt.key) dans le même .tar, non chiffré, et l'envoyer vers un bucket. Quiconque récupère ce fichier détient toute la base et la clé qui déchiffre les mots de passe LDAP, SMTP et collecteur - autrement dit, les identifiants d'infrastructure du client en texte récupérable. La sauvegarde hors site doit partir chiffrée (par exemple avec age ou gpg) et avec un accès restreint.
Complétez le plan par un runbook écrit - où sont les sauvegardes, quel est l'ordre de restauration, qui le déclenche - et par un RTO chronométré lors d'une vraie répétition. En maintenance, ce qui sépare une frayeur d'une catastrophe n'a jamais été d'avoir une sauvegarde ; c'était d'avoir restauré cette sauvegarde auparavant, chronomètre en main, et de savoir qu'elle revient en 40 minutes et non en "je ne sais pas".
Si votre GLPI est critique et que vous n'avez jamais chronométré une restauration complète - base, fichiers et la clé de chiffrement ensemble - NexTool conçoit et exploite la routine de sauvegarde et de disaster recovery de votre environnement, avec une restauration répétée et des copies hors site chiffrées. Parlez-nous du support et de la maintenance GLPI.
Ce contenu a été produit avec l'aide de l'intelligence artificielle et revu par l'équipe Nextool Solutions.