⚡ AutomationsAI|Portal de Cursos →

Verificando acesso...

MÓDULO 6.4

💾 Backup e segurança

Backup não é o que você faz — é o que você prova que consegue restaurar. Tokens, dumps, encriptação, rotação e plano de DR para dormir tranquilo.

6
Tópicos
35
Minutos
Avançado
Nível
Prático
Tipo
1

🗄️ pg_dump diário em cron

O coração do Postiz é o Postgres: posts agendados, contas conectadas, tokens OAuth, métricas. Perder o volume é perder semanas de trabalho. A primeira camada de defesa é um pg_dump diário em formato -Fc (custom) — comprimido, mais rápido pra restaurar e permite restore seletivo de tabelas.

Use cron do host, não cron dentro do container. Container morre, cron morre junto. O dump roda via docker exec no Postgres já em execução.

# /usr/local/bin/postiz-backup.sh
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR=/var/backups/postiz
STAMP=$(date +%F_%H%M)
mkdir -p "$BACKUP_DIR"

# -Fc = custom format (comprimido + restore seletivo)
docker exec postiz-postgres \
  pg_dump -U postiz -d postiz -Fc \
  > "$BACKUP_DIR/postiz_${STAMP}.dump"

# Retenção local: 7 dias
find "$BACKUP_DIR" -name "postiz_*.dump" -mtime +7 -delete

echo "[$(date -Iseconds)] backup ok: postiz_${STAMP}.dump"
# Tornar executável e agendar (03:00 todo dia)
chmod +x /usr/local/bin/postiz-backup.sh

crontab -e
# adicionar:
0 3 * * * /usr/local/bin/postiz-backup.sh >> /var/log/postiz-backup.log 2>&1

💡 Dica prática

Sempre use set -euo pipefail no topo. Sem isso, um pg_dump que falha silenciosamente gera um arquivo de 0 bytes — e você só descobre no dia do desastre. Com pipefail, o script aborta e o cron envia e-mail.

Conceitos-chave

pg_dump -Fc

Custom format, comprimido, restaura seletivo.

cron

Agendador do host — sobrevive a restart de container.

Retenção

Janela de versões mantidas antes de purgar.

pipefail

Falha do script propaga falha do pipeline.

2

☁️ Sync para S3 / R2 com restic

Dump no mesmo host onde o Postiz roda não é backup — é uma cópia. Se o disco morrer, morre junto. A camada off-site usa restic: encripta com AES-256 antes de subir, faz dedup em blocos (vários dumps quase iguais ocupam quase nada) e tem retenção declarativa.

Cloudflare R2 é a opção barata: zero egress fee, API S3-compatível, ~$0.015/GB-mês. AWS S3 funciona igual com endpoint default. O segredo de encriptação fica só no servidor — sem ele, o backup é lixo aleatório no bucket.

# Instalar restic
sudo apt install restic

# Variáveis (idealmente em /etc/postiz-backup.env, chmod 600)
export AWS_ACCESS_KEY_ID=<r2_access_key>
export AWS_SECRET_ACCESS_KEY=<r2_secret>
export RESTIC_REPOSITORY=s3:https://<account>.r2.cloudflarestorage.com/postiz-backups
export RESTIC_PASSWORD=<senha_forte_de_64_chars>

# Inicializar repo (UMA vez)
restic init

# Backup do diretório de dumps
restic backup /var/backups/postiz --tag daily

# Política de retenção: 7 diários, 4 semanais, 6 mensais
restic forget \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6 \
  --prune
# Adicionar ao postiz-backup.sh, após o pg_dump
source /etc/postiz-backup.env

restic backup "$BACKUP_DIR" --tag daily --quiet
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune --quiet

🔒 Dica prática

Guarde RESTIC_PASSWORD em dois lugares offline: gerenciador de senhas + papel no cofre. Se o servidor pegar fogo junto com a única cópia da senha, o backup encriptado no R2 vira inútil. Aconteceu. Mais de uma vez.

Conceitos-chave

restic

Backup com dedup, encriptação e snapshots.

Dedup

Blocos repetidos são armazenados uma só vez.

forget --prune

Aplica retenção e libera espaço do repositório.

Off-site

Cópia em rede / região / provedor diferente.

3

✅ Teste de restore mensal

Backup não testado é boato. Você só descobre que o dump está corrompido, que faltou uma tabela, que o segredo está errado ou que ninguém anotou o procedimento — no dia em que precisa. Marque no calendário: primeiro domingo de cada mês, restore de teste num ambiente isolado.

O teste roda em uma VM ou container separado da produção. Restore o dump mais recente, suba um Postiz apontando para esse Postgres, faça login e verifique se posts agendados, contas conectadas e métricas voltaram.

