Backup e Recovery
Este documento ensina como implementar backup e recovery para n8n, incluindo backup automático de workflows, export/import de credenciais, versionamento de configurações, recuperação point-in-time, testes de restauração, e estratégias de disaster recovery que garantem proteção completa dos dados críticos e continuidade operacional mesmo em cenários catastróficos de perda de dados ou infraestrutura.
Estratégia 3-2-1
Implemente a estratégia 3-2-1 para proteção máxima:
- 3 cópias dos dados
- 2 tipos de mídia diferentes
- 1 cópia fora do local
Backup de Banco de Dados
PostgreSQL
#!/bin/bash
# Configurações
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="n8n"
DB_USER="n8n"
DB_PASSWORD="n8n"
BACKUP_DIR="/backups/n8n/database"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/n8n_db_$DATE.sql"
RETENTION_DAYS=30
echo "Iniciando backup do PostgreSQL..."
pg_dump -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME > $BACKUP_FILE
if [ $? -eq 0 ]; then
echo "Backup criado com sucesso: $BACKUP_FILE"
# Comprimir backup
gzip $BACKUP_FILE
echo "Backup comprimido: $BACKUP_FILE.gz"
# Calcular tamanho do backup
BACKUP_SIZE=$(du -h "$BACKUP_FILE.gz" | cut -f1)
echo "Tamanho do backup: $BACKUP_SIZE"
# Remover backups antigos
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backups antigos removidos (mais de $RETENTION_DAYS dias)"
# Log do backup
echo "$(date): Backup PostgreSQL criado - $BACKUP_FILE.gz ($BACKUP_SIZE)" >> /var/log/n8n/backup.log
else
echo "ERRO: Falha no backup do PostgreSQL"
exit 1
fi
Backup Incremental
#!/bin/bash
# Configurações
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="n8n"
DB_USER="n8n"
BACKUP_DIR="/backups/n8n/database/incremental"
DATE=$(date +%Y%m%d_%H%M%S)
echo "Iniciando backup incremental..."
pg_basebackup -h $DB_HOST -p $DB_PORT -U $DB_USER -D $BACKUP_DIR/base_$DATE
echo "Backup incremental criado: $BACKUP_DIR/base_$DATE"
MySQL
#!/bin/bash
# Configurações
DB_HOST="localhost"
DB_PORT="3306"
DB_NAME="n8n"
DB_USER="n8n"
DB_PASSWORD="n8n"
BACKUP_DIR="/backups/n8n/database"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/n8n_db_$DATE.sql"
RETENTION_DAYS=30
echo "Iniciando backup do MySQL..."
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD \
--single-transaction \
--routines \
--triggers \
--events \
$DB_NAME > $BACKUP_FILE
if [ $? -eq 0 ]; then
echo "Backup criado com sucesso: $BACKUP_FILE"
# Comprimir backup
gzip $BACKUP_FILE
echo "Backup comprimido: $BACKUP_FILE.gz"
# Calcular tamanho do backup
BACKUP_SIZE=$(du -h "$BACKUP_FILE.gz" | cut -f1)
echo "Tamanho do backup: $BACKUP_SIZE"
# Remover backups antigos
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backups antigos removidos (mais de $RETENTION_DAYS dias)"
# Log do backup
echo "$(date): Backup MySQL criado - $BACKUP_FILE.gz ($BACKUP_SIZE)" >> /var/log/n8n/backup.log
else
echo "ERRO: Falha no backup do MySQL"
exit 1
fi
Backup de Workflows
Script de Backup de Workflows
#!/bin/bash
# Configurações
N8N_URL="https://seudominio.com"
API_KEY="sua_api_key"
BACKUP_DIR="/backups/n8n/workflows"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/workflows_$DATE.json"
RETENTION_DAYS=30
echo "Iniciando backup de workflows..."
curl -H "X-N8N-API-KEY: $API_KEY" \
"$N8N_URL/api/v1/workflows" \
| jq '.' > $BACKUP_FILE
if [ $? -eq 0 ]; then
echo "Backup de workflows criado: $BACKUP_FILE"
# Comprimir backup
gzip $BACKUP_FILE
echo "Backup comprimido: $BACKUP_FILE.gz"
# Calcular tamanho do backup
BACKUP_SIZE=$(du -h "$BACKUP_FILE.gz" | cut -f1)
echo "Tamanho do backup: $BACKUP_SIZE"
# Remover backups antigos
find $BACKUP_DIR -name "*.json.gz" -mtime +$RETENTION_DAYS -delete
echo "Backups antigos removidos (mais de $RETENTION_DAYS dias)"
# Log do backup
echo "$(date): Backup de workflows criado - $BACKUP_FILE.gz ($BACKUP_SIZE)" >> /var/log/n8n/backup.log
else
echo "ERRO: Falha no backup de workflows"
exit 1
fi
Script de Backup de Credenciais
#!/bin/bash
# Configurações
N8N_URL="https://seudominio.com"
API_KEY="sua_api_key"
BACKUP_DIR="/backups/n8n/credentials"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/credentials_$DATE.json"
RETENTION_DAYS=30
echo "Iniciando backup de credenciais..."
curl -H "X-N8N-API-KEY: $API_KEY" \
"$N8N_URL/api/v1/credentials" \
| jq '.' > $BACKUP_FILE
if [ $? -eq 0 ]; then
echo "Backup de credenciais criado: $BACKUP_FILE"
# Comprimir backup
gzip $BACKUP_FILE
echo "Backup comprimido: $BACKUP_FILE.gz"
# Calcular tamanho do backup
BACKUP_SIZE=$(du -h "$BACKUP_FILE.gz" | cut -f1)
echo "Tamanho do backup: $BACKUP_SIZE"
# Remover backups antigos
find $BACKUP_DIR -name "*.json.gz" -mtime +$RETENTION_DAYS -delete
echo "Backups antigos removidos (mais de $RETENTION_DAYS dias)"
# Log do backup
echo "$(date): Backup de credenciais criado - $BACKUP_FILE.gz ($BACKUP_SIZE)" >> /var/log/n8n/backup.log
else
echo "ERRO: Falha no backup de credenciais"
exit 1
fi
Backup de Volumes Docker
#!/bin/bash
# Configurações
VOLUME_NAME="n8n_data"
BACKUP_DIR="/backups/n8n/volumes"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/n8n_volume_$DATE.tar.gz"
RETENTION_DAYS=30
echo "Parando container n8n..."
docker stop n8n
echo "Iniciando backup do volume Docker..."
docker run --rm -v $VOLUME_NAME:/data -v $BACKUP_DIR:/backup \
alpine tar czf /backup/n8n_volume_$DATE.tar.gz -C /data .
echo "Reiniciando container n8n..."
docker start n8n
if [ $? -eq 0 ]; then
echo "Backup do volume criado: $BACKUP_FILE"
# Calcular tamanho do backup
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "Tamanho do backup: $BACKUP_SIZE"
# Remover backups antigos
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backups antigos removidos (mais de $RETENTION_DAYS dias)"
# Log do backup
echo "$(date): Backup de volume criado - $BACKUP_FILE ($BACKUP_SIZE)" >> /var/log/n8n/backup.log
else
echo "ERRO: Falha no backup do volume"
exit 1
fi
Backup na Nuvem
AWS S3
#!/bin/bash
# Configurações
S3_BUCKET="n8n-backups"
S3_REGION="us-east-1"
BACKUP_DIR="/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=90
echo "Iniciando backup para S3..."
# Backup de banco de dados
aws s3 cp $BACKUP_DIR/database/ s3://$S3_BUCKET/database/ --recursive
# Backup de workflows
aws s3 cp $BACKUP_DIR/workflows/ s3://$S3_BUCKET/workflows/ --recursive
# Backup de credenciais
aws s3 cp $BACKUP_DIR/credentials/ s3://$S3_BUCKET/credentials/ --recursive
# Configurar lifecycle para remoção automática
aws s3api put-bucket-lifecycle-configuration \
--bucket $S3_BUCKET \
--lifecycle-configuration '{
"Rules": [
{
"ID": "DeleteOldBackups",
"Status": "Enabled",
"Filter": {
"Prefix": ""
},
"Expiration": {
"Days": '$RETENTION_DAYS'
}
}
]
}'
echo "Backup para S3 concluído"
Google Cloud Storage
#!/bin/bash
# Configurações
GCS_BUCKET="n8n-backups"
BACKUP_DIR="/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=90
echo "Iniciando backup para Google Cloud Storage..."
# Backup de banco de dados
gsutil -m cp $BACKUP_DIR/database/* gs://$GCS_BUCKET/database/
# Backup de workflows
gsutil -m cp $BACKUP_DIR/workflows/* gs://$GCS_BUCKET/workflows/
# Backup de credenciais
gsutil -m cp $BACKUP_DIR/credentials/* gs://$GCS_BUCKET/credentials/
# Configurar lifecycle para remoção automática
gsutil lifecycle set lifecycle.json gs://$GCS_BUCKET
echo "Backup para GCS concluído"
Restauração
Restauração de Banco de Dados
#!/bin/bash
# Configurações
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="n8n"
DB_USER="n8n"
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "Uso: $0 <arquivo_backup>"
exit 1
fi
# Verificar se arquivo existe
if [ ! -f "$BACKUP_FILE" ]; then
echo "ERRO: Arquivo de backup não encontrado: $BACKUP_FILE"
exit 1
fi
echo "Iniciando restauração do PostgreSQL..."
# Parar n8n
echo "Parando n8n..."
docker stop n8n
# Criar backup de segurança
echo "Criando backup de segurança..."
pg_dump -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME > \
/backups/n8n/pre_restore_backup_$(date +%Y%m%d_%H%M%S).sql
# Descomprimir se necessário
if [[ "$BACKUP_FILE" == *.gz ]]; then
echo "Descomprimindo backup..."
gunzip -c "$BACKUP_FILE" > "${BACKUP_FILE%.gz}"
BACKUP_FILE="${BACKUP_FILE%.gz}"
fi
# Restaurar backup
echo "Restaurando backup..."
psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME < "$BACKUP_FILE"
if [ $? -eq 0 ]; then
echo "Restauração concluída com sucesso"
# Reiniciar n8n
echo "Reiniciando n8n..."
docker start n8n
# Log da restauração
echo "$(date): Restauração PostgreSQL concluída - $BACKUP_FILE" >> /var/log/n8n/restore.log
else
echo "ERRO: Falha na restauração"
exit 1
fi
Restauração de Workflows
#!/bin/bash
# Configurações
N8N_URL="https://seudominio.com"
API_KEY="sua_api_key"
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "Uso: $0 <arquivo_backup>"
exit 1
fi
# Verificar se arquivo existe
if [ ! -f "$BACKUP_FILE" ]; then
echo "ERRO: Arquivo de backup não encontrado: $BACKUP_FILE"
exit 1
fi
echo "Iniciando restauração de workflows..."
# Descomprimir se necessário
if [[ "$BACKUP_FILE" == *.gz ]]; then
echo "Descomprimindo backup..."
gunzip -c "$BACKUP_FILE" > "${BACKUP_FILE%.gz}"
BACKUP_FILE="${BACKUP_FILE%.gz}"
fi
# Restaurar workflows
echo "Restaurando workflows..."
jq -c '.[]' "$BACKUP_FILE" | while read workflow; do
curl -X POST \
-H "X-N8N-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d "$workflow" \
"$N8N_URL/api/v1/workflows"
if [ $? -eq 0 ]; then
echo "Workflow restaurado com sucesso"
else
echo "ERRO: Falha na restauração do workflow"
fi
done
echo "Restauração de workflows concluída"
# Log da restauração
echo "$(date): Restauração de workflows concluída - $BACKUP_FILE" >> /var/log/n8n/restore.log
Disaster Recovery
Cenários de Desastre
#!/bin/bash
# Cenários comuns de desastre
DISASTER_SCENARIOS=(
"Perda de servidor principal"
"Corrupção de banco de dados"
"Falha de storage"
"Desastre natural"
"Ataque cibernético"
"Erro humano"
)
Script de Disaster Recovery
#!/bin/bash
# Configurações
PRIMARY_SERVER="n8n.empresa.com"
BACKUP_SERVER="n8n-backup.empresa.com"
S3_BUCKET="n8n-backups"
LATEST_BACKUP=$(aws s3 ls s3://$S3_BUCKET/database/ | sort | tail -1 | awk '{print $4}')
echo "Iniciando Disaster Recovery..."
# 1. Verificar conectividade
echo "Verificando conectividade..."
if ! ping -c 3 $PRIMARY_SERVER > /dev/null; then
echo "Servidor primário indisponível, iniciando DR..."
# 2. Provisionar servidor de backup
echo "Provisionando servidor de backup..."
# Aqui você incluiria comandos para provisionar infraestrutura
# 3. Restaurar banco de dados
echo "Restaurando banco de dados..."
aws s3 cp s3://$S3_BUCKET/database/$LATEST_BACKUP /tmp/
gunzip /tmp/$LATEST_BACKUP
psql -h localhost -U n8n -d n8n < /tmp/${LATEST_BACKUP%.gz}
# 4. Restaurar workflows
echo "Restaurando workflows..."
aws s3 cp s3://$S3_BUCKET/workflows/ /tmp/workflows/ --recursive
# 5. Configurar DNS
echo "Atualizando DNS..."
# Comandos para atualizar DNS
# 6. Verificar funcionalidade
echo "Verificando funcionalidade..."
curl -f https://$BACKUP_SERVER/healthz
if [ $? -eq 0 ]; then
echo "Disaster Recovery concluído com sucesso"
# Notificar equipe
curl -X POST $WEBHOOK_URL \
-H "Content-type: application/json" \
-d '{"text":"✅ Disaster Recovery concluído - n8n disponível em backup"}'
else
echo "ERRO: Falha no Disaster Recovery"
exit 1
fi
else
echo "Servidor primário está funcionando"
fi
Testes de Restauração
Script de Teste
#!/bin/bash
# Configurações
BACKUP_FILE="$1"
TEST_DB="n8n_test"
if [ -z "$BACKUP_FILE" ]; then
echo "Uso: $0 <arquivo_backup>"
exit 1
fi
echo "Iniciando teste de restauração..."
# Criar ambiente de teste
echo "Criando ambiente de teste..."
docker run -d --name $TEST_ENV \
-e DB_TYPE=postgresdb \
-e DB_POSTGRESDB_HOST=localhost \
-e DB_POSTGRESDB_DATABASE=$TEST_DB \
-p 5679:5678 \
n8nio/n8n:latest
# Aguardar inicialização
echo "Aguardando inicialização..."
sleep 30
# Restaurar backup de teste
echo "Restaurando backup de teste..."
gunzip -c "$BACKUP_FILE" | psql -h localhost -U n8n -d $TEST_DB
# Verificar restauração
echo "Verificando restauração..."
WORKFLOW_COUNT=$(curl -s http://localhost:5679/api/v1/workflows | jq '. | length')
echo "Workflows restaurados: $WORKFLOW_COUNT"
# Testar funcionalidade
echo "Testando funcionalidade..."
curl -f http://localhost:5679/healthz
if [ $? -eq 0 ]; then
echo "✅ Teste de restauração PASSOU"
# Limpar ambiente de teste
docker stop $TEST_ENV
docker rm $TEST_ENV
psql -h localhost -U n8n -c "DROP DATABASE $TEST_DB;"
else
echo "❌ Teste de restauração FALHOU"
exit 1
fi
Limpeza Automática
#!/bin/bash
# Configurações
BACKUP_DIR="/backups/n8n"
RETENTION_DAYS=30
CLOUD_RETENTION_DAYS=90
echo "Iniciando limpeza de backups antigos..."
# Limpar backups locais
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.json.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
# Limpar backups na nuvem
aws s3 ls s3://n8n-backups/ | \
awk '$1 < "'$(date -d "$CLOUD_RETENTION_DAYS days ago" +%Y-%m-%d)'" {print $4}' | \
xargs -I {} aws s3 rm s3://n8n-backups/{}
echo "Limpeza concluída"
Checklist de Backup
Configuração
- Estratégia 3-2-1 implementada
- Scripts de backup criados
- Automação com cron configurada
- Backup na nuvem configurado
- Retenção de backups definida
Recuperação
- Scripts de restauração criados
- Testes de restauração realizados
- Plano de DR documentado
- RTO e RPO definidos
- Procedimentos de recuperação testados
Monitoramento
- Logs de backup configurados
- Alertas de falha configurados
- Métricas de backup coletadas
- Relatórios de backup gerados
- Verificação de integridade implementada
Documentação
- Procedimentos documentados
- Contatos de emergência definidos
- Matriz de responsabilidades
- Plano de comunicação
- Exercícios de DR realizados
Próximos Passos
- Configure automação de backups
- Teste restaurações regularmente
- Monitore integridade dos backups
- Documente procedimentos de DR
Dica Pro
Teste restaurações regularmente em ambiente isolado para garantir que seus backups são funcionais.
Importante
Mantenha múltiplas cópias de backup em locais diferentes e teste procedimentos de restauração antes de precisar deles.