Backup e Disaster Recovery do GLPI: Guia Definitivo

Roteiro de produção para backup e disaster recovery do GLPI: dump consistente, o glpicrypt.key que quase todo mundo esquece, rotação, teste de restore ensaiado e matriz de decisão RPO/RTO.

Backup que nunca foi restaurado é esperança, não estratégia - e no GLPI a parte que mais derruba o restore não é o dump do banco, é o glpicrypt.key. Na sustentação de ambientes de clientes já vimos restore "perfeito" do banco em que ninguém mais conseguia logar por LDAP nem enviar e-mail: os dados voltaram, mas a chave que decifra as senhas de LDAP, SMTP e coletor de e-mail ficou para trás. Este guia consolida o roteiro de backup, rotação, teste de restore e disaster recovery que aplicamos em produção, com os pontos onde as coisas realmente quebram.

O que realmente precisa entrar no backup

O GLPI tem três camadas de estado, e as três precisam voltar juntas e coerentes:

  • Banco de dados - chamados, ativos, usuários, regras e configurações. É o coração, mas sozinho não reergue o ambiente.
  • Diretório de arquivos (files/) - documentos anexados (files/_documents), imagens, inventários XML e dados de plugins. Se o banco tem a linha do documento mas o arquivo não voltou, o usuário clica e recebe erro.
  • Configuração (config/) - o config_db.php (host, base e credenciais) e, principalmente, o glpicrypt.key. Essa chave é o que decifra as senhas gravadas no banco: bind do LDAP, coletor de e-mail (mailcollector), SMTP das notificações e segredos de OAuth. Restaurar o banco sem ela deixa todas essas senhas como lixo indecifrável.

Dentro de files/ nem tudo precisa de backup. Diretórios voláteis como _cache, _tmp, _sessions, _cron e _lock são regenerados sozinhos e só incham o backup - exclua-os. O que importa preservar é _documents, _pictures, _uploads, _inventories e _plugins.

Dump consistente do banco

O GLPI 10 e 11 usam InnoDB em todas as tabelas, então o --single-transaction tira um snapshot coerente sem travar a aplicação - os usuários continuam abrindo chamados durante o backup. O --quick evita carregar tabelas gigantes na memória e o --default-character-set=utf8mb4 impede corrupção de acentos e emojis. Nunca passe a senha na linha de comando (ela aparece no ps e nos logs); use um arquivo de credenciais restrito:

# ~/.my.cnf (chmod 600) - evita a senha no 'ps' e nos logs
[client]
host = 127.0.0.1
user = glpi
password = ...senha_do_glpi...

O backup nativo do GLPI (Administração > Manutenção) grava um .sql em files/_dumps, mas em bases grandes ele tende a estourar tempo e memória do PHP. Para produção, o mysqldump agendado é mais confiável.

Script de backup com rotação

Um script único que resolve banco, arquivos e config na ordem certa e ainda limpa o que passou de 30 dias:

#!/usr/bin/env bash
set -euo pipefail

# Credenciais em ~/.my.cnf (chmod 600), nunca na linha de comando
DATA=$(date +%F)
DEST="/backup/glpi/${DATA}"
mkdir -p "${DEST}"

# Banco: snapshot consistente de InnoDB, sem travar a aplicacao
mysqldump --single-transaction --quick --routines --triggers \
  --default-character-set=utf8mb4 glpi \
  | gzip -6 > "${DEST}/glpi_db.sql.gz"

# Arquivos + config DEPOIS do dump (arquivo a mais e inofensivo;
# linha no banco apontando para arquivo ausente, nao)
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

# Rotacao: manter 30 dias
find /backup/glpi -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +

echo "Backup OK: ${DEST}"

Repare na ordem: o dump vem antes do tar. Um arquivo que caiu no disco depois do dump é inofensivo no restore; o contrário - uma linha no banco apontando para um arquivo que ainda não existia quando o tar rodou - vira um anexo quebrado. Agende no cron:

# /etc/cron.d/glpi-backup - diario as 02h15
15 2 * * * root /opt/scripts/backup-glpi.sh >> /var/log/glpi-backup.log 2>&1

Matriz de decisão: RPO x RTO

Antes de fechar frequência e retenção, responda duas perguntas: quanto de dado o negócio aceita perder (RPO) e em quanto tempo precisa estar de pé de novo (RTO). A resposta muda por criticidade:

Perfil do ambienteRPO alvoRTO alvoFrequência do bancoRetençãoOffsite
Homologação / teste24 hdiasdiário7 diasopcional
Produção padrão24 h4 hdiário14-30 diassim (nuvem)
Produção crítica (SLA)15 min1 hdiário + binlog ou réplica30-90 diassim, cifrado

São faixas honestas, não promessas. RPO de 15 minutos exige binlog do MariaDB/MySQL ou réplica - o dump diário sozinho não entrega isso.

