Backup e Disaster Recovery di GLPI: la Guida Definitiva

Manuale di produzione per backup e disaster recovery di GLPI: dump coerente, il glpicrypt.key che quasi tutti dimenticano, rotazione, test di ripristino provato e matrice di decisione RPO/RTO.

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/) - il config_db.php (host, database e credenziali) e soprattutto glpicrypt.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'ambienteRPO obiettivoRTO obiettivoFrequenza del databaseRetentionOffsite
Staging / test24 hgiornigiornaliero7 giorniopzionale
Produzione standard24 h4 hgiornaliero14-30 giornisì (cloud)
Produzione critica (SLA)15 min1 hgiornaliero + binlog o replica30-90 giornisì, 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.

Domande Frequenti

Usa mysqldump --single-transaction: poiché GLPI 10 e 11 sono tutti InnoDB, il dump è coerente senza bloccare l'applicazione e gli utenti continuano ad aprire ticket. Fai il backup dei file (files/) e della configurazione subito dopo, nello stesso script pianificato con cron.

È la chiave che decifra le password salvate nel database: bind LDAP, collettore e-mail, SMTP delle notifiche e segreti OAuth. Se ripristini il database ma hai perso config/glpicrypt.key, quelle password diventano spazzatura indecifrabile e login LDAP e invio e-mail si fermano. Fai sempre il backup di config/ insieme al database.

Database: giornaliero come minimo in produzione. File: giornaliero o settimanale, in base al volume degli allegati. Per un RPO breve (15-30 minuti) serve il binlog di MariaDB o una replica; il solo dump giornaliero dà un RPO fino a 24 ore.

Ripristinalo periodicamente in un ambiente usa e getta (Docker), mai sopra la produzione. Avvia GLPI, accedi, apri un vecchio ticket con allegato e verifica LDAP e invio e-mail. Cronometra il processo: quel tempo è il tuo RTO reale. Un backup mai ripristinato non è una garanzia.

Sì, purché il codice sia uguale o più nuovo del dump. Ripristina il database, poi esegui php bin/console db:update per migrare lo schema. Non ripristinare mai un dump più nuovo su codice più vecchio: la struttura non torna indietro e l'ambiente si rompe.

Stesso principio: docker exec nel contenitore del database per il mysqldump e tar dei volumi montati di files/ e config/. Fissa la versione dell'immagine (non usare :latest) così il ripristino cade su un codice compatibile con il dump.

Hai bisogno di aiuto?