# Em ambiente isolado (host de teste)
restic snapshots                    # listar backups disponíveis
restic restore latest --target /tmp/restore

# Subir Postgres temporário
docker run -d --name pg-restore \
  -e POSTGRES_USER=postiz \
  -e POSTGRES_PASSWORD=teste \
  -e POSTGRES_DB=postiz \
  postgres:16-alpine

# Restaurar o dump (-c = drop antes, --if-exists = idempotente)
cat /tmp/restore/var/backups/postiz/postiz_*.dump | \
  docker exec -i pg-restore \
    pg_restore -U postiz -d postiz -c --if-exists

# Smoke test: contar registros das tabelas críticas
docker exec pg-restore psql -U postiz -d postiz -c "
  SELECT 'users' tbl, count(*) FROM users
  UNION ALL SELECT 'posts', count(*) FROM posts
  UNION ALL SELECT 'integrations', count(*) FROM integrations;"

# Limpar
docker rm -f pg-restore

✓ O que FAZER

  • Agendar o teste no calendário, com lembrete.
  • Documentar o procedimento num RUNBOOK.md.
  • Cronometrar — RTO real só sai do teste.
  • Conferir contagem de linhas em tabelas-chave.

✗ O que NÃO fazer

  • Restaurar em cima da produção — nunca.
  • "Confiar no log do cron" sem abrir o dump.
  • Pular o teste porque "está tudo funcionando".
  • Esquecer de remover o container de teste depois.

Conceitos-chave

Restore drill

Ensaio periódico do procedimento de recuperação.

Ambiente isolado

Host/VM separados sem risco de afetar prod.

Smoke test

Verificações mínimas que dizem "voltou ok".

Disciplina

Cumprir o rito mesmo quando "está tudo bem".

4

🔄 Rotação de tokens

Tokens de longa duração são superfícies de ataque permanentes. Um vazamento de log, um backup que escapou, um dev que saiu da empresa — todos viram acesso eterno enquanto o token estiver válido. A política mínima é rotacionar tudo em ciclos previsíveis.

⏱️ Frequências recomendadas

  • JWT_SECRET do Postiz: a cada 90 dias OU imediatamente após qualquer suspeita. Rotacionar invalida sessões — avise os usuários.
  • Senha do Postgres: 180 dias. Lembre de atualizar DATABASE_URL no .env.
  • API keys de redes sociais: seguir o ciclo do provedor — X expira em 2h (refresh automático), Meta a cada 60 dias, LinkedIn anual.
  • Chaves S3/R2 do backup: 90 dias. Crie a nova, atualize o .env, valide um backup, revogue a antiga.
  • SSH keys do servidor: anual + sempre após desligamento de pessoa.
# Rotacionar JWT_SECRET (zero-downtime parcial)
# 1) Gerar novo segredo
NEW=$(openssl rand -hex 64)

# 2) Atualizar .env
sed -i "s|^JWT_SECRET=.*|JWT_SECRET=${NEW}|" ~/postiz/.env

# 3) Reiniciar Postiz (sessões atuais caem — avise!)
docker compose -f ~/postiz/docker-compose.yml up -d --force-recreate postiz

# 4) Confirmar
docker compose logs --tail=20 postiz | grep -i ready

📅 Dica prática

Crie eventos recorrentes no calendário com o checklist da rotação. "Rotação de tokens — Q1/2026" no primeiro dia do trimestre. Sem rito agendado, ninguém rotaciona — e descobrir uma chave de 3 anos atrás num backup vazado é experiência humilhante.

Conceitos-chave

Rotação

Substituir credencial ativa por uma nova.

Revogação

Invalidar a credencial antiga no provedor.

Refresh token

Troca o access token sem novo login do user.

Blast radius

Escopo de impacto se a credencial vazar.

5

🔐 Princípio do menor privilégio

Toda credencial deve ter o mínimo de poder necessário pra fazer seu trabalho — e nada além disso. Token de backup acessa só o bucket de backup. Token do app acessa só o banco do app. Chave OAuth de Twitter só com escopos que o Postiz realmente usa.

Se um atacante conseguir uma credencial, o estrago é limitado pelo que ela pode fazer. Uma chave R2 com permissão de Object Read & Write em um único bucket é infinitamente melhor que uma chave master da conta.

# Exemplo: policy AWS S3 mínima para o backup
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
      "s3:ListBucket"
    ],
    "Resource": [
      "arn:aws:s3:::postiz-backups",
      "arn:aws:s3:::postiz-backups/*"
    ]
  }]
}
# SEM s3:* ou Resource: "*" — atacante não enumera outros buckets

✓ O que FAZER

  • Criar IAM user dedicado por função (backup, deploy, app).
  • Escopos OAuth mínimos — só os endpoints usados.
  • Rodar containers como user não-root (user: no compose).
  • Postgres do Postiz com role própria, sem SUPERUSER.

