Un backup mai ripristinato è speranza, non strategia - e in GLPI la parte che rompe più spesso il ripristino non è il dump del database, è glpicrypt.key. Nella manutenzione di ambienti dei clienti abbiamo già visto un ripristino "perfetto" del database in cui nessuno riusciva più ad autenticarsi via LDAP né a inviare e-mail: i dati erano tornati, ma la chiave che decifra le password di LDAP, SMTP e collettore e-mail era rimasta indietro. Questa guida consolida la routine di backup, rotazione, test di ripristino e disaster recovery che eseguiamo in produzione, concentrandosi sui punti in cui le cose si rompono davvero.
Cosa deve davvero entrare nel backup
GLPI ha tre livelli di stato, e tutti e tre devono tornare insieme e coerenti:
- Database - ticket, asset, utenti, regole e configurazioni. È il cuore, ma da solo non ricostruisce l'ambiente.
- Directory dei file (
files/) - documenti allegati (files/_documents), immagini, inventari XML e dati dei plugin. Se il database ha la riga del documento ma il file non è tornato, l'utente clicca e riceve un errore. - Configurazione (
config/) - ilconfig_db.php(host, database e credenziali) e soprattuttoglpicrypt.key. Questa chiave decifra le password salvate nel database: bind LDAP, collettore e-mail, SMTP delle notifiche e segreti OAuth. Ripristinare il database senza di essa lascia tutte quelle password come spazzatura indecifrabile.
Dentro files/ non tutto va salvato. Directory volatili come _cache, _tmp, _sessions, _cron e _lock si rigenerano da sole e gonfiano soltanto il backup - escludile. Ciò che conta è preservare _documents, _pictures, _uploads, _inventories e _plugins.
Un dump coerente del database
GLPI 10 e 11 usano InnoDB su tutte le tabelle, quindi --single-transaction scatta uno snapshot coerente senza bloccare l'applicazione - gli utenti continuano ad aprire ticket durante il backup. --quick evita di caricare tabelle enormi in memoria e --default-character-set=utf8mb4 impedisce la corruzione di accenti ed emoji. Non passare mai la password sulla riga di comando (compare in ps e nei log); usa un file di credenziali con permessi ristretti:
# ~/.my.cnf (chmod 600) - evita la password in 'ps' e nei log
[client]
host = 127.0.0.1
user = glpi
password = ...password_glpi...
Il backup nativo di GLPI (Amministrazione > Manutenzione) scrive un .sql in files/_dumps, ma su database grandi tende a sforare i limiti di tempo e memoria di PHP. Per la produzione, un mysqldump pianificato è più affidabile.
Script di backup con rotazione
Un unico script che gestisce database, file e config nell'ordine giusto e pulisce anche ciò che supera i 30 giorni:
#!/usr/bin/env bash
set -euo pipefail
# Credenziali in ~/.my.cnf (chmod 600), mai sulla riga di comando
DATA=$(date +%F)
DEST="/backup/glpi/${DATA}"
mkdir -p "${DEST}"
# Database: snapshot coerente di InnoDB senza bloccare l'applicazione
mysqldump --single-transaction --quick --routines --triggers \
--default-character-set=utf8mb4 glpi \
| gzip -6 > "${DEST}/glpi_db.sql.gz"
# File + config DOPO il dump (un file in piu e innocuo;
# una riga nel database che punta a un file assente, no)
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
# Rotazione: conservare 30 giorni
find /backup/glpi -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
echo "Backup OK: ${DEST}"
Nota l'ordine: il dump viene prima del tar. Un file finito su disco dopo il dump è innocuo al ripristino; il contrario - una riga nel database che punta a un file non ancora esistente quando tar è partito - diventa un allegato rotto. Pianificalo in cron:
# /etc/cron.d/glpi-backup - giornaliero alle 02:15
15 2 * * * root /opt/scripts/backup-glpi.sh >> /var/log/glpi-backup.log 2>&1
Matrice di decisione: RPO vs RTO
Prima di fissare frequenza e retention, rispondi a due domande: quanti dati l'azienda può permettersi di perdere (RPO) e in quanto tempo deve tornare in piedi (RTO). La risposta cambia con la criticità:
| Profilo dell'ambiente | RPO obiettivo | RTO obiettivo | Frequenza del database | Retention | Offsite |
|---|---|---|---|---|---|
| Staging / test | 24 h | giorni | giornaliero | 7 giorni | opzionale |
| Produzione standard | 24 h | 4 h | giornaliero | 14-30 giorni | sì (cloud) |
| Produzione critica (SLA) | 15 min | 1 h | giornaliero + binlog o replica | 30-90 giorni | sì, cifrato |
Sono intervalli onesti, non promesse. Un RPO di 15 minuti richiede il binlog di MariaDB/MySQL o una replica - il dump giornaliero da solo non lo garantisce.
Test di ripristino: il passo che quasi nessuno fa
Un backup mai ripristinato è un numero in un report, non una garanzia. Prova il ripristino periodicamente in un ambiente usa e getta - Docker è ideale - e mai sopra la produzione:
# Ambiente USA E GETTA (Docker). Non provare mai sopra la produzione.
mysql -u root -e "CREATE DATABASE glpi_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
# 1) Database
zcat glpi_db.sql.gz | mysql --default-character-set=utf8mb4 -u root glpi_restore
# 2) File + config (INCLUDE config/glpicrypt.key)
tar -xzf glpi_files.tar.gz -C /var/www/glpi
# 3) Codice piu nuovo del dump? applica la migrazione di schema
php bin/console db:update --no-interaction
# 4) Svuota la cache e avvia per validare login/LDAP/e-mail
php bin/console cache:clear
Dopo il ripristino, conferma che lo stato corrisponda alla realtà prima di fidarti. Due query rapide intercettano già i problemi più comuni:
-- Versione salvata nel database (deve coincidere con quella del codice prima di db:update)
SELECT value AS versione_db
FROM glpi_configs
WHERE context = 'core' AND name = 'version';
-- Quanti documenti puntano a un file fisico in files/_documents
SELECT COUNT(*) AS docs_con_file
FROM glpi_documents
WHERE filepath <> '';
La prima mostra la versione salvata nel database: se è inferiore a quella del codice, è db:update a riconciliare lo schema. La seconda conta i documenti che si aspettano un file su disco - confrontala con ciò che è davvero arrivato in files/_documents. In Docker, gli stessi passi girano con docker exec -u www-data glpi php bin/console ....
Disaster recovery vero
Un backup è un comando; il disaster recovery è un piano. Il minimo sano è la regola 3-2-1: tre copie, su due supporti diversi, una offsite. E qui sta l'errore comune: mettere il dump del database e config/ (con glpicrypt.key) nello stesso .tar, non cifrato, e spedirlo a un bucket. Chi mette le mani su quel file ha l'intero database e la chiave che decifra le password di LDAP, SMTP e collettore - cioè le credenziali di infrastruttura del cliente in testo recuperabile. Il backup offsite deve partire cifrato (per esempio con age o gpg) e con accesso ristretto.
Chiudi il piano con un runbook scritto - dove sono i backup, qual è l'ordine di ripristino, chi lo attiva - e con l'RTO cronometrato in una prova reale. Nella manutenzione, ciò che separa uno spavento da una catastrofe non è mai stato avere un backup; è stato aver ripristinato quel backup prima, cronometro alla mano, e sapere che torna in 40 minuti e non in "non lo so".
Se il tuo GLPI è critico e non hai mai cronometrato un ripristino completo - database, file e la chiave di cifratura insieme - NexTool progetta e gestisce la routine di backup e disaster recovery del tuo ambiente, con ripristino provato e copie offsite cifrate. Parlaci del supporto e della manutenzione di GLPI.
Questo contenuto è stato prodotto con l'ausilio dell'intelligenza artificiale e revisionato dal team di Nextool Solutions.