Uma cópia de segurança que nunca foi restaurada é esperança, não estratégia - e no GLPI a parte que mais estraga o restauro não é o dump da base de dados, é o glpicrypt.key. Na sustentação de ambientes de clientes já vimos um restauro "perfeito" da base em que ninguém mais conseguia autenticar-se por LDAP nem enviar e-mail: os dados voltaram, mas a chave que decifra as palavras-passe de LDAP, SMTP e coletor de e-mail ficou para trás. Este guia consolida a rotina de cópia de segurança, rotação, teste de restauro e disaster recovery que aplicamos em produção, com os pontos onde as coisas realmente partem.
O que tem mesmo de entrar na cópia
O GLPI tem três camadas de estado, e as três têm de voltar juntas e coerentes:
- Base de dados - pedidos, ativos, utilizadores, regras e configurações. É o coração, mas sozinha não reergue o ambiente.
- Diretório de ficheiros (
files/) - documentos anexados (files/_documents), imagens, inventários XML e dados de plugins. Se a base tem a linha do documento mas o ficheiro não voltou, o utilizador clica e recebe um erro. - Configuração (
config/) - oconfig_db.php(anfitrião, base e credenciais) e, sobretudo, oglpicrypt.key. Essa chave decifra as palavras-passe gravadas na base: bind do LDAP, coletor de e-mail, SMTP das notificações e segredos de OAuth. Restaurar a base sem ela deixa todas essas palavras-passe como lixo indecifrável.
Dentro de files/ nem tudo precisa de cópia. Diretórios voláteis como _cache, _tmp, _sessions, _cron e _lock regeneram-se sozinhos e só incham a cópia - exclua-os. O que importa preservar é _documents, _pictures, _uploads, _inventories e _plugins.
Um dump consistente da base
O GLPI 10 e 11 usam InnoDB em todas as tabelas, por isso o --single-transaction tira um snapshot coerente sem bloquear a aplicação - os utilizadores continuam a abrir pedidos durante a cópia. O --quick evita carregar tabelas enormes na memória e o --default-character-set=utf8mb4 impede a corrupção de acentos e emojis. Nunca passe a palavra-passe na linha de comandos (aparece no ps e nos registos); use um ficheiro de credenciais restrito:
# ~/.my.cnf (chmod 600) - evita a palavra-passe no 'ps' e nos registos
[client]
host = 127.0.0.1
user = glpi
password = ...palavra_passe_glpi...
A cópia nativa do GLPI (Administração > Manutenção) grava um .sql em files/_dumps, mas em bases grandes tende a estourar os limites de tempo e memória do PHP. Para produção, um mysqldump agendado é mais fiável.
Script de cópia com rotação
Um único script que trata da base, dos ficheiros e da config pela ordem certa e ainda limpa o que passou dos 30 dias:
#!/usr/bin/env bash
set -euo pipefail
# Credenciais em ~/.my.cnf (chmod 600), nunca na linha de comandos
DATA=$(date +%F)
DEST="/backup/glpi/${DATA}"
mkdir -p "${DEST}"
# Base de dados: snapshot consistente de InnoDB, sem bloquear a aplicacao
mysqldump --single-transaction --quick --routines --triggers \
--default-character-set=utf8mb4 glpi \
| gzip -6 > "${DEST}/glpi_db.sql.gz"
# Ficheiros + config DEPOIS do dump (um ficheiro a mais e inofensivo;
# uma linha na base a apontar para um ficheiro em falta, 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 ficheiro que caiu no disco depois do dump é inofensivo no restauro; o contrário - uma linha na base a apontar para um ficheiro que ainda não existia quando o tar correu - torna-se um anexo partido. 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 a duas perguntas: quantos dados o negócio pode dar-se ao luxo de perder (RPO) e em quanto tempo tem de estar de pé (RTO). A resposta muda consoante a criticidade:
| Perfil do ambiente | RPO alvo | RTO alvo | Frequência da base | Retenção | Offsite |
|---|---|---|---|---|---|
| Pré-produção / teste | 24 h | dias | diário | 7 dias | opcional |
| Produção padrão | 24 h | 4 h | diário | 14-30 dias | sim (nuvem) |
| Produção crítica (SLA) | 15 min | 1 h | diário + binlog ou réplica | 30-90 dias | sim, cifrado |
São intervalos honestos, não promessas. Um RPO de 15 minutos exige binlog do MariaDB/MySQL ou uma réplica - o dump diário sozinho não o entrega.
Teste de restauro: o passo que quase ninguém faz
Uma cópia que nunca foi restaurada é um número num relatório, não uma garantia. Ensaie o restauro 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) Base de dados
zcat glpi_db.sql.gz | mysql --default-character-set=utf8mb4 -u root glpi_restore
# 2) Ficheiros + config (INCLUI o config/glpicrypt.key)
tar -xzf glpi_files.tar.gz -C /var/www/glpi
# 3) Codigo mais recente que o dump? aplica a migracao de esquema
php bin/console db:update --no-interaction
# 4) Limpa a cache e arranca para validar login/LDAP/e-mail
php bin/console cache:clear
Depois do restauro, confirme que o estado corresponde à realidade antes de confiar. Duas consultas rápidas já apanham os problemas mais comuns:
-- Versao gravada na base (tem de coincidir com a do codigo antes do db:update)
SELECT value AS versao_bd
FROM glpi_configs
WHERE context = 'core' AND name = 'version';
-- Quantos documentos apontam para um ficheiro fisico em files/_documents
SELECT COUNT(*) AS docs_com_ficheiro
FROM glpi_documents
WHERE filepath <> '';
A primeira mostra a versão gravada na base: se for inferior à do código, é o db:update que reconcilia o esquema. A segunda conta os documentos que esperam um ficheiro em disco - compare com o que realmente veio no files/_documents. Em Docker, os mesmos passos correm com docker exec -u www-data glpi php bin/console ....
Disaster recovery a sério
Uma cópia é um comando; o disaster recovery é um plano. O mínimo saudável é a regra 3-2-1: três cópias, em dois suportes diferentes, uma delas offsite. E aqui está o erro comum: meter o dump da base e o config/ (com o glpicrypt.key) no mesmo .tar sem cifrar e enviar para um bucket. Quem puser a mão nesse ficheiro tem a base inteira e a chave que decifra as palavras-passe de LDAP, SMTP e coletor - ou seja, credenciais de infraestrutura do cliente em texto recuperável. A cópia offsite tem de ir cifrada (por exemplo com age ou gpg) e com acesso restrito.
Feche o plano com um runbook escrito - onde estão as cópias, qual a ordem de restauro, 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 cópia; foi ter restaurado essa cópia antes, com relógio na mão, e saber que ela volta em 40 minutos e não em "não sei".
Se o seu GLPI é crítico e nunca cronometrou um restauro completo - base, ficheiros e a chave de cifra juntos - a NexTool desenha e opera a rotina de cópia de segurança e disaster recovery do seu ambiente, com restauro ensaiado e cópias offsite cifradas. Fale connosco sobre suporte e sustentação de GLPI.
Este conteúdo foi produzido com auxílio de inteligência artificial e revisto pela equipa Nextool Solutions.