✗ O que NÃO fazer

  • Usar credencial root/master no servidor.
  • Reusar a mesma API key em deploy e em backup.
  • Pedir todos os escopos OAuth "por garantia".
  • Compartilhar a senha do Postgres com a app via env-debug.

Conceitos-chave

PoLP

Principle of Least Privilege.

IAM policy

Regra explícita de quem faz o quê em que recurso.

Scopes OAuth

Subconjunto de permissões pedidas ao usuário.

Separação

Uma identidade por função, nunca compartilhada.

6

🆘 Disaster recovery plan

Um DR plan responde duas perguntas antes do desastre: RTO (Recovery Time Objective — quanto tempo até voltar) e RPO (Recovery Point Objective — quanto de dados pode perder). Para um Postiz pessoal: RTO de 2h e RPO de 24h é razoável. Para SaaS pago: RTO <30min, RPO <1h exige replicação contínua.

A defesa robusta é a regra 3-2-1: três cópias, em dois meios diferentes, com uma off-site. Volume Docker (1), dump local em /var/backups (2), restic no R2 (3) — meios diferentes (disco do servidor vs. object storage), uma off-site (R2).

📋 Runbook mínimo — DR do Postiz

  • 1. Provisionar host novo: VPS limpa, Docker instalado, DNS apontando.
  • 2. Restaurar segredos: .env, RESTIC_PASSWORD, chaves R2 (do gerenciador offline).
  • 3. Puxar último snapshot: restic restore latest --target /.
  • 4. Subir Postgres vazio via docker compose up -d postgres.
  • 5. Restaurar dump: pg_restore -U postiz -d postiz -c --if-exists < backup.dump.
  • 6. Subir app: docker compose up -d e validar /api/health.
  • 7. Reconectar OAuth: alguns tokens podem precisar renovação manual no painel.
# Runbook em script — DR_RESTORE.sh (mantenha no repositório)
#!/usr/bin/env bash
set -euo pipefail

source /etc/postiz-backup.env

echo "[1/4] Baixando último snapshot..."
restic restore latest --target /tmp/dr

echo "[2/4] Subindo Postgres..."
cd ~/postiz && docker compose up -d postgres
until docker exec postiz-postgres pg_isready -U postiz; do sleep 2; done

echo "[3/4] Restaurando dump mais recente..."
LATEST=$(ls -t /tmp/dr/var/backups/postiz/postiz_*.dump | head -1)
docker exec -i postiz-postgres pg_restore -U postiz -d postiz -c --if-exists < "$LATEST"

echo "[4/4] Subindo aplicação..."
docker compose up -d
sleep 10
curl -fsS http://localhost:5000/api/health && echo "DR concluído ✓"

🎯 Dica prática

O runbook precisa estar acessível quando o servidor está fora do ar. Não adianta versionar só no repositório que vive no servidor que caiu. Mantenha cópia: GitHub privado + PDF impresso na gaveta + nota no gerenciador de senhas. Pareça paranoico — desastre acontece num domingo às 3h da manhã.

Conceitos-chave

RTO

Tempo máximo aceitável até a aplicação voltar.

RPO

Janela máxima de dados que pode-se perder.

Regra 3-2-1

3 cópias, 2 meios, 1 off-site. Mínimo viável.

Runbook

Procedimento passo a passo, testado e acessível.

🎉 Parabéns! Você concluiu o curso MkBlogs

Da primeira ideia de "quero publicar online" até um Postiz em produção com domínio, HTTPS, monitoramento e plano de disaster recovery — você atravessou as seis trilhas. Não é pouca coisa. A maior parte dos blogs que existem hoje na internet foram colocados no ar por pessoas que sabiam menos do que você sabe agora.

O que você domina agora

Fundamentos (T1) — o que é um blog, como a web funciona, vocabulário técnico.
Postiz (T2) — setup Docker, configuração, IA, agendamento, troubleshooting.
Redes sociais (T3) — OAuth, integração de Twitter, LinkedIn, Instagram, calendário.
Blogs (T4) — Ghost, WordPress, static sites, escolha de stack e RSS.
Do zero (T5) — VPS, Docker em produção, primeiro deploy real.
Deploy avançado (T6) — domínio, HTTPS, monitoramento, backup e DR.

🚀 Próximos passos

  • Publique algo público esta semana. Não precisa ser perfeito — precisa existir.
  • Agende a primeira rotação de tokens daqui a 90 dias no calendário.
  • Faça o primeiro restore drill ainda este mês, antes que você esqueça como funciona.
  • Volte aqui sempre que precisar revisar um conceito — o curso fica.

"A internet foi feita por pessoas que decidiram publicar. Agora você é uma delas."