Dia 14: Backups e Recuperação em Linux — rsync e BorgBackup

No Dia 13 automatizámos tarefas com cron e systemd timers. Hoje, Dia 14, atacamos o tema que separa sysadmins amadores de profissionais: backups e recuperação. Um servidor sem uma estratégia de backup testada é um incidente à espera de acontecer — não uma questão de “se”, mas de “quando”.

Vamos cobrir a estratégia 3-2-1, o clássico rsync com --link-dest para incrementais via hard links, tar com compressão, dump/restore para ext4, e o moderno BorgBackup com deduplicação e compressão embutidas. No fim, tens um sistema de backup automático, verificado e testado.

Neste artigo

Estratégia 3-2-1: A Regra de Ouro dos Backups

A regra 3-2-1 é o padrão da indústria para resiliência de dados, recomendada por organismos como a Arch Wiki e seguida por sysadmins desde os anos 90. O conceito é simples:

Componente Significado Exemplo Prático
3 cópias dos dados Original + 2 backups independentes Servidor + NAS local + disco externo
2 tipos de suporte diferentes Reduz risco de falha comum do mesmo tipo de media Disco HDD + LTO tape, ou HDD + SSD
1 cópia fora do local Protege contra roubo, incêndio, inundação, ransomware NAS remoto, cloud, cofre físico

ℹ Extensão 3-2-1-1-0: A variação moderna adiciona 1 cópia imutável (offline ou com immutable storage) e 0 erros após verificação. Em ambientes com ransomware, a cópia imutável é o que garante recuperação mesmo quando o atacante compromete o servidor de backups. Já abordámos este tema no artigo Ransomware 2026: Backup 3-2-1 Imutável.

Tipos de Backup

Antes de escolher ferramentas, compreender os três tipos fundamentais:

Tipo O que Copia Vantagem Desvantagem
Completo Todos os ficheiros Restauro simples e rápido Lento, consome muito espaço
Incremental Apenas mudanças desde o último backup Rápido, pouco espaço Restauro exige cadeia completa
Diferencial Mudanças desde o último completo Restauro mais rápido que incremental Cresce ao longo do ciclo

rsync: Sincronização Eficiente e Backups Incrementais

O rsync é a ferramenta de transferência de ficheiros mais eficiente em Linux. Em vez de copiar tudo, compara origem e destino e transfere apenas os blocos que diferem — usando o algoritmo Rsync de Andrew Tridgell. Para backups, é a base de quase todas as soluções Linux.

Sintaxe Essencial: -avz

# Sincronizar directoria local para destino
rsync -avz /home/user/documentos/ /backup/documentos/

# -a  archive mode (preserva permissões, timestamps, symlinks, etc.)
# -v  verbose (mostra progresso)
# -z  compressão durante transferência (rede)

A flag -a (archive) é o ponto de partida — equivale a -rlptgoD (recursive, links, perms, times, group, owner, devices). É o que garante que o destino é uma réplica exacta da origem.

✓ Barra final importa: rsync -avz /src/ /dst/ copia o conteúdo de /src/ para /dst/. Sem a barra — rsync -avz /src /dst/ — cria /dst/src/. Esta é a causa #1 de confusão com rsync.

–delete: Espelhar Exactamente a Origem

# Espelhar: remove no destino o que já não existe na origem
rsync -avz --delete /home/user/documentos/ /backup/documentos/

# Cuidado: --delete APAGA ficheiros no destino!
# Usar --delete-after (mais seguro que --delete-during)

Sem --delete, o rsync apenas adiciona e actualiza — nunca remove. Para um backup espelho (mirror), --delete é obrigatório. Para um backup incremental onde queres preservar versões antigas, não usar.

–exclude: Ignorar Ficheiros Irrelevantes

# Excluir padrões específicos
rsync -avz --delete \
  --exclude='*.tmp' \
  --exclude='.cache/' \
  --exclude='node_modules/' \
  --exclude='*.log' \
  /home/user/ /backup/user/

# Usar ficheiro de exclusões (--exclude-from)
rsync -avz --delete --exclude-from='/etc/rsync-exclude.txt' \
  /home/user/ /backup/user/

