Tutorial: automatizar snapshots LVM e uploads incrementais para S3 usando systemd timers e Restic no Debian
Hospedagem & VPS · Por Kevin Marcondes · Publicado em · 10 min de leitura
Este tutorial mostra, passo a passo, como automatizar snapshots LVM e fazer uploads incrementais para S3 com Restic no Debian, orquestrando tudo com systemd timers. Você terá scripts prontos, unidades do systemd e dicas de verificação e recuperação. Requer acesso root e atenção às etapas para evitar interrupções.
Arquitetura do backup: LVM snapshot + Restic + S3
A estratégia combina três peças: snapshot em LVM para congelar um ponto consistente do volume, Restic para realizar o backup incremental e criptografado, e S3 como armazenamento remoto. O systemd agenda e garante execução confiável, com logs centralizados no journal.
Fluxo resumido: criar snapshot LVM (copy-on-write), montar em readonly, executar restic backup no snapshot, desmontar e remover o snapshot. Em janela de manutenção do backup, o sistema segue operando no volume original normalmente.
O Restic armazena apenas blocos alterados entre execuções, reduzindo tráfego e tempo. A retenção é aplicada com forget + prune. Se você usa cron, avaliar migrar para timers melhora observabilidade e robustez.
- Snapshot LVM: captura ponto no tempo sem parar serviços.
- Restic: deduplicação, criptografia por padrão, incremental eficiente.
- S3: armazenamento remoto resiliente.
- systemd: agendador com logs, retries e dependências.
Pré-requisitos e planejamento de capacidade
Antes de começar, confirme o ambiente e dimensione o snapshot. Operações em LVM incorretas podem causar indisponibilidade ou perda de dados. Teste primeiro em um servidor de homologação.
Para segurança básica do servidor, revise a lista de boas práticas em checklist de segurança para VPS Linux.
- Debian 11/12 com acesso root.
- Pacotes: lvm2, restic.
- Volume LVM (VG/LV) com espaço livre no VG para o snapshot (tamanho depende da taxa de escrita durante o backup).
- Bucket S3 acessível pela rede e credenciais IAM com permissão restrita.
- Sincronização de horário (timers dependem de clock correto).
- Planeje exclusões (caches, tmp, mounts) para evitar ruído no backup.
Bucket S3 e credenciais IAM mínimas
Crie um bucket exclusivo para backups (por projeto/ambiente) e um usuário IAM com acesso restrito apenas a esse bucket. Use chaves de acesso dedicadas. Consulte a documentação do Amazon S3 para criar o bucket e políticas.
O Restic usa a URL do repositório no formato s3:https://endpoint/bucket/prefix. Em S3 padrão: s3:https://s3.amazonaws.com/seu-bucket/prefix. Ajuste a região conforme seu bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ResticBackupAccess",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions"
],
"Resource": [
"arn:aws:s3:::SEU-BUCKET"
]
},
{
"Sid": "ResticObjectsAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucketMultipartUploads",
"s3:AbortMultipartUpload"
],
"Resource": [
"arn:aws:s3:::SEU-BUCKET/*"
]
}
]
}
Instalar Restic e configurar variáveis seguras
Instale os pacotes e centralize as credenciais/variáveis do Restic em um arquivo root-only. Proteja esse arquivo (0600). Crie também um arquivo de exclusões para evitar backup de caches/mounts temporários.
Variáveis comuns estão na tabela abaixo. Adapte ao seu ambiente.
| Variável | Exemplo | Descrição |
|---|---|---|
| RESTIC_REPOSITORY | s3:https://s3.amazonaws.com/meu-bucket/projeto1 | URL do repositório Restic em S3 |
| RESTIC_PASSWORD | uma-senha-forte | Senha de criptografia do repositório |
| AWS_ACCESS_KEY_ID | AKIA... | Chave de acesso AWS |
| AWS_SECRET_ACCESS_KEY | xxxxxxxx | Chave secreta AWS |
| AWS_DEFAULT_REGION | us-east-1 | Região do bucket |
| BACKUP_TAGS | vps-01,lvm-snapshot | Tags aplicadas aos snapshots do Restic |
set -euo pipefail
apt update && apt install -y lvm2 restic
install -d -m 0700 /etc/restic
cat > /etc/restic.env <<'EOF'
RESTIC_REPOSITORY=s3:https://s3.amazonaws.com/SEU-BUCKET/projeto1
RESTIC_PASSWORD=troque-esta-senha
AWS_ACCESS_KEY_ID=COLOQUE_SUA_CHAVE
AWS_SECRET_ACCESS_KEY=COLOQUE_SUA_SECRETA
AWS_DEFAULT_REGION=us-east-1
BACKUP_TAGS=vps-01,lvm-snapshot
EOF
chmod 0600 /etc/restic.env
# Exclusões do backup (ajuste conforme necessário)
install -d -m 0755 /etc/restic
cat > /etc/restic/excludes.txt <<'EOF'
/proc/*
/sys/*
/run/*
/tmp/*
/var/tmp/*
/var/cache/*
/mnt/*
/media/*
/swapfile
EOF
Inicializar o repositório e validar conexão
Inicialize o repositório no S3 e faça um teste rápido de backup/consulta. Use uma variável de ambiente para carregar as credenciais antes de chamar o Restic. Guarde a senha (RESTIC_PASSWORD): sem ela, você não recupera os dados.
set -euo pipefail
set -a
. /etc/restic.env
set +a
# Inicializa o repositório (executar apenas uma vez)
restic init
# Teste rápido de backup (arquivo pequeno)
restic backup --tag test /etc/hosts --exclude-file=/etc/restic/excludes.txt
# Lista snapshots para confirmar
restic snapshots
Script de backup com snapshot LVM (atômico e com limpeza)
O script abaixo cria um snapshot LVM readonly, monta, executa o backup incremental com Restic e remove o snapshot com limpeza garantida via trap. Inclui um lock simples para evitar concorrência. Ajuste VG/LV, tamanho do snapshot e paths.
Se você faz backup do volume raiz, certifique espaço livre no VG. Para bancos de dados, considere um dump coordenado ou um freeze curto do filesystem para consistência lógica.
#!/usr/bin/env bash
set -euo pipefail
# Configuração específica do host
VG_NAME="vg0" # Volume Group
LV_NAME="root" # Logical Volume original
SNAP_SIZE="5G" # Tamanho do snapshot (depende da taxa de escrita)
MOUNT_POINT="/mnt/backup-snap"
SNAP_NAME="${LV_NAME}-snap-$(date +%Y%m%d%H%M%S)"
LOCK_FILE="/var/lock/restic-lvm-backup.lock"
exec 9>"$LOCK_FILE" || true
if ! flock -n 9; then
echo "Outro backup está em execução. Abortando." >&2
exit 1
fi
cleanup() {
set +e
if mountpoint -q "$MOUNT_POINT"; then umount "$MOUNT_POINT"; fi
if lvdisplay "/dev/${VG_NAME}/${SNAP_NAME}" >/dev/null 2>&1; then lvremove -f "/dev/${VG_NAME}/${SNAP_NAME}"; fi
}
trap cleanup EXIT
# Garante mountpoint
install -d -m 0755 "$MOUNT_POINT"
# Carrega variáveis do Restic
set -a
. /etc/restic.env
set +a
LV_PATH="/dev/${VG_NAME}/${LV_NAME}"
SNAP_PATH="/dev/${VG_NAME}/${SNAP_NAME}"
# (Opcional) Freeze curto do FS se souber o mount do LV original
# fsfreeze -f / && trap 'fsfreeze -u /; cleanup' EXIT # Exemplo perigoso; ajuste ao seu mount real
# Cria snapshot copy-on-write
lvcreate -s -L "$SNAP_SIZE" -n "$SNAP_NAME" "$LV_PATH"
# Descongela se tiver congelado
# fsfreeze -u /
# Monta snapshot como readonly
mount -o ro "$SNAP_PATH" "$MOUNT_POINT"
# Executa backup incremental com Restic
HOSTNAME_FQDN="$(hostname -f || hostname)"
ionice -c2 -n7 nice -n 10 \
restic backup \
--host "$HOSTNAME_FQDN" \
--tag "$BACKUP_TAGS" \
--exclude-file=/etc/restic/excludes.txt \
"$MOUNT_POINT"
# (Opcional) Verificação rápida de integridade do último snapshot
restic snapshots --last --compact
# Cleanup é feito no trap
Agendamento com systemd: service + timers (backup e retenção)
Vamos criar unidades do systemd para orquestrar o backup e a retenção. O timer diário roda o backup; o semanal aplica retenção e prune. Use RandomizedDelaySec para evitar pico simultâneo em vários hosts.
Se você ainda usa cron, confira como migrar no guia Migrar cron para systemd timers.
# /usr/local/sbin/backup-lvm-restic.sh deve estar executável
chmod +x /usr/local/sbin/backup-lvm-restic.sh
# Unidade de backup
cat > /etc/systemd/system/backup-lvm-restic.service <<'EOF'
[Unit]
Description=Backup com LVM snapshot + Restic para S3
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic.env
ExecStart=/usr/local/sbin/backup-lvm-restic.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
UMask=0077
[Install]
WantedBy=multi-user.target
EOF
# Timer diário do backup
cat > /etc/systemd/system/backup-lvm-restic.timer <<'EOF'
[Unit]
Description=Agendamento diário do backup LVM+Restic
[Timer]
OnCalendar=02:30
RandomizedDelaySec=20m
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Serviço de retenção e prune semanal
cat > /etc/systemd/system/restic-prune.service <<'EOF'
[Unit]
Description=Restic forget+prune (retenção)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic.env
ExecStart=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
UMask=0077
EOF
# Timer semanal de retenção (domingo 03:30)
cat > /etc/systemd/system/restic-prune.timer <<'EOF'
[Unit]
Description=Agendamento semanal Restic prune
[Timer]
OnCalendar=Sun *-*-* 03:30:00
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Aplica e inicia timers
systemctl daemon-reload
systemctl enable --now backup-lvm-restic.timer
systemctl enable --now restic-prune.timer
# Primeira execução manual (opcional)
# systemctl start backup-lvm-restic.service
Verificação, restauração rápida e boas práticas
Valide a execução dos timers, examine logs do journal e confirme snapshots no repositório. Faça um restore de amostra para testar o caminho de recuperação. Teste antes de precisar.
Se você centraliza logs, integre o journal com ferramentas como no guia Fluentd + Elasticsearch: logs PHP em VPS (guia).
- Confirme timers ativos e próxima execução.
- Cheque logs do serviço e saída do Restic.
- Liste snapshots e tags.
- Restaure um arquivo/diretório de teste para validar chaves e permissão de acesso.
- Automatize testes periódicos de restore em ambiente isolado.
# Timers e próximas execuções
systemctl list-timers | grep -E 'backup-lvm-restic|restic-prune'
# Logs da última execução do backup
journalctl -u backup-lvm-restic.service -n 200 --no-pager
# Lista snapshots
set -a; . /etc/restic.env; set +a
restic snapshots --compact
# Restauração de teste (ex.: arquivo do /etc)
mkdir -p /tmp/restore-test
restic restore latest --target /tmp/restore-test --include etc/hosts
ls -l /tmp/restore-test/etc/hosts
Solução de problemas comuns
Erros frequentes envolvem espaço insuficiente para snapshot, credenciais inválidas e locks pendentes no repositório. Abaixo, sintomas e ações. Nunca force remoções em LVM no volume errado.
Em sistemas com escrita intensa, aumente o SNAP_SIZE ou reduza a janela do backup. Confirme DNS/firewall para alcançar o endpoint S3.
- Snapshot fica cheio/invalidado: aumente SNAP_SIZE ou reduza a atividade de escrita durante o backup.
- lvcreate falhou: confirme VG/LV corretos e espaço livre no VG (vgs/lvs).
- Permissão S3 negada: valide política IAM e variáveis em /etc/restic.env.
- Repositório trancado: use 'restic unlock' com cautela, assegurando que não há processos em execução.
- Tempo de backup alto: ajuste excludes, use tags e agende fora do horário de pico.
# Diagnóstico LVM
vgs; lvs -a -o +devices
# Verificação de mountpoint do snapshot
mount | grep backup-snap || lsblk -f
# Teste de credenciais/ambiente do Restic
set -a; . /etc/restic.env; set +a
restic snapshots || echo "Verifique RESTIC_REPOSITORY e variáveis AWS"
# Remover lock do repositório com cuidado
restic unlock
# Logs detalhados
journalctl -u backup-lvm-restic.service --since "-2h" -e --no-pager
Perguntas frequentes
Qual tamanho devo usar para o snapshot LVM?
Depende da taxa de escrita durante a janela do backup. Quanto mais o volume muda, maior precisa ser o snapshot (área de copy‑on‑write). Comece com alguns gigabytes e ajuste após observar se o snapshot enche. Monitore nas primeiras execuções.
Posso usar endpoints compatíveis com S3?
Sim, o Restic trabalha com APIs compatíveis com S3 ao informar o endpoint na URL do repositório. Verifique requisitos de autenticação, região e TLS do provedor escolhido, e teste com restic init e restic snapshots antes de automatizar.
Backups de bancos de dados ficam consistentes com snapshot LVM?
O snapshot LVM garante consistência de bloco. Para consistência lógica da aplicação, faça um dump transacional ou um freeze rápido do filesystem/serviço (quando suportado) antes do lvcreate, e desfaz após a criação do snapshot. Avalie o impacto no seu workload.
Como faço retenção sem perder os backups úteis?
Use restic forget com política adequada ao negócio, seguida de prune. Por exemplo, manter 7 diários, 4 semanais e 6 mensais. Ajuste aos seus RPO/RTO. Sempre teste restaurações após alterar políticas para conferir se atendem ao objetivo.
É seguro manter as credenciais no /etc/restic.env?
Sim, desde que o arquivo tenha permissões restritas (0600) e acesso apenas por root. Considere separar o usuário que roda o Restic quando não precisar de privilégios elevados, e rotacione chaves IAM periodicamente.
Quanto custará armazenar no S3?
Varia com volume total em GB, número de objetos/versões, requisições e região do bucket. Uploads incrementais e retenção adequada reduzem custo. Verifique preços atuais diretamente no site do provedor e ajuste a política de retenção conforme necessário.
Precisa adaptar o backup ao seu ambiente?
Se quiser revisar política de retenção, exclusões e janelas de execução para sua carga de trabalho, entre em contato e descreva seu cenário.
Conversar sobre backup e automaçãoVeja também
- tutorial: implementar Canary releases com Traefik em Docker Compose usando headers e weight routing para deploys graduais de aplicações PHP
- Tutorial: configurar HAProxy com Let's Encrypt e healthchecks para balanceamento de tráfego entre containers Docker em VPS (passo a passo)
- Tutorial prático: implementar mTLS entre Nginx e microserviços usando smallstep CA em Docker Compose
- Tutorial: configurar cgroup v2 e systemd ResourceControl para limitar CPU, memória e I/O de containers Docker no Debian