Teste de restore: o passo que quase ninguém faz

Backup que nunca foi restaurado é um número num relatório, não uma garantia. Ensaie o restore periodicamente num ambiente descartável - Docker é ideal - e nunca por cima da produção:

# Ambiente DESCARTAVEL (Docker). Nunca ensaie por cima da producao.
mysql -u root -e "CREATE DATABASE glpi_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"

# 1) Banco
zcat glpi_db.sql.gz | mysql --default-character-set=utf8mb4 -u root glpi_restore

# 2) Arquivos + config (INCLUI o config/glpicrypt.key)
tar -xzf glpi_files.tar.gz -C /var/www/glpi

# 3) Codigo mais novo que o dump? aplica a migracao de schema
php bin/console db:update --no-interaction

# 4) Limpa o cache e sobe para validar login/LDAP/e-mail
php bin/console cache:clear

Depois do restore, confirme que o estado bate com a realidade antes de confiar. Duas consultas rápidas já pegam os problemas mais comuns:

-- Versao gravada no banco (precisa casar com a do codigo antes do db:update)
SELECT value AS versao_db
FROM glpi_configs
WHERE context = 'core' AND name = 'version';

-- Quantos documentos apontam para um arquivo fisico em files/_documents
SELECT COUNT(*) AS docs_com_arquivo
FROM glpi_documents
WHERE filepath <> '';

A primeira mostra a versão gravada no banco: se ela for menor que a do código, é o db:update que reconcilia o schema. A segunda conta os documentos com arquivo esperado em disco - compare com o que realmente veio no files/_documents. Em Docker, os mesmos passos rodam com docker exec -u www-data glpi php bin/console ....

Disaster recovery de verdade

Backup é comando; disaster recovery é plano. O mínimo saudável é a regra 3-2-1: três cópias, em dois meios diferentes, uma delas offsite. E aqui mora o erro comum: jogar o dump do banco e o config/ (com o glpicrypt.key) no mesmo .tar sem cifrar e mandar para um bucket. Quem puser a mão nesse arquivo tem o banco inteiro e a chave que decifra as senhas de LDAP, SMTP e coletor - ou seja, credenciais de infraestrutura do cliente em texto recuperável. Backup offsite tem que ir cifrado (por exemplo com age ou gpg) e com acesso restrito.

Feche o plano com um runbook escrito - onde estão os backups, qual a ordem de restore, quem aciona - e com o RTO cronometrado num ensaio real. Na sustentação, o que separa um susto de uma catástrofe nunca foi ter backup; foi ter restaurado aquele backup antes, com relógio na mão, e saber que ele volta em 40 minutos e não em "não sei".

Se o seu GLPI é crítico e você nunca cronometrou um restore completo - banco, arquivos e a chave de cifra juntos - a NexTool desenha e opera a rotina de backup e disaster recovery do seu ambiente, com restore ensaiado e offsite cifrado. Fale com a gente sobre suporte e sustentação de GLPI.


Este conteúdo foi produzido com auxílio de inteligência artificial e revisado pela equipe Nextool Solutions.

Perguntas Frequentes

Use mysqldump --single-transaction: como o GLPI 10 e 11 são todos InnoDB, o dump sai consistente sem travar a aplicação, e os usuários seguem abrindo chamados. Faça o backup dos arquivos (files/) e da configuração logo em seguida, no mesmo script agendado por cron.

É a chave que decifra as senhas guardadas no banco: bind do LDAP, coletor de e-mail, SMTP das notificações e segredos de OAuth. Se você restaura o banco mas perdeu o config/glpicrypt.key, essas senhas viram lixo indecifrável e o login por LDAP e o envio de e-mail param. Faça backup do config/ junto do banco, sempre.

Banco: diário no mínimo, para produção. Arquivos: diário ou semanal, conforme o volume de anexos. Para um RPO curto (15 a 30 minutos) você precisa de binlog do MariaDB ou réplica; só o dump diário entrega RPO de até 24 horas.

Restaure periodicamente num ambiente descartável (Docker), nunca por cima da produção. Suba o GLPI, faça login, abra um chamado antigo com anexo e confira LDAP e envio de e-mail. Cronometre o processo: esse tempo é o seu RTO real. Um backup nunca restaurado não é garantia.

Sim, desde que o código seja igual ou mais novo que o dump. Restaure o banco e então rode php bin/console db:update para migrar o schema. Nunca restaure um dump mais novo num código mais antigo: a estrutura não retrocede e o ambiente quebra.

Mesmo princípio: docker exec no container do banco para o mysqldump e tar dos volumes montados de files/ e config/. Fixe a versão da imagem (não use :latest) para que o restore caia num código compatível com o dump.

Precisa de ajuda?