# Conteúdo de /etc/rsync-exclude.txt:
# *.tmp
# .cache/
# .local/share/Trash/
# *.iso
# downloads/

-e ssh: Backup Remoto Seguro

# Backup para servidor remoto via SSH
rsync -avz -e ssh /home/user/documentos/ \
  [email protected]:/backup/servidor/documentos/

# Especificar porta SSH não-padrão
rsync -avz -e "ssh -p 2222" /home/user/documentos/ \
  [email protected]:/backup/servidor/documentos/

# Usar chave SSH específica
rsync -avz -e "ssh -i /home/user/.ssh/backup_key" \
  /home/user/documentos/ \
  [email protected]:/backup/servidor/documentos/

O rsync sobre SSH usa a ligação segura do Dia 10 — ideal para backups offsite. A combinação de chaves SSH (sem palavra-passe) com cron permite backups totalmente automáticos.

–link-dest: Incrementais via Hard Links

A flag --link-dest é a forma mais elegante de criar backups incrementais com rsync. Compara o destino com um backup anterior e cria hard links para ficheiros inalterados — cada backup parece completo, mas o espaço em disco é apenas o dos ficheiros alterados.

# Backup incremental estilo "time machine"
DATA=$(date +%Y-%m-%d)
ULTIMO=$(ls -1 /backup/daily/ | tail -1)

rsync -avz --delete \
  --link-dest="/backup/daily/$ULTIMO" \
  /home/user/ /backup/daily/$DATA/

# Resultado:
# /backup/daily/2026-07-20/  -> backup completo aparente
# /backup/daily/2026-07-21/  -> hard links para 07-20 + alterações
# Espaço extra em disco = apenas ficheiros modificados

ℹ Hard links e filesystem: --link-dest só funciona em filesystems que suportam hard links — ext4, xfs, btrfs. Não funciona em FAT32/exFAT. Os hard links não consomem espaço extra porque apontam para o mesmo inode.

tar: Arquivos com Compressão gzip, bzip2 e xz

O tar (tape archive) é a ferramenta mais antiga de backup em Unix. Cria um único ficheiro (tarball) que pode ser comprimido. É ideal para snapshots pontuais e arquivamento.

Criar e Extrair Arquivos

# Criar tarball simples
tar cf backup.tar /home/user/documentos/

# Criar com gzip (rápido, compressão moderada)
tar czf backup-$(date +%F).tar.gz /home/user/documentos/

# Criar com bzip2 (mais compressão, mais lento)
tar cjf backup-$(date +%F).tar.bz2 /home/user/documentos/

# Criar com xz (máxima compressão, mais lento)
tar cJf backup-$(date +%F).tar.xz /home/user/documentos/

# Ver conteúdo sem extrair
tar tzf backup-2026-07-21.tar.gz

# Extrair
tar xzf backup-2026-07-21.tar.gz
tar xjf backup-2026-07-21.tar.bz2
tar xJf backup-2026-07-21.tar.xz

Flags Essenciais: -p, -C, –exclude

# -p  preservar permissões (crítico para backup)
# -C  mudar de directoria antes de empacotar (para chroot/restore)
tar czpf sistema-completo.tar.gz -C / home etc var

# Excluir ficheiros do tarball
tar czpf backup.tar.gz --exclude='*.log' --exclude='.cache' \
  -C / home/user

# Backup de sistema completo (excluir pseudo-filesystems)
tar czpf /backup/sistema-$(date +%F).tar.gz \
  --exclude='/backup' \
  --exclude='/proc' \
  --exclude='/sys' \
  --exclude='/dev' \
  --exclude='/run' \
  --exclude='/tmp' \
  --exclude='/mnt' \
  --exclude='/media' \
  -C / .

⚠ tar e permissões de root: Sem sudo, o tar não consegue preservar ownership de ficheiros de outros utilizadores. Para um backup de sistema completo, correr sempre como root. A flag -p sem root só preserva as permissões que o utilizador consegue ler.

Comparação de Compressão

Flag Algoritmo Rácio Velocidade Quando Usar
-z gzip Médio Rápido Uso geral, backups diários
-j bzip2 Bom Médio Arquivamento, equilíbrio
-J xz (LZMA) Excelente Lento Arquivo a longo prazo

