Wiki
Backup e recuperação
Como o QuoteNode gere os backups de base de dados e ficheiros — arquivos cifrados com age, restauração guiada por manifesto, kits de recuperação e perfis de runtime.
Backup e recuperação
O QuoteNode inclui um sistema de backups integrado que protege os seus dados comerciais contra falhas de hardware, eliminações acidentais e incidentes operacionais.
O que é incluído no backup
Cada backup cria um arquivo que contém:
- Dump da base de dados — um dump completo do PostgreSQL em formato personalizado (
pg_dump --format=custom), incluindo todas as tabelas, sequências e restrições. - Armazenamento de ficheiros — todos os ficheiros carregados (imagens de produtos, logótipos de empresa) e os PDF gerados, arquivados como
files.tar.gzcom caminhos relativos. - Manifesto do backup — um ficheiro
backup-manifest.jsonque contém a versão de origem, o modo de cifragem, o modo de payload da base de dados, as somas de verificação e os metadados de compatibilidade de restauração. - Somas de verificação de integridade — um ficheiro
checksums.sha256que contém os hashes SHA-256 de todos os componentes do arquivo.
As três camadas de cifragem
Um backup envolve três segredos/definições independentes. «Backup cifrado» é ambíguo — nomeie sempre a camada:
- Identidade privada AGE — desbloqueia apenas o arquivo externo
.tar.age. Vem do Recovery Kit e é usada ao restaurar/verificar (RESTORE_AGE_IDENTITY_FILE). Não contém nem substitui aDB_ENCRYPTION_KEY. DB_ENCRYPTION_KEY— decifra os camposAPP_ENCRYPTEDda base de dados e os segredos operacionais (MFA, SMTP, payloads de e-mail de oferta). Faça o backup dela em separado do arquivo e nunca a passe como argumento de linha de comandos.ENCRYPT_PII— a política de armazenamento em tempo de execução do destino. Não decifra um arquivo; alterá-la nunca substitui a chave correta nem o pós-processamento de restauro.
Guarde os seus segredos .env / de implementação e o Recovery Kit em localizações protegidas separadas.
Cifragem do arquivo
Os novos backups cifrados usam a cifragem por destinatário age (AGE_RECIPIENT). É o único modelo de cifragem suportado para os novos arquivos.
- O processo de backup usa apenas um destinatário age público (
age1...) — não é necessária qualquer chave privada no servidor para criar backups. - Os arquivos cifrados têm a extensão
.tar.age. - A soma de verificação SHA-256 do arquivo cifrado é guardada junto ao arquivo para verificação do lado do operador.
- A decifragem requer a identidade age privada correspondente, mantida exclusivamente no kit de recuperação do operador.
- A identidade age privada em bruto nunca é guardada na base de dados, nos registos, nos DTO nem nos argumentos de processo após a confirmação da configuração.
Backups locais não cifrados
Os backups locais não cifrados (.tar) só são permitidos quando todas as condições seguintes se verificam:
BACKUP_ARCHIVE_ENCRYPTION_MODE=NONEBACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=true- O destino é o armazenamento local
BACKUP_DATABASE_PAYLOAD_MODE=APP_ENCRYPTED- O administrador reconheceu explicitamente o risco na interface
Os arquivos não cifrados são bloqueados para o armazenamento remoto e para os payloads com PII decifradas.
Configuração (.env). O destinatário age é gerado pelo kit de recuperação (Administração → Segurança → Backup) e guardado na instância — não coloca qualquer chave no .env. Defina apenas as duas variáveis de modo:
BACKUP_ENABLED=true
# Second, dedicated switch — default off. Set true only on the backup-worker to run scheduled backups.
BACKUP_SCHEDULER_ENABLED=true
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT
BACKUP_DATABASE_PAYLOAD_MODE=APP_ENCRYPTED
# Alternative — encrypted archive + decrypted PII (cross-instance portability):
# BACKUP_DATABASE_PAYLOAD_MODE=PII_DECRYPTED
BACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=false
Para desativar a cifragem do arquivo (apenas local, não recomendado — as PII continuam cifradas no payload):
BACKUP_ARCHIVE_ENCRYPTION_MODE=NONE
BACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=true
Com
AGE_RECIPIENT, se ainda não tiver sido gerado nenhum destinatário, o backup falha de forma explícita em vez de escrever um arquivo desprotegido. A combinaçãoNONE+PII_DECRYPTEDé rejeitada.
Modos de payload da base de dados
| Modo | Descrição |
|---|---|
APP_ENCRYPTED |
Predefinido. Os campos PII permanecem cifrados com a chave da aplicação DB_ENCRYPTION_KEY. Restaurar sobre a mesma chave (impressão digital correspondente) não requer passos adicionais; restaurar sobre uma chave diferente requer a chave de origem original (via PII_REKEY_OLD_KEY) para uma recifragem offline, caso contrário o restauro é bloqueado antes de qualquer alteração. |
PII_DECRYPTED |
Os campos PII são decifrados para uma base de dados temporária antes do arquivamento. Os hashes das palavras-passe dos utilizadores permanecem inalterados. Requer a cifragem do arquivo AGE_RECIPIENT. Útil para a portabilidade entre instâncias. |
Ao restaurar um backup PII_DECRYPTED num destino com ENCRYPT_PII=true, o processo de restauração volta a cifrar automaticamente as PII com a DB_ENCRYPTION_KEY do destino antes do arranque normal da aplicação.
Kit de recuperação
Durante a configuração, o administrador gera (ou importa) um destinatário age para os backups cifrados. O kit de recuperação é um ficheiro ZIP que contém:
quotenode-age-identity.txt— a identidade age privada (devolvida apenas uma vez)quotenode-age-recipient.txt— o destinatário público e a impressão digitalquotenode-backup-verify.sh— script de verificação local (Linux/macOS)quotenode-backup-verify.ps1— script de verificação local (Windows)README.md— comandos de verificação e restauração
Crítico: a identidade age privada é devolvida apenas uma vez durante a geração do kit. Se for perdida, os arquivos cifrados não poderão ser decifrados. Guarde o kit de recuperação num local offline seguro.
O administrador tem de confirmar que o kit foi guardado e testado antes de o assistente de configuração marcar o backup como pronto para produção.
Verificação local de backups
Os backups transferidos podem ser verificados fora da aplicação em execução através dos scripts do kit de recuperação:
scripts/quotenode-backup-verify.sh \
--archive /path/backup.tar.age \
--identity /path/quotenode-age-identity.txt \
--expected-sha256 <sha256-from-ui-or-sidecar>
O verificador:
- Verifica a soma de verificação SHA-256 do arquivo cifrado em relação ao valor esperado ou ao ficheiro acompanhante
.sha256. - Decifra com
age -dpara um diretório temporário privado. - Valida as entradas tar (rejeita caminhos absolutos,
.., ligações simbólicas e ficheiros de dispositivo). - Verifica se
backup-manifest.jsonexiste e tem uma versão suportada. - Executa
sha256sum -c checksums.sha256. - Executa
pg_restore --list db.dumpquando opg_restoreestá disponível. - Remove por predefinição os dados temporários decifrados (use
--keep-decryptedpara os manter).
Backup online (predefinido)
Os backups online são executados enquanto a aplicação atende pedidos. Não há tempo de inatividade.
- O
pg_dumpem formato personalizado cria um instantâneo transacionalmente consistente sem bloquear tabelas nem consultas. - O armazenamento de ficheiros é arquivado em paralelo — os ficheiros carregados e os PDF são imutáveis após a criação, pelo que o arquivo é sempre consistente.
- O PostgreSQL não precisa de parar para produzir um dump consistente da base de dados.
Como são executados os backups: escolher uma topologia
Existem duas formas de executar continuamente os backups agendados. Ambas produzem arquivos idênticos — diferem apenas em onde a tarefa de backup é executada.
| Topologia | Quando usar | Contentores |
|---|---|---|
| Worker dedicado (predefinido) | Produção. Os backups são executados num contentor backup-worker separado, pelo que nunca competem com o tráfego web por memória ou CPU. |
backend web + backup-worker |
| In-process | Configurações próprias com um único backend e ficheiro Compose próprio (os pacotes da versão não o usam). O backend web executa também os backups — um contentor a menos para operar. | apenas backend web |
A própria tarefa de backup é o mesmo pipeline de shell (pg_dump → arquivamento → cifragem) em ambos os casos, executado fora do heap da JVM, pelo que o seu custo de memória é modesto.
Como selecionar uma topologia
Duas variáveis de ambiente funcionam em conjunto:
JOBS_MODEdecide qual contentor executa efetivamente a tarefa de backup agendada.BACKUP_RUNTIME_PROFILEé um rótulo registado nos registos e manifestos dos backups, para que possa ver, a posteriori, como cada backup foi produzido.
| Topologia | Backend web | Backup worker |
|---|---|---|
| Worker dedicado (predefinido) | JOBS_MODE=web + BACKUP_RUNTIME_PROFILE=WORKER |
contentor JOBS_MODE=backup-only |
| In-process | JOBS_MODE=all + BACKUP_RUNTIME_PROFILE=WEB_MAINTENANCE |
(nenhum) |
Os pacotes da versão usam a topologia de worker dedicado em todas as instalações (servidor, LAN, portátil, NAS e Coolify): ambos os ficheiros Compose incluem um serviço
backup-workere definemJOBS_MODEpor serviço. No pacote autónomo esta definição do Compose prevalece sobre o.env, pelo que o modo in-process (JOBS_MODE=all+BACKUP_RUNTIME_PROFILE=WEB_MAINTENANCE) exige um ficheiro Compose mantido por si.
Referência dos perfis de runtime
BACKUP_RUNTIME_PROFILE aceita quatro valores. Os dois primeiros são para as topologias contínuas acima; os dois últimos para backups pontuais geridos pelo operador.
| Perfil | Descrição |
|---|---|
WORKER |
Predefinido. Um contentor backup-worker permanente executa os backups agendados através de cron. |
WEB_MAINTENANCE |
O backend web executa diretamente os backups agendados. Não é necessário nenhum contentor worker adicional. |
ONE_SHOT |
Um cron externo ou operador executa operator/backup-one-shot.sh e termina. Sem worker permanente. |
OFFLINE_MAINTENANCE |
Um script automatizado anuncia o tempo de inatividade, para frontend/backend/backup-worker, mantém o PostgreSQL em execução, executa o backup, reinicia os serviços e verifica o estado. |
Backup pontual (one-shot)
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT \
BACKUP_AGE_RECIPIENT=age1... \
./operator/backup-one-shot.sh
Manutenção offline
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
BACKUP_OFFLINE_NOTICE_SECONDS=300 \
./operator/backup-offline-maintenance.sh
O script de manutenção offline:
- Anuncia uma manutenção agendada (período de tolerância configurável).
- Ativa opcionalmente uma página de manutenção estática enquanto os serviços estão inativos.
- Para o frontend, o backend e o backup-worker (mantém o PostgreSQL em execução).
- Executa um backup pontual.
- Reinicia todos os serviços.
- Verifica o estado do backend.
- Escreve um diário de manutenção JSONL ao nível do host.
Se o script falhar em qualquer ponto, um trap de segurança reinicia automaticamente os serviços.
Use --dry-run para pré-visualizar o plano sem o executar:
./operator/backup-offline-maintenance.sh --dry-run
Agendamento
- Agendamento predefinido: todos os dias às 2:00 (
0 0 2 * * *, configurável através deBACKUP_CRON) - Ativação (dois interruptores): os backups agendados só são executados quando ambos
BACKUP_ENABLED=trueeBACKUP_SCHEDULER_ENABLED=trueestão definidos.BACKUP_SCHEDULER_ENABLEDé um interruptor de corte dedicado, desativado por predefinição, para que ativar os backups nunca provoque uma primeira execução agendada inesperada. Defina-o apenas no backup-worker (perfil de tempo de execuçãoWORKER/WEB_MAINTENANCE), nunca no nível web. - Acionamento manual: os administradores podem acionar um backup imediato a partir do painel de administração ou através da API (
POST /api/v1/admin/backup/trigger). O acionador responde de imediato (HTTP 202) enquanto o backup é executado de forma assíncrona. - Proteção contra concorrência: um bloqueio suportado pela base de dados garante que apenas um backup é executado de cada vez em todos os workers e acionamentos manuais.
Para os perfis ONE_SHOT e OFFLINE_MAINTENANCE, o agendador interno está desativado — os backups são geridos externamente.
Opções de armazenamento
Armazenamento local (predefinido)
Os backups são guardados em BACKUP_LOCAL_DIR (predefinição: /app/data/backups), mapeado para um volume Docker.
Em produção, os backups locais devem ser complementados com cópias remotas.
Armazenamento remoto via rclone
Se BACKUP_RCLONE_REMOTE estiver configurado, os backups são automaticamente carregados para um destino remoto após a criação local. O rclone suporta mais de 70 fornecedores de armazenamento na cloud, incluindo os compatíveis com S3, Google Cloud Storage, Azure Blob, SFTP e WebDAV.
Transferência de backups
A transferência de arquivos de backup requer autorização reforçada (step-up):
- Navegue até Definições > Backup.
- Clique em Transferir na entrada do backup.
- Introduza a sua palavra-passe atual (e o código TOTP, se a MFA estiver ativada).
- O sistema emite uma concessão de transferência de utilização única e de curta duração (predefinição: 120 segundos).
- O arquivo é transferido automaticamente.
O token de concessão é guardado apenas como hash SHA-256. A criação da concessão e a transferência são auditadas e os restantes administradores são notificados.
Nota: uma transferência direta sem concessão devolve 403. Os backups em armazenamento remoto não podem ser transferidos através do painel de administração.
Metadados e trilho de auditoria
Cada backup é registado na tabela backup_logs com:
- Estado (RUNNING, SUCCESS, FAILED)
- Iniciado por (SCHEDULER ou ADMIN)
- Hora de início/conclusão
- Tamanho (bytes) e soma de verificação SHA-256
- Destino (caminho local ou URL remoto)
- Versão do manifesto e versão da app de origem
- Modo de cifragem do arquivo e impressão digital
- Modo de payload da base de dados
- Perfil de runtime
- Estado de verificação (NOT_RUN, PASSED, FAILED, SKIPPED_TIMEOUT)
- Estado do teste de restauração e estado de compatibilidade de restauração
Restauração
Utilização de operator/restore.sh
O script de restauração canónico gere todo o ciclo de vida:
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE_PATH=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
DB_USERNAME="$(grep '^DB_USERNAME=' .env | cut -d= -f2-)" \
DB_NAME="$(grep '^DB_NAME=' .env | cut -d= -f2-)" \
DB_PASSWORD="$(grep '^DB_PASSWORD=' .env | cut -d= -f2-)" \
RESTORE_JOURNAL_DIR=$PWD/restore-journal \
RESTORE_AGE_IDENTITY_FILE=/path/to/quotenode-age-identity.txt \
[email protected] \
RESTORE_ADMIN_PASSWORD_FILE=/path/to/password \
./operator/restore.sh /path/to/backup.tar.age
O script:
- Extrai e valida o arquivo (manifesto, somas de verificação, segurança das entradas tar).
- Executa verificações preliminares (capacidade de disco, versão do PostgreSQL, conectividade à base de dados).
- Cria um backup de segurança do destino antes de qualquer operação destrutiva.
- Escreve um diário de restauração ao nível do host (JSONL, sobrevive à substituição da base de dados).
- Restaura a base de dados.
- Prepara os ficheiros num diretório temporário e troca-os no lugar.
- Preserva a identidade do destino (ID de instância, metadados de cifragem dos backups, estado da licença).
- Limpa sessões, ligações públicas de propostas e tokens de notificação.
- Repõe ou força a alteração do acesso de administrador.
- Volta a cifrar as PII se o backup for
PII_DECRYPTEDe o destino tiverENCRYPT_PII=true.
Restauração entre instâncias
Ao restaurar um backup de uma instalação diferente, o modo predefinido é PRESERVE_TARGET_IDENTITY:
- O ID de instância de destino, o destinatário age dos backups, os metadados do kit de recuperação e o estado da licença são preservados.
- As sessões, as ligações públicas de propostas e os tokens de notificação são limpos.
- A palavra-passe de administrador é reposta/é forçada a sua alteração.
- Os dados de negócio são totalmente substituídos (sem fusão).
Compatibilidade de restauração
A verificação preliminar da restauração valida:
- Backup mais antigo numa app mais recente: permitido (compatível).
- Backup mais recente numa app mais antiga: bloqueado.
- Manifesto em falta: bloqueado.
- Impressão digital de chave de cifragem incorreta para um payload
APP_ENCRYPTED: bloqueado antes do trabalho destrutivo. PII_DECRYPTEDsem cifragem do arquivo: bloqueado.
Decisões de recuperação e ações seguras
As decisões da política de restauro vêm de um único motor e devolvem reason codes estáveis; um resultado bloqueado não altera nada.
- APP_ENCRYPTED sobre uma chave diferente, sem chave de origem →
SOURCE_DB_ENCRYPTION_KEY_REQUIRED. Forneça a chave original viaPII_REKEY_OLD_KEY(variável de ambiente, nunca em argv) para fazer o rekey. - Chave de origem incorreta →
SOURCE_DB_ENCRYPTION_KEY_MISMATCH. Forneça a chave original correta; não gere uma de substituição. - Destino com PII em texto simples, sem confirmação →
PLAINTEXT_PII_TARGET_NOT_ACKNOWLEDGED. DefinaRESTORE_ACKNOWLEDGE_PLAINTEXT_PII=trueapenas se a PII em texto simples em repouso for intencional. - Sem chave de origem verificada (apenas PII_DECRYPTED) → os segredos operacionais só podem ser REPOSTOS. Defina
RESTORE_ACKNOWLEDGE_OPERATIONAL_SECRET_RESET=truepara aceitar. - Identidade AGE incorreta / falha de integridade → o arquivo não é aberto e nada é alterado.
Consequências da reposição dos segredos operacionais (se aceite): os registos MFA são repostos e os utilizadores têm de os reconfigurar; o SMTP é limpo e o e-mail de saída permanece desativado até à reconfiguração; os payloads de offer-email não recuperáveis são removidos e não podem ser reenviados. FEATURE_2FA_ENABLED=false é apenas um break-glass de emergência temporário, nunca uma definição normal.
Semântica do resultado do restauro:
- Sucesso — BD + ficheiros restaurados, pós-processamento cripto concluído, e só então a app pode servir tráfego.
- Recusa antes da mutação — uma política bloqueada ou um preflight falhado deixam o destino inalterado.
- Rollback bem-sucedido — uma falha após a mutação reverte a BD + ficheiros em conjunto a partir do backup de segurança do destino.
- Rollback falhado — a aplicação fica deliberadamente PARADA com todos os artefactos de recuperação preservados; recupere a partir do arquivo de segurança.
Não faça: gerar uma DB_ENCRYPTION_KEY de substituição aleatória; passar qualquer segredo como argumento de linha de comandos; nem iniciar a aplicação web antes de o pós-processamento cripto terminar.
Garantia de acesso de administrador
A restauração garante o acesso de administrador através de uma das seguintes opções:
RESTORE_ADMIN_PASSWORD_FILE— palavra-passe fornecida pelo operador (definida comforcePasswordChange=true)RESTORE_ADMIN_PASSWORD— apenas para utilização local/de teste- Token de reposição de utilização única gerado automaticamente — impresso na consola e no diário ao nível do host
Execução de teste (dry run)
RESTORE_DRY_RUN=true ./operator/restore.sh /path/to/backup.tar.age
Valida o arquivo, verifica as somas de verificação e o manifesto e comunica o plano de restauração sem modificar nada.
Recuperação de desastres — reconstrução do zero
O seu servidor desapareceu. Tem um arquivo de backup (.tar.age ou .tar) e um novo servidor com Docker. Eis como restaurar.
Passo 1 — Preparar o novo servidor
mkdir quotenode && cd quotenode
Configure docker-compose.yml e .env conforme descrito no Guia de instalação.
Crítico para os backups APP_ENCRYPTED: o mais simples é restaurar com a mesma
DB_ENCRYPTION_KEY. Restaurar sobre uma chave diferente continua a funcionar se fornecer a chave original viaPII_REKEY_OLD_KEYpara uma recifragem. Sem a chave original, as PIIAPP_ENCRYPTEDnão são recuperáveis (apenas um arquivoPII_DECRYPTEDo é, e os seus segredos operacionais terão então de ser repostos) — nunca gere uma chave de substituição aleatória.
Crítico para os arquivos cifrados: precisa do ficheiro de identidade privada do kit de recuperação (
quotenode-age-identity.txt) para decifrar o arquivo.
Passo 2 — Copiar o backup e o script de restauração
scp backup.tar.age user@new-server:~/quotenode/
# operator/restore.sh comes with the release package (the release that created the backup, or a later one)
curl -fsSLO https://quotenode.dev/releases/v0.9.8-alpha/quotenode-deploy-v0.9.8-alpha.tar.gz
tar -xzf quotenode-deploy-v0.9.8-alpha.tar.gz --strip-components=1
Passo 3 — Executar a restauração
# Only a successful restore starts the remaining services (the restore itself starts PostgreSQL, the backend and
# the frontend). On failure nothing else starts and the restore's exit status is kept: read its message.
# Default installations keep PII unencrypted at rest (ENCRYPT_PII=false); a restore into such a target requires the
# explicit RESTORE_ACKNOWLEDGE_PLAINTEXT_PII acknowledgement below, for this command only. A target with
# ENCRYPT_PII=true in .env does not use it.
export COMPOSE_PROJECT_NAME=quotenode
COMPOSE_FILE_PATH=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
DB_USERNAME="$(grep '^DB_USERNAME=' .env | cut -d= -f2-)" \
DB_NAME="$(grep '^DB_NAME=' .env | cut -d= -f2-)" \
DB_PASSWORD="$(grep '^DB_PASSWORD=' .env | cut -d= -f2-)" \
RESTORE_JOURNAL_DIR=$PWD/restore-journal \
RESTORE_AGE_IDENTITY_FILE=./quotenode-age-identity.txt \
[email protected] \
RESTORE_ADMIN_PASSWORD_FILE=./admin-password \
RESTORE_ACKNOWLEDGE_PLAINTEXT_PII=true \
./operator/restore.sh --fresh-install backup.tar.age \
&& docker compose up -d
Se a reposição indicar uma falha, não inicies o QuoteNode à mão: arrancaria uma instalação vazia ou reposta só em parte. Lê a mensagem, corrige a causa (por exemplo, o ficheiro de identidade ou DB_ENCRYPTION_KEY) e executa o bloco de novo. Se a reposição indicar que deixou a aplicação parada com os artefactos de recuperação preservados, segue Decisões de recuperação e ações seguras acima.
Passo 4 — Verificar
Abra o seu domínio e inicie sessão. Todos os clientes, propostas, produtos e definições deverão estar exatamente como estavam no momento do backup.
Recuperação de desastres testada
O percurso completo de backup → restauro isolado é exercitado de ponta a ponta como um exercício automatizado de recuperação de desastres (cenários A–G): restauro com a mesma chave, recifragem para uma chave diferente, confirmação de PII em texto simples, reposição dos segredos operacionais, recusa em caso de identidade incorreta e rollback após o restauro. É executado contra um PostgreSQL real num ambiente descartável e verifica as garantias de rollback e de chaves descritas acima.
Retenção de backups
- Local: são mantidos os
BACKUP_RETENTION_DAILY(predefinição: 7) backups bem-sucedidos mais recentes. - Remoto: configure políticas de ciclo de vida no seu fornecedor de armazenamento.
- Os backups com PII decifradas devem ter uma retenção mais rigorosa devido à sua natureza sensível.
Tempo limite do backup
Cada backup tem um tempo limite configurável (predefinição: 30 minutos através de BACKUP_TIMEOUT_MINUTES). Se for excedido, o backup é terminado e registado como FAILED.
Estratégia recomendada
- Ative backups automáticos diários com cifragem
AGE_RECIPIENTe armazenamento remoto. - Gere um kit de recuperação durante a configuração e guarde-o num local offline seguro.
- Verifique o seu kit de recuperação em relação a um backup real usando os scripts de verificação incluídos.
- Teste periodicamente os procedimentos de restauração — um backup que nunca foi testado não é um backup.
- Transfira um backup pelo menos uma vez por mês para um local offline (requer autorização reforçada).
- Monitorize o estado dos backups no painel de administração — surgem avisos para backups desatualizados, falhados ou não cifrados.
- Mantenha pelo menos 7 dias de histórico de backups (a predefinição).