Sauvegarde et Disaster Recovery de GLPI : le Guide Complet

Manuel de production pour la sauvegarde et le disaster recovery de GLPI : dump cohérent, le glpicrypt.key que presque tout le monde oublie, rotation, test de restauration répété et matrice de décision RPO/RTO.

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/) - le config_db.php (hôte, base et identifiants) et surtout glpicrypt.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'environnementRPO cibleRTO cibleFréquence de la baseRétentionHors site
Préproduction / test24 hjoursquotidien7 joursoptionnel
Production standard24 h4 hquotidien14-30 joursoui (cloud)
Production critique (SLA)15 min1 hquotidien + binlog ou réplica30-90 joursoui, 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.

Questions fréquentes

Utilisez mysqldump --single-transaction : comme GLPI 10 et 11 sont tout en InnoDB, le dump est cohérent sans bloquer l'application, et les utilisateurs continuent d'ouvrir des tickets. Sauvegardez les fichiers (files/) et la configuration juste après, dans le même script planifié par cron.

C'est la clé qui déchiffre les mots de passe stockés en base : bind LDAP, collecteur d'e-mail, SMTP des notifications et secrets OAuth. Si vous restaurez la base mais avez perdu config/glpicrypt.key, ces mots de passe deviennent une bouillie indéchiffrable et la connexion LDAP et l'envoi d'e-mail s'arrêtent. Sauvegardez toujours config/ avec la base.

Base de données : quotidienne au minimum en production. Fichiers : quotidienne ou hebdomadaire, selon le volume de pièces jointes. Pour un RPO court (15 à 30 minutes) il faut le binlog de MariaDB ou un réplica ; le dump quotidien seul donne un RPO jusqu'à 24 heures.

Restaurez-la régulièrement dans un environnement jetable (Docker), jamais par-dessus la production. Démarrez GLPI, connectez-vous, ouvrez un ancien ticket avec pièce jointe et vérifiez LDAP et l'envoi d'e-mail. Chronométrez le processus : ce temps est votre RTO réel. Une sauvegarde jamais restaurée n'est pas une garantie.

Oui, tant que le code est égal ou plus récent que le dump. Restaurez la base, puis lancez php bin/console db:update pour migrer le schéma. Ne restaurez jamais un dump plus récent sur du code plus ancien : la structure ne recule pas et l'environnement casse.

Même principe : docker exec dans le conteneur de la base pour le mysqldump et tar des volumes montés de files/ et config/. Épinglez la version de l'image (n'utilisez pas :latest) pour que la restauration tombe sur un code compatible avec le dump.

Besoin d'aide ?