dump/restore: Backups ao Nível do Filesystem ext4

O dump e restore são ferramentas clássicas que operam ao nível do filesystem — lêem os inodes directamente, sem percorrer a árvore de directorias. Suportam backups incrementais nativos (níveis 0-9) e são específicos de ext2/ext3/ext4. Não funcionam em xfs, btrfs ou zfs.

Instalação

# Debian/Ubuntu
sudo apt install dump

# RHEL/Rocky/Alma/Fedora
sudo dnf install dump

Backup Completo e Incremental

# Backup completo (nível 0) de /dev/sda1 (montado em /home)
sudo dump -0u -f /backup/home-level0.dump /home

# Backup incremental (nível 9) — apenas alterações desde último dump
sudo dump -9u -f /backup/home-level9-$(date +%F).dump /home

# -0  nível 0 (completo)
# -9  nível 9 (incremental desde último backup de nível inferior)
# -u  actualizar /etc/dumpdates (regista data e nível)
# -f  ficheiro de saída

# Comprimir backup em tempo real
sudo dump -0u -z -f /backup/home-level0.dump.gz /home

Restaurar com restore

# Restaurar para directoria temporária (modo interactivo)
cd /tmp/restore
sudo restore -i -f /backup/home-level0.dump

# Comandos dentro do modo interactivo:
# ls        listar ficheiros
# add dir   adicionar directoria à lista de restauro
# extract   extrair ficheiros seleccionados
# quit      sair

# Restauro completo (não-interactivo)
sudo restore -rf /backup/home-level0.dump

# Ver conteúdo do dump sem extrair
sudo restore -tf /backup/home-level0.dump

⚠ dump em filesystems montados: O dump deve correr com o filesystem desmontado ou em modo só-de-leitura para garantir consistência. Em produção, usar um snapshot LVM (Dia 12) e fazer dump do snapshot. Para filesystems modernos como xfs, usar xfsdump/xfsrestore em vez de dump.

BorgBackup: Deduplicação, Compressão e Encriptação

O BorgBackup (ou Borg) é a ferramenta moderna de backup para Linux. Resolve os problemas que rsync e tar não resolvem nativamente: deduplicação ao nível de bloco, compressão automática e encriptação client-side. Cada backup é um snapshot completo aparente, mas o espaço em disco é apenas o dos blocos novos.

Instalação

# Debian/Ubuntu
sudo apt install borgbackup

# RHEL/Rocky/Alma/Fedora (EPEL pode ser necessário)
sudo dnf install borgbackup

# Via pip (versão mais recente)
pip install borgbackup

borg init: Inicializar Repositório

# Inicializar repositório local com encriptação
borg init --encryption=repokey /backup/borg/servidor

# Inicializar repositório remoto via SSH
borg init --encryption=repokey \
  [email protected]:/backup/borg/servidor

# Tipos de encriptação:
# repokey     chave armazenada no repositório (palavra-passe protege)
# keyfile     chave em ficheiro local (mais seguro, guardar backup da chave!)
# none        sem encriptação (NÃO usar para dados sensíveis)

⚠ Guardar a palavra-passe e a chave: Se usares keyfile e perderes a chave ou a palavra-passe, os backups são irrecuperáveis. Guardar ambos em local seguro e separado do repositório. Definir BORG_PASSPHRASE como variável de ambiente para automatização.

borg create: Criar um Backup

# Sintaxe: borg create [opções] REPOSITORIO::ARQUIVO ORIGEM
borg create --stats --progress \
  /backup/borg/servidor::diario-{now:%Y-%m-%d} \
  /home/user

# Comprimir (zstd é o melhor rácio/velocidade em 2026)
borg create --compression=zstd,11 \
  /backup/borg/servidor::diario-{now:%Y-%m-%d} \
  /home/user

# Excluir padrões
borg create --compression=zstd,11 \
  --exclude '/home/user/.cache' \
  --exclude '*.tmp' \
  --exclude '*/node_modules/*' \
  /backup/borg/servidor::diario-{now:%Y-%m-%d} \
  /home/user

# Backup remoto via SSH
BORG_RSH="ssh -i /home/user/.ssh/backup_key" \
  borg create \
  [email protected]:/backup/borg/servidor::diario-{now:%Y-%m-%d} \
  /home/user

Deduplicação e Compressão

O Borg divide cada ficheiro em chunks (blocos de tamanho variável, tipicamente 16-64 KB) e calcula um hash de cada chunk. Antes de armazenar, verifica se o chunk já existe no repositório. Se sim, não o armazena novamente. Isto significa:

  • Ficheiros grandes modificados parcialmente (ex: ficheiro ZIP, base de dados) só transferem os blocos alterados
  • Backups consecutivos do mesmo sistema ocupam muito pouco espaço extra
  • Backups de máquinas similares (ex: VMs do mesmo template) partilham blocos
Algoritmo Velocidade Rácio Recomendação
none Máxima Nenhuma Dados já comprimidos (imagens, vídeo)
lz4 Muito rápida Baixa Backups frequentes em rede rápida
zstd,N Rápida Alta Recomendado para 2026 (nível 3-11)
zlib,N Média Média Compatibilidade, default histórico
lzma,N Lenta Máxima Arquivo a longo prazo, CPU disponível

borg prune: Reter Apenas o Necessário

# Reter: 7 diários, 4 semanais, 6 mensais, 2 anuais
borg prune --keep-daily=7 --keep-weekly=4 \
  --keep-monthly=6 --keep-yearly=2 \
  /backup/borg/servidor

# --dry-run primeiro para ver o que seria apagado
borg prune --dry-run --keep-daily=7 --keep-weekly=4 \
  --keep-monthly=6 --keep-yearly=2 \
  /backup/borg/servidor

O prune não apaga os dados imediatamente — marca os arquivos para remoção. O espaço só é libertado após borg check ou borg compact.

borg mount: Montar um Backup como Filesystem

# Montar repositório inteiro (todos os arquivos visíveis)
sudo mkdir /mnt/borg
sudo borg mount /backup/borg/servidor /mnt/borg

# Navegar como filesystem normal
ls /mnt/borg/
# diario-2026-07-19/  diario-2026-07-20/  diario-2026-07-21/

# Copiar ficheiro específico de um backup
cp /mnt/borg/diario-2026-07-20/home/user/documentos/notas.txt /tmp/

# Desmontar
sudo fusermount -u /mnt/borg

O borg mount usa FUSE para apresentar todos os arquivos do repositório como directorias. É a forma mais conveniente de recuperar um ficheiro individual sem extrair o backup inteiro.

cron + rsync: Backups Automáticos

Combinando o cron do Dia 13 com rsync, conseguimos backups automáticos e incrementais. O script seguinte implementa a estratégia 3-2-1 com rotação de backups diários via --link-dest.

Script de Backup Automático

#!/bin/bash
# /usr/local/bin/backup-rsync.sh
# Backup incremental via rsync --link-dest

set -euo pipefail

ORIGEM="/home/user"
DESTINO="/backup/daily"
DATA=$(date +%Y-%m-%d)
ULTIMO=$(ls -1 "$DESTINO" 2>/dev/null | tail -1)
LOG="/var/log/backup-rsync.log"

echo "[$(date)] Iniciando backup de $ORIGEM" >> "$LOG"

if [ -z "$ULTIMO" ]; then
  # Primeiro backup — completo
  rsync -avz --delete \
    "$ORIGEM/" "$DESTINO/$DATA/"
else
  # Backup incremental via hard links
  rsync -avz --delete \
    --link-dest="$DESTINO/$ULTIMO" \
    "$ORIGEM/" "$DESTINO/$DATA/"
fi

# Remover backups com mais de 30 dias
find "$DESTINO" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +

echo "[$(date)] Backup concluído: $DESTINO/$DATA" >> "$LOG"
# Tornar executável
sudo chmod +x /usr/local/bin/backup-rsync.sh

# Adicionar ao crontab do root (backup diário às 02:00)
sudo crontab -e
# 0 2 * * * /usr/local/bin/backup-rsync.sh

# Ou via systemd timer (recomendado, ver Dia 13)
sudo tee /etc/systemd/system/backup.service << 'EOF'
[Unit]
Description=Backup rsync diário

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-rsync.sh
Nice=19
IOSchedulingClass=idle
EOF

sudo tee /etc/systemd/system/backup.timer << 'EOF'
[Unit]
Description=Backup rsync diário às 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl enable --now backup.timer

Script de Backup com BorgBackup

#!/bin/bash
# /usr/local/bin/backup-borg.sh
# Backup com BorgBackup + retenção automática

set -euo pipefail

REPOSITORIO="/backup/borg/servidor"
ORIGEM="/home/user"
LOG="/var/log/backup-borg.log"

export BORG_PASSPHRASE='minha-palavra-passe-secreta'

echo "[$(date)] Iniciando backup Borg" >> "$LOG"

# Criar backup
borg create --stats --compression=zstd,11 \
  --exclude "$ORIGEM/.cache" \
  --exclude "$ORIGEM/.local/share/Trash" \
  "$REPOSITORIO::diario-{now:%Y-%m-%d}" \
  "$ORIGEM" 2>>"$LOG"

# Prune: reter 7 diários, 4 semanais, 6 mensais
borg prune --keep-daily=7 --keep-weekly=4 \
  --keep-monthly=6 \
  "$REPOSITORIO" 2>>"$LOG"

# Compactar (libertar espaço dos chunks removidos)
borg compact "$REPOSITORIO" 2>>"$LOG"

echo "[$(date)] Backup Borg concluído" >> "$LOG"

Verificação de Backups: --dry-run e borg check

Um backup não verificado é uma esperança, não um backup. A verificação deve ser parte do processo — não um passo opcional. As duas ferramentas principais de verificação são rsync --dry-run e borg check.

rsync --dry-run: Simular Antes de Executar

# Simular: mostrar o que seria transferido sem alterar nada
rsync -avz --dry-run --delete /home/user/ /backup/user/

# Comparar origem e destino (verificar integridade)
rsync -avzn --checksum /home/user/ /backup/user/

# -n  = --dry-run (simulação)
# -c  = --checksum (verificar por checksum em vez de tamanho+tempo)
# Útil para auditar diferenças entre origem e backup

borg check: Verificar Integridade do Repositório

# Verificação rápida (estrutura do repositório)
borg check /backup/borg/servidor

# Verificação completa (verifica todos os dados)
borg check --verify-data /backup/borg/servidor

# Verificar apenas um arquivo específico
borg check --verify-data \
  /backup/borg/servidor::diario-2026-07-21

# Reparar repositório corrompido (último recurso)
borg check --repair /backup/borg/servidor

⚠ borg check --verify-data é lento: Verifica todos os chunks do repositório lendo-os do disco. Num repositório de 500 GB pode demorar horas. Usar semanalmente ou mensalmente, não diariamente. A verificação rápida (sem --verify-data) é suficiente para uso diário.

Testar o Restauro

# Borg: listar ficheiros de um backup
borg list /backup/borg/servidor::diario-2026-07-21

# Borg: extrair ficheiro específico
borg extract \
  /backup/borg/servidor::diario-2026-07-21 \
  home/user/documentos/notas.txt

# Borg: montar e verificar visualmente
sudo borg mount /backup/borg/servidor /mnt/borg
ls -la /mnt/borg/diario-2026-07-21/home/user/documentos/
sudo fusermount -u /mnt/borg

# tar: testar integridade do tarball
gzip -t backup-2026-07-21.tar.gz    # testa integridade gzip
tar tzf backup-2026-07-21.tar.gz | head  # lista conteúdo

Recuperação Bare-Metal

Recuperação bare-metal é o restauro completo de um servidor para hardware novo ou vazia — sem sistema operativo pré-instalado. É o teste final de qualquer estratégia de backup. Se nunca testaste um bare-metal restore, o teu backup é uma teoria, não um facto.

Passos para Bare-Metal com rsync

# 1. Bootar a partir de Live USB/CD (Ubuntu, SystemRescue, etc.)
#    Descobrir e formatar o disco destino
lsblk
sudo mke2fs -t ext4 /dev/sda1       # ext4 (não usar em produção sem LVM)
sudo mount /dev/sda1 /mnt

# 2. Restaurar ficheiros do backup
rsync -avz --numeric-ids \
  --exclude=/proc/* --exclude=/sys/* \
  --exclude=/dev/* --exclude=/run/* \
  [email protected]:/backup/servidor/ /mnt/

# 3. Reinstalar GRUB
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt
grub-install /dev/sda
update-grub

# 4. Actualizar fstab se os UUIDs mudaram
blkid
nano /etc/fstab

# 5. Sair do chroot e reiniciar
exit
sudo umount /mnt/dev /mnt/proc /mnt/sys
sudo umount /mnt
sudo reboot

Bare-Metal com BorgBackup

# 1. Bootar Live USB e montar o disco destino
sudo mount /dev/sda1 /mnt

# 2. Extrair backup completo do Borg
export BORG_PASSPHRASE='minha-palavra-passe'
borg extract --numeric-owner \
  [email protected]:/backup/borg/servidor::completo-2026-07-21

# 3. Reinstalar bootloader (igual ao rsync)
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt
grub-install /dev/sda
update-grub
exit

# 4. Actualizar fstab e reiniciar
blkid
nano /mnt/etc/fstab
sudo umount /mnt/{dev,proc,sys}
sudo umount /mnt
sudo reboot

✓ Testar o bare-metal restore regularmente: O teste deve ser feito pelo menos trimestralmente. Muitos sysadmins descobrem tarde demais que o backup estava corrompido, que o fstab tem UUIDs errados, ou que o GRUB não instala. Um teste em VM de staging custa 30 minutos; um falhanço em produção custa horas ou dias de downtime.

Erros Comuns

Erro Causa Solução
rsync: failed to set permissions Destino não suporta permissões Unix (FAT32, NTFS sem mapping) Usar --no-perms --no-owner --no-group ou formatar destino em ext4
rsync apagou ficheiros no destino --delete com origem errada ou vazia Usar --dry-run sempre antes de --delete
borg: Connection closed by remote host SSH timeout ou repositório remoto inacessível Verificar BORG_RSH, conectividade SSH, e espaço no destino
borg: Repository corruption Disco com bad sectors, corte de energia Correr borg check --repair e ter réplica offsite
tar: Cannot open: Permission denied Ficheiros de outro utilizador sem sudo Correr tar como root para backups de sistema
dump: Bad magic number Tentar dump em filesystem não-ext (xfs, btrfs) Usar xfsdump para xfs, ou rsync/Borg para outros
borg: No space left on device Repositório cresceu sem prune + compact Correr borg prune seguido de borg compact
Backups não correm no cron PATH diferente no cron, BORG_PASSPHRASE não definido Definir variáveis de ambiente no script ou no crontab

Checklist de Backup

  1. Aplicar a regra 3-2-1: 3 cópias, 2 tipos de media, 1 cópia offsite — mínimo absoluto
  2. Escolher a ferramenta certa: rsync para espelhos, tar para snapshots, Borg para deduplicação + encriptação
  3. Automatizar com cron ou systemd timer: backup manual não é backup — é esquecimento à espera de acontecer
  4. Usar --dry-run antes de --delete: confirmar sempre o que o rsync vai apagar
  5. Verificar backups regularmente: borg check --verify-data mensalmente, rsync --checksum semanalmente
  6. Testar bare-metal restore: pelo menos trimestralmente em VM de staging
  7. Configurar retenção: borg prune ou find -mtime para rotação automática
  8. Encriptar backups offsite: Borg com repokey ou keyfile, rsync sobre SSH
  9. Guardar palavra-passe/chave Borg separadamente: sem ela, o backup encriptado é irrecuperável
  10. Monitorizar logs de backup: journalctl -u backup.service ou /var/log/backup-*.log
  11. Documentar o procedimento de restauro: um runbook que qualquer colega consiga seguir

Artigos Relacionados

No Dia 15 entraremos na configuração de web servers com Apache e Nginx — onde os backups de hoje garantem que podes reverter config changes problemáticas sem downtime. A estratégia 3-2-1 que aprendemos aqui é a base de qualquer operação de produção resiliente.