Monalisa
Operação

Backups

Backup diário do PostgreSQL de staging no Garage, a verificação e a restauração.

O PostgreSQL de staging tem backup diário no Garage v2.4.1, um armazenamento compatível com S3 que roda como duas aplicações a mais no mesmo servidor do Dokploy (NOVA-119). A escolha do Garage em vez do MinIO: um binário pequeno, com modo de nó único documentado e uma API de administração para criar o bucket e a chave por script. A imagem dele não tem shell, por isso a configuração inicial é um job separado.

As peças

PeçaO que é
garagedxflrs/garage:v2.4.1, um nó (replication_factor = 1), metadados em SQLite, dois volumes (metadados e dados), atualização stop-first: duas tarefas no mesmo volume de metadados o corromperiam
garage.tomlCommitado sem segredos; o segredo de RPC e o token de administração vêm do ambiente do Dokploy, gerados uma vez pelo apply e nunca impressos
API S3 (porta 3900)A única parte pública: https://s3.novahml.com (Let's Encrypt), path-style, região garage
API de administração (porta 3903)Sem domínio: alcançável só na rede interna do swarm
garage-initJob one-shot (curlimages/curl): define o layout do nó quando ele não tem um, importa a chave de backup que o apply gerou, cria o bucket monalisa-staging-backups e dá à chave leitura e escrita só nesse bucket
Destino garage-stagingDestino S3 do Dokploy, com essa chave
Backup do PostgreSQLpg_dump -Fc do banco, compactado, todo dia às 03:00 UTC pelo agendador do Dokploy, mantendo as 14 cópias mais recentes

O que os backups cobrem

Os backups ficam só no servidor (VPS) do banco. Eles protegem contra erros lógicos (uma migration ruim, um DELETE errado, uma versão quebrada) e permitem voltar staging a um dia anterior. Não protegem contra a perda do servidor ou do disco: não há cópia fora dele, por decisão, porque os dados de staging podem ser reconstruídos.

O Valkey e o ElasticMQ não têm backup. O Valkey guarda só caches, portões de idempotência e sinais de despertar, e pode começar vazio; as filas do ElasticMQ são em memória.

Num servidor novo

  1. dokploy:apply declara garage, garage-init, volumes, montagens, domínio e segredos, e avisa que os backups esperam o garage-init.
  2. dokploy:deploy sobe o Garage e roda o garage-init depois da versão (ver Staging no Dokploy), conferindo que ele termina Complete.
  3. O apply seguinte cria o destino com a chave do garage-init, faz o Dokploy testar a conexão listando o bucket e agenda o backup. Bucket e chave só existem depois do garage-init, e um destino não testado só falharia às 03:00.

O DNS do domínio S3 precisa apontar para o servidor antes do primeiro apply que o usa, para o Let's Encrypt emitir o certificado. Uma mudança em garage.toml só vale depois de republicar o garage na interface; uma mudança no script do garage-init roda com dokploy:deploy --reinit.

Para trocar a chave de backup: remova as duas variáveis da chave do ambiente do garage-init, rode apply (gera um par novo), deploy --reinit (importa) e apply (atualiza o destino), e então apague a chave antiga no Garage, ou ao menos retire o acesso dela ao bucket; o Garage a mantém, com os direitos, até lá.

Verificar: dokploy:backup-check

bun run dokploy:backup-check

O comando dispara o backup agendado na hora e confere que um arquivo .sql.gz novo e não vazio chegou ao bucket, imprimindo a chave e o tamanho dele.

Restaurar

O Dokploy só oferece restauração pela interface (não há endpoint de API), então o teste é manual, num banco de rascunho:

  1. Rode dokploy:backup-check e anote o arquivo que ele imprimiu.
  2. No servidor, crie um banco de rascunho no contêiner do PostgreSQL (createdb … monalisa_restore_check).
  3. Na interface do Dokploy (staging › postgres › Backups › Restore), escolha o destino garage-staging, o arquivo e o banco monalisa_restore_check. O Dokploy roda pg_restore -O --clean --if-exists nesse banco.
  4. Compare com o banco original:
    • a migration mais nova (select name from mikro_orm_migrations order by id desc limit 1) deve ser igual ao latestMigration do /ready;
    • o número de tabelas (select count(*) from information_schema.tables where table_schema = 'public') deve ser igual ao do banco monalisa.
  5. Apague o banco de rascunho (dropdb).

Restaurar sobre o próprio monalisa é a mesma ação na interface, com o nome monalisa: pare a API e os workers antes.

Uma restauração foi testada em 2026-10-09: o banco restaurado tinha as 82 tabelas e as migrations até 0017_authorization-scope-ceiling-locks.

Nesta página