{"id":1751,"date":"2026-09-24T07:29:25","date_gmt":"2026-09-24T10:29:25","guid":{"rendered":"https:\/\/www.linuxpro.com.br\/?p=1751"},"modified":"2026-09-24T08:09:05","modified_gmt":"2026-09-24T11:09:05","slug":"databasus-backup-de-postgresql-mysql-e-mariadb-com-restore-testado","status":"publish","type":"post","link":"https:\/\/www.linuxpro.com.br\/es\/2026\/09\/databasus-backup-de-postgresql-mysql-e-mariadb-com-restore-testado\/","title":{"rendered":"Databasus: backup de PostgreSQL, MySQL y MariaDB con restore probado"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/databasus-backup-postgresql-mysql-mariadb.webp\" alt=\"Mascote LinuxPro guardando cilindros de PostgreSQL, MySQL, MariaDB e MongoDB num cofre de backup com o logo do Databasus, com o cachorro caramelo cyborg ao lado\" width=\"1486\" height=\"856\" \/><\/p>\n<p>Todo mundo tem backup de banco. Pouca gente tem backup que <strong>j\u00e1 foi restaurado<\/strong>. O <a href=\"https:\/\/github.com\/databasus\/databasus\">Databasus<\/a> ataca justamente essa diferen\u00e7a: \u00e9 uma ferramenta self-hosted, com interface web, que agenda dumps de PostgreSQL, MySQL, MariaDB e MongoDB, comprime, criptografa, manda para S3, Google Drive, SFTP ou disco local, avisa no Telegram ou no Slack e, para PostgreSQL, ainda sobe um container descart\u00e1vel, restaura o backup e conta as linhas de cada tabela para provar que ele funciona.<\/p>\n<p>O projeto \u00e9 open source sob licen\u00e7a Apache 2.0, escrito em Go (backend) e TypeScript (frontend), e roda em Docker. Neste post a gente v\u00ea como ele funciona por dentro, instala, configura um backup de MariaDB\/MySQL, entende o PITR do PostgreSQL 17 e monta o agente de verifica\u00e7\u00e3o de restore.<\/p>\n<h2>De Postgresus a Databasus<\/h2>\n<p>O projeto nasceu como <strong>Postgresus<\/strong>, criado por Rostislav Dugin, e era s\u00f3 para PostgreSQL. Quando ganhou suporte a MySQL, MariaDB e MongoDB, o nome deixou de fazer sentido e virou Databasus, no fim de 2025 (as issues de migra\u00e7\u00e3o &#8220;Upgrade path from Postgresus to Databasus&#8221; s\u00e3o de dezembro de 2025). O reposit\u00f3rio antigo <code>RostislavDugin\/postgresus<\/code> hoje redireciona para <code>databasus\/databasus<\/code>.<\/p>\n<p>Em setembro de 2026 o reposit\u00f3rio passa de 8.600 estrelas, a imagem no Docker Hub tem mais de 1,9 milh\u00e3o de pulls e a vers\u00e3o mais recente \u00e9 a <strong>v3.60.0<\/strong>, de 22\/09\/2026. O ritmo de releases \u00e9 alto, ent\u00e3o confira a <a href=\"https:\/\/github.com\/databasus\/databasus\/releases\">p\u00e1gina de releases<\/a> antes de fixar uma vers\u00e3o.<\/p>\n<h2>Faz backup de MySQL e MariaDB? Sim, mas s\u00f3 l\u00f3gico<\/h2>\n<p>Essa \u00e9 a pergunta que mais importa para quem roda LAMP. A resposta curta: <strong>sim<\/strong>, com uma limita\u00e7\u00e3o que precisa ficar clara.<\/p>\n<table>\n<thead>\n<tr>\n<th>Banco<\/th>\n<th>Vers\u00f5es<\/th>\n<th>Tipo de backup<\/th>\n<th>Ferramenta usada<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>PostgreSQL<\/td>\n<td>14, 15, 16, 17 e 18<\/td>\n<td>l\u00f3gico e f\u00edsico (f\u00edsico s\u00f3 no 17+)<\/td>\n<td><code>pg_dump<\/code>, <code>pg_basebackup<\/code>, <code>pg_receivewal<\/code><\/td>\n<\/tr>\n<tr>\n<td>MySQL<\/td>\n<td>5.7, 8.0, 8.4, 9 e 26<\/td>\n<td>s\u00f3 l\u00f3gico<\/td>\n<td><code>mysqldump<\/code><\/td>\n<\/tr>\n<tr>\n<td>MariaDB<\/td>\n<td>5.5, 10, 11, 12 e 13<\/td>\n<td>s\u00f3 l\u00f3gico<\/td>\n<td><code>mariadb-dump<\/code><\/td>\n<\/tr>\n<tr>\n<td>MongoDB<\/td>\n<td>4.2+, 5, 6, 7 e 8<\/td>\n<td>s\u00f3 l\u00f3gico<\/td>\n<td>dump nativo<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Para MySQL, o Databasus chama o <code>mysqldump<\/code> oficial; para MariaDB, usa o <code>mariadb-dump<\/code> nativo, e n\u00e3o o dump do MySQL, o que evita incompatibilidades com recursos espec\u00edficos do MariaDB. Os bin\u00e1rios de cada vers\u00e3o v\u00eam embutidos na imagem, ent\u00e3o voc\u00ea n\u00e3o instala cliente nenhum. Olhando o c\u00f3digo do backend, os par\u00e2metros passados ao dump s\u00e3o estes:<\/p>\n<ul>\n<li><code>--single-transaction<\/code>: snapshot consistente em InnoDB, sem travar as tabelas;<\/li>\n<li><code>--routines<\/code>, <code>--triggers<\/code> e <code>--events<\/code>: procedures, functions, triggers e eventos agendados entram no backup;<\/li>\n<li><code>--quick<\/code> e <code>--max-allowed-packet=1G<\/code>: linhas em streaming, sem carregar tabelas inteiras na mem\u00f3ria;<\/li>\n<li><code>--no-tablespaces<\/code>: dispensa o privil\u00e9gio <code>PROCESS<\/code>;<\/li>\n<li>compress\u00e3o de rede zstd no MySQL 8.0+ (no 5.7 cai para a compress\u00e3o antiga).<\/li>\n<\/ul>\n<p>Tem um cuidado com MariaDB Galera: no restore, o Databasus desliga a replica\u00e7\u00e3o s\u00f3 naquela sess\u00e3o (<code>wsrep_on<\/code>), para que o dump n\u00e3o seja replicado linha a linha pelo cluster. Isso pode ser desativado na configura\u00e7\u00e3o do banco. Quem roda o <a href=\"\/2026\/09\/mariadb-galera-cluster-mariabackup-ubuntu\/\">cluster Galera<\/a> vai gostar desse detalhe.<\/p>\n<p>A senha vai num <code>.my.cnf<\/code> tempor\u00e1rio com permiss\u00e3o <code>0600<\/code>, nunca na linha de comando, ent\u00e3o n\u00e3o aparece no <code>ps<\/code> nem nos logs.<\/p>\n<p><strong>O que voc\u00ea n\u00e3o tem em MySQL\/MariaDB:<\/strong> backup f\u00edsico, incremental ou PITR com binlog. Para bancos grandes (o pr\u00f3prio site do projeto fala em algo acima de 100 GB) ou quando voc\u00ea precisa voltar ao segundo exato antes de um <code>DELETE<\/code> errado, continue com <code>mariabackup<\/code>\/XtraBackup e binlog, como mostrei no post do <a href=\"\/2026\/09\/mariadb-galera-cluster-mariabackup-ubuntu\/\">cluster MariaDB Galera com mariabackup<\/a>. A verifica\u00e7\u00e3o autom\u00e1tica de restore, descrita mais abaixo, tamb\u00e9m \u00e9 s\u00f3 para PostgreSQL por enquanto. Para o banco de um WordPress, um GLPI ou um Nextcloud de porte m\u00e9dio, o dump di\u00e1rio com reten\u00e7\u00e3o GFS resolve bem.<\/p>\n<h2>Como ele funciona por dentro<\/h2>\n<p>O Databasus roda <strong>longe do banco<\/strong>. Ele se conecta pela rede, como qualquer cliente, e puxa o dump em streaming, bloco a bloco. Nada \u00e9 instalado no servidor de banco. Se o banco estiver numa rede fechada, ele alcan\u00e7a por t\u00fanel SSH atrav\u00e9s de um bastion. Isso tamb\u00e9m significa que funciona com bancos gerenciados (RDS, Cloud SQL, Azure Database), que n\u00e3o deixam instalar nada no host.<\/p>\n<figure><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/databasus-arquitetura.webp\" alt=\"Arquitetura do Databasus: bancos, servidor Databasus, storages, notificadores e agente de verifica\u00e7\u00e3o\" width=\"1200\" height=\"720\" \/><\/figure>\n<p>O fluxo de cada backup:<\/p>\n<ol>\n<li>o agendador dispara no hor\u00e1rio (a cada hora, di\u00e1rio, semanal, mensal ou cron);<\/li>\n<li>o dump sai do banco em streaming e \u00e9 comprimido com zstd (no PostgreSQL, formato custom do <code>pg_dump<\/code> com zstd n\u00edvel 5);<\/li>\n<li>cada arquivo \u00e9 criptografado com AES-256-GCM, com chave pr\u00f3pria derivada da chave mestra, do ID do backup e de um salt aleat\u00f3rio;<\/li>\n<li>o arquivo vai para o storage escolhido, que s\u00f3 enxerga dado cifrado;<\/li>\n<li>a pol\u00edtica de reten\u00e7\u00e3o apaga os antigos: por tempo, por quantidade, por tamanho ou no esquema GFS (av\u00f4-pai-filho, com c\u00f3pias por hora, dia, semana, m\u00eas e ano);<\/li>\n<li>o notificador avisa sucesso ou falha.<\/li>\n<\/ol>\n<p>O estado interno (agendamentos, usu\u00e1rios, hist\u00f3rico) fica num PostgreSQL embutido na pr\u00f3pria imagem, em <code>databasus-data\/pgdata<\/code>, e as credenciais dos bancos ficam cifradas com a chave <code>databasus-data\/secret.key<\/code>. Guarde essa chave em outro lugar: sem ela, os backups criptografados viram lixo.<\/p>\n<h2>Instala\u00e7\u00e3o<\/h2>\n<p>S\u00e3o quatro caminhos: script autom\u00e1tico, <code>docker run<\/code>, Docker Compose e Helm. Se Docker ainda \u00e9 novidade, o post <a href=\"\/2026\/09\/a-historia-do-docker\/\">A hist\u00f3ria do Docker<\/a> d\u00e1 o contexto.<\/p>\n<h3>Script (Debian\/Ubuntu)<\/h3>\n<p>Instala Docker e Compose se faltarem, coloca tudo em <code>\/opt\/databasus\/<\/code> e configura o in\u00edcio autom\u00e1tico no boot:<\/p>\n<pre><code class=\"language-bash\">sudo apt-get install -y curl\ncurl -sSL https:\/\/raw.githubusercontent.com\/databasus\/databasus\/refs\/heads\/main\/install-databasus.sh -o install-databasus.sh\nless install-databasus.sh     # leia antes de rodar como root\nsudo bash install-databasus.sh<\/code><\/pre>\n<h3>Docker Compose<\/h3>\n<p>\u00c9 o caminho que eu prefiro, porque fica versionado junto com o resto da infraestrutura:<\/p>\n<pre><code class=\"language-yaml\">services:\n  databasus:\n    container_name: databasus\n    image: databasus\/databasus:latest\n    ports:\n      - \"127.0.0.1:4005:4005\"\n    volumes:\n      - .\/databasus-data:\/databasus-data\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"databasus\", \"healthcheck\"]\n      interval: 30s\n      timeout: 5s\n      retries: 3\n      start_period: 60s<\/code><\/pre>\n<pre><code class=\"language-bash\">mkdir -p \/opt\/databasus && cd \/opt\/databasus\n# salve o docker-compose.yml acima aqui\ndocker compose up -d\ndocker compose ps<\/code><\/pre>\n<p>Publiquei a porta s\u00f3 em <code>127.0.0.1<\/code> de prop\u00f3sito: a interface guarda credenciais de todos os seus bancos, ent\u00e3o ela fica atr\u00e1s de um proxy reverso com TLS, n\u00e3o exposta crua na internet. Se o Docker Hub limitar o pull, a mesma imagem est\u00e1 em <code>ghcr.io\/databasus\/databasus:latest<\/code>. Em produ\u00e7\u00e3o, troque <code>latest<\/code> por uma tag fixa.<\/p>\n<h3>Kubernetes com Helm<\/h3>\n<pre><code class=\"language-bash\">helm install databasus oci:\/\/ghcr.io\/databasus\/charts\/databasus \\\n  -n databasus --create-namespace \\\n  --set ingress.enabled=true \\\n  --set ingress.hosts[0].host=backup.exemplo.com.br<\/code><\/pre>\n<p>O chart tamb\u00e9m aceita <code>service.type=LoadBalancer<\/code>, NodePort e HTTPRoute do Gateway API. Em bare metal, o <a href=\"\/2026\/09\/metallb-loadbalancer-kubernetes-bare-metal-layer2-bgp\/\">MetalLB<\/a> entrega o IP do LoadBalancer.<\/p>\n<h3>Compilando a imagem a partir do c\u00f3digo<\/h3>\n<p>Se a sua pol\u00edtica exige imagem constru\u00edda em casa (auditoria, registry interno, sem pull do Docker Hub), o <code>Dockerfile<\/code> na raiz do reposit\u00f3rio faz tudo em est\u00e1gios: frontend com Node 24 e pnpm, backend e agente de verifica\u00e7\u00e3o com Go 1.26, e imagem final em <code>debian:bookworm-slim<\/code> com os clientes de banco j\u00e1 embutidos no reposit\u00f3rio (<code>assets\/tools<\/code>, uns 320 MB de bin\u00e1rios de <code>pg_dump<\/code>, <code>mysqldump<\/code> e <code>mariadb-dump<\/code> por vers\u00e3o). Use sempre uma tag de release, n\u00e3o a <code>main<\/code>:<\/p>\n<pre><code class=\"language-bash\">git clone --depth 1 --branch v3.60.0 https:\/\/github.com\/databasus\/databasus.git\ncd databasus\ndocker build --build-arg APP_VERSION=v3.60.0 -t registry.exemplo.com.br\/databasus:v3.60.0 .\ndocker push registry.exemplo.com.br\/databasus:v3.60.0<\/code><\/pre>\n<p>No meu teste, numa m\u00e1quina com cache vazio, o build levou cerca de 2 minutos e 15 segundos e gerou uma imagem de 800 MB, o mesmo tamanho da oficial. O <code>APP_VERSION<\/code> aparece na interface e em <code>\/api\/v1\/system\/version<\/code>. No <code>docker-compose.yml<\/code>, basta trocar a linha <code>image:<\/code> pela sua tag.<\/p>\n<h3>Proxy reverso com nginx<\/h3>\n<pre><code class=\"language-nginx\">server {\n    listen 443 ssl http2;\n    server_name backup.exemplo.com.br;\n\n    ssl_certificate     \/etc\/letsencrypt\/live\/backup.exemplo.com.br\/fullchain.pem;\n    ssl_certificate_key \/etc\/letsencrypt\/live\/backup.exemplo.com.br\/privkey.pem;\n\n    client_max_body_size 0;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:4005;\n        proxy_set_header Host $host;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}<\/code><\/pre>\n<p>Abra <code>https:\/\/backup.exemplo.com.br<\/code> e crie a primeira conta: <strong>ela vira a administradora da inst\u00e2ncia<\/strong>, ent\u00e3o fa\u00e7a isso logo depois de subir, antes de qualquer outra pessoa chegar na tela.<\/p>\n<h2>Backup de MariaDB e MySQL passo a passo<\/h2>\n<h3>1. Usu\u00e1rio s\u00f3 de leitura<\/h3>\n<p>O Databasus trabalha por padr\u00e3o com usu\u00e1rio somente leitura e checa os privil\u00e9gios antes de rodar. Pelo c\u00f3digo, <code>SELECT<\/code> e <code>SHOW VIEW<\/code> s\u00e3o obrigat\u00f3rios; sem <code>TRIGGER<\/code> e <code>EVENT<\/code> o backup n\u00e3o falha, mas deixa triggers e eventos de fora. Ent\u00e3o d\u00ea os quatro:<\/p>\n<pre><code class=\"language-sql\">CREATE USER 'databasus'@'10.0.0.50' IDENTIFIED BY 'troque-esta-senha';\nGRANT SELECT, SHOW VIEW, TRIGGER, EVENT ON wordpress.* TO 'databasus'@'10.0.0.50';\nFLUSH PRIVILEGES;<\/code><\/pre>\n<p>Troque <code>10.0.0.50<\/code> pelo IP do servidor do Databasus e <code>wordpress<\/code> pelo seu schema. Se o MariaDB escuta s\u00f3 em <code>127.0.0.1<\/code>, n\u00e3o abra a porta 3306: use o t\u00fanel SSH embutido.<\/p>\n<h3>2. Cadastrar o banco<\/h3>\n<ol>\n<li><strong>New Database<\/strong> \u2192 escolha MySQL ou MariaDB;<\/li>\n<li>host, porta, usu\u00e1rio, senha e banco (ou t\u00fanel SSH e TLS);<\/li>\n<li>agenda: por exemplo di\u00e1rio \u00e0s 03:00, fora do hor\u00e1rio de pico;<\/li>\n<li>storage: disco local, S3 (AWS, MinIO, Backblaze B2), Cloudflare R2, Google Drive, Dropbox, SFTP, FTP ou qualquer destino do rclone;<\/li>\n<li>reten\u00e7\u00e3o: GFS \u00e9 o padr\u00e3o sensato, por exemplo 7 di\u00e1rios, 4 semanais, 12 mensais;<\/li>\n<li>notifica\u00e7\u00e3o: Telegram, Slack, Discord, Teams, Mattermost, e-mail ou webhook.<\/li>\n<\/ol>\n<p>Salvando, ele valida conex\u00e3o e privil\u00e9gios, detecta a vers\u00e3o do servidor sozinho e j\u00e1 aponta se falta algum grant. Dois detalhes que vi no teste: ao ligar os backups, ele <strong>dispara o primeiro backup na hora<\/strong>, ent\u00e3o confira antes se a op\u00e7\u00e3o <strong>Encryption<\/strong> est\u00e1 em <em>Encrypted<\/em> (\u00e9 o padr\u00e3o da interface para backup l\u00f3gico). Sem criptografia, o arquivo no storage \u00e9 um <code>.zst<\/code> leg\u00edvel por qualquer um com acesso ao bucket.<\/p>\n<p>Um bom macete da FAQ do projeto: se voc\u00ea tem r\u00e9plica, aponte o backup para ela. O <code>--single-transaction<\/code> n\u00e3o para a replica\u00e7\u00e3o e tira a carga do prim\u00e1rio.<\/p>\n<h3>3. Restaurar<\/h3>\n<p>O dump \u00e9 um <code>mysqldump<\/code> padr\u00e3o, comprimido com zstd. Baixe o backup pela interface (ele sai j\u00e1 descriptografado, como <code>.sql.zst<\/code>) e restaure em qualquer MySQL\/MariaDB, em outra vers\u00e3o ou outro provedor. A interface mostra o comando exato de cada backup; o formato \u00e9 este:<\/p>\n<pre><code class=\"language-bash\">zstd -dc wp-lab_backup_2026-09-24_10-23-28.sql.zst | mariadb -h 127.0.0.1 -u root -p wordpress_restore<\/code><\/pre>\n<p>Fa\u00e7a isso pelo menos uma vez, num banco de teste, antes de precisar. \u00c9 o \u00fanico jeito de saber quanto tempo o restore leva de verdade.<\/p>\n<h2>PostgreSQL: f\u00edsico, incremental e PITR<\/h2>\n<p>Aqui o Databasus vai bem al\u00e9m do dump. A partir do <strong>PostgreSQL 17<\/strong>, que trouxe backup incremental nativo em n\u00edvel de bloco (desenvolvido por Robert Haas, com ajuda de David Steele, autor do pgBackRest), ele faz:<\/p>\n<ul>\n<li><strong>full<\/strong> com <code>pg_basebackup<\/code>, transmitido direto para o Databasus;<\/li>\n<li><strong>incremental<\/strong> com <code>pg_basebackup --incremental<\/code>: o servidor, com <code>summarize_wal = on<\/code>, sabe quais blocos mudaram e s\u00f3 eles trafegam;<\/li>\n<li><strong>WAL streaming<\/strong> cont\u00ednuo com <code>pg_receivewal<\/code>, que fecha a corrente entre um backup e outro.<\/li>\n<\/ul>\n<p>No restore, o <code>pg_combinebackup<\/code> junta o full com os incrementais num diret\u00f3rio de dados e o PostgreSQL reaplica o WAL at\u00e9 o instante que voc\u00ea escolher. \u00c9 PITR de verdade, com RPO perto de zero. Tudo pelo protocolo de replica\u00e7\u00e3o, remoto, sem instalar nada no servidor do banco.<\/p>\n<p>No servidor PostgreSQL, habilite o resumo de WAL e libere replica\u00e7\u00e3o para o usu\u00e1rio do backup:<\/p>\n<pre><code class=\"language-bash\">sudo -u postgres psql -c \"ALTER SYSTEM SET summarize_wal = on;\"\nsudo -u postgres psql -c \"SELECT pg_reload_conf();\"\nsudo -u postgres psql -c \"CREATE ROLE databasus WITH LOGIN REPLICATION PASSWORD 'troque-esta-senha';\"\n# pg_hba.conf: host replication databasus 10.0.0.50\/32 scram-sha-256<\/code><\/pre>\n<p>Nas vers\u00f5es 14 a 16, s\u00f3 o backup l\u00f3gico com <code>pg_dump<\/code> est\u00e1 dispon\u00edvel.<\/p>\n<p>Uma nota de hist\u00f3rico: vers\u00f5es antigas usavam um <strong>agente de backup<\/strong> instalado no host do banco. O projeto admite na FAQ que foi um erro (RTO longo, duas coisas para configurar, n\u00e3o roda em RDS) e removeu. Quem ainda tem backups desse tipo pode ficar na <strong>v3.42.0<\/strong>, a \u00faltima que os suporta; a atualiza\u00e7\u00e3o avisa antes de mexer. O racioc\u00ednio est\u00e1 no <a href=\"https:\/\/github.com\/databasus\/databasus\/blob\/main\/adr\/0009-why-remote-physical-backups-instead-of-agents.md\">ADR-0009<\/a>.<\/p>\n<h2>Verifica\u00e7\u00e3o de restore: o backup testado de verdade<\/h2>\n<p>Um backup que terminou sem erro n\u00e3o \u00e9 um backup que restaura. Checksum pega bit podre no arquivo, mas n\u00e3o diz se o dump est\u00e1 completo. O c\u00f3digo de sa\u00edda diz que o comando rodou, mas n\u00e3o pega um usu\u00e1rio sem permiss\u00e3o num objeto, uma extens\u00e3o ausente ou um tablespace diferente, casos em que objetos somem do dump em sil\u00eancio.<\/p>\n<p>A <a href=\"https:\/\/databasus.com\/restore-verification\/\">verifica\u00e7\u00e3o de restore<\/a> resolve isso restaurando de fato. Um <strong>agente de verifica\u00e7\u00e3o<\/strong>, um bin\u00e1rio Go pequeno que roda numa m\u00e1quina sua com Docker:<\/p>\n<ol>\n<li>pega o backup mais recente na fila do Databasus (conex\u00e3o HTTPS de sa\u00edda, nada precisa ser aberto para dentro);<\/li>\n<li>sobe um container de banco descart\u00e1vel na mesma vers\u00e3o major;<\/li>\n<li>roda o restore com a ferramenta nativa e confere o tamanho restaurado;<\/li>\n<li>conta as linhas de cada tabela;<\/li>\n<li>destr\u00f3i o container e manda o relat\u00f3rio.<\/li>\n<\/ol>\n<p><strong>Limite atual:<\/strong> no c\u00f3digo do agente, o restore s\u00f3 est\u00e1 implementado para PostgreSQL (<code>pg_restore<\/code>, com imagem Docker s\u00f3 de Postgres). Para MySQL e MariaDB, o teste de restore continua sendo manual, como na se\u00e7\u00e3o anterior.<\/p>\n<h3>Subindo o agente<\/h3>\n<p>Em <code>Settings \u2192 Verification agents \u2192 Create verification agent<\/code>, d\u00ea um nome (<code>verificador-01<\/code>) e copie o token, que s\u00f3 aparece uma vez. Na m\u00e1quina de verifica\u00e7\u00e3o:<\/p>\n<pre><code class=\"language-bash\">curl -L -o verification-agent \\\n  \"https:\/\/backup.exemplo.com.br\/api\/v1\/system\/verification-agent?arch=amd64\" \\\n  &amp;&amp; chmod +x verification-agent\n\n.\/verification-agent start \\\n  --databasus-host=https:\/\/backup.exemplo.com.br \\\n  --agent-id=&lt;AGENT_ID&gt; \\\n  --token=&lt;TOKEN&gt; \\\n  --max-cpu=2 \\\n  --max-ram-mb=2048 \\\n  --max-disk-gb=20 \\\n  --max-concurrent-jobs=1<\/code><\/pre>\n<p>Troque <code>amd64<\/code> por <code>arm64<\/code> em ARM. Os <code>--max-*<\/code> s\u00e3o or\u00e7amentos totais, divididos entre os jobs simult\u00e2neos, com piso de 1 CPU e 512 MB por job. O disco \u00e9 o que mais erra: cada job precisa do tamanho do backup, mais o tamanho do banco restaurado, mais uma folga de at\u00e9 5 GB. O Databasus precisa estar em <code>https:\/\/<\/code>; HTTP puro s\u00f3 com <code>--allow-insecure-http<\/code>, para laborat\u00f3rio.<\/p>\n<p>O <code>start<\/code> vira daemon e grava as flags em <code>databasus-verification.json<\/code>. Para rodar sob systemd, use <code>run<\/code>, que fica em primeiro plano e l\u00ea as mesmas flags salvas. Fa\u00e7a o primeiro <code>start<\/code> dentro de <code>\/opt\/databasus-agent<\/code>, para o JSON ficar l\u00e1:<\/p>\n<pre><code class=\"language-ini\"># \/etc\/systemd\/system\/databasus-verification.service\n[Unit]\nDescription=Databasus verification agent\nAfter=docker.service network-online.target\nRequires=docker.service\n\n[Service]\nWorkingDirectory=\/opt\/databasus-agent\nExecStart=\/opt\/databasus-agent\/verification-agent run\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n<pre><code class=\"language-bash\">cd \/opt\/databasus-agent\n.\/verification-agent stop        # para o daemon criado pelo start\nsudo systemctl daemon-reload\nsudo systemctl enable --now databasus-verification\n.\/verification-agent status<\/code><\/pre>\n<p>Se o <a href=\"\/2026\/09\/dominando-o-systemd-comandos-essenciais\/\">systemd<\/a> ainda \u00e9 territ\u00f3rio estranho, o post dedicado ajuda.<\/p>\n<h3>Agendando<\/h3>\n<p>Nas configura\u00e7\u00f5es de cada banco, ligue <strong>Scheduled verification<\/strong> e escolha:<\/p>\n<ul>\n<li><strong>After backup<\/strong>: todo backup bem-sucedido \u00e9 verificado em seguida. A garantia mais forte. Se chega backup novo antes de terminar a verifica\u00e7\u00e3o anterior, a pendente \u00e9 cancelada e s\u00f3 o mais recente espera na fila;<\/li>\n<li><strong>hourly, daily, weekly, monthly<\/strong> com hor\u00e1rio;<\/li>\n<li><strong>cron<\/strong> em UTC, por exemplo <code>0 4 * * 0<\/code> (domingo \u00e0s 04:00 UTC).<\/li>\n<\/ul>\n<p>As notifica\u00e7\u00f5es de sucesso e de falha s\u00e3o independentes. Ligue s\u00f3 a de falha para n\u00e3o criar ru\u00eddo. Cada verifica\u00e7\u00e3o mostra linha do tempo, c\u00f3digo de sa\u00edda, tamanho restaurado, n\u00famero de schemas e tabelas e a contagem de linhas por tabela.<\/p>\n<h2>Testei no laborat\u00f3rio<\/h2>\n<p>Antes de escrever, subi a v3.60.0 em containers locais: a imagem oficial e a compilada a partir do <code>Dockerfile<\/code>, apontando para um MariaDB 11.8 e um MySQL 8.4 com tabela, view, trigger e evento, usando o usu\u00e1rio com s\u00f3 <code>SELECT, SHOW VIEW, TRIGGER, EVENT<\/code>. O resultado:<\/p>\n<ul>\n<li>a vers\u00e3o do servidor foi detectada sozinha e os privil\u00e9gios foram registrados como <code>EVENT,SELECT,SHOW VIEW,TRIGGER<\/code>;<\/li>\n<li>backups de MariaDB e MySQL conclu\u00eddos em menos de um segundo, com status <code>COMPLETED<\/code>;<\/li>\n<li>no storage local, o backup criptografado \u00e9 um blob opaco, acompanhado de um <code>.metadata<\/code> com salt e IV; sem criptografia, \u00e9 um <code>.zst<\/code> com o SQL leg\u00edvel;<\/li>\n<li>o download pela interface j\u00e1 sai descriptografado (<code>.sql.zst<\/code>); restaurado com <code>zstd -dc<\/code> num banco novo, voltaram as linhas, a view, o trigger no MariaDB e o evento no MySQL;<\/li>\n<li>a imagem compilada localmente se comportou igual \u00e0 oficial.<\/li>\n<\/ul>\n<h2>Seguran\u00e7a<\/h2>\n<ul>\n<li><strong>AES-256-GCM<\/strong> nos arquivos de backup e nos segredos guardados (senhas, tokens, strings de conex\u00e3o), que n\u00e3o aparecem nem em mensagens de erro;<\/li>\n<li><strong>storage &#8220;zero trust&#8221;<\/strong>: o bucket s\u00f3 recebe arquivo cifrado, ent\u00e3o um vazamento do S3 n\u00e3o entrega seus dados;<\/li>\n<li><strong>usu\u00e1rio somente leitura<\/strong> por padr\u00e3o;<\/li>\n<li><strong>workspaces<\/strong> com pap\u00e9is viewer, member, admin e owner, e <strong>log de auditoria<\/strong>, export\u00e1vel via OpenTelemetry;<\/li>\n<li><strong>2FA<\/strong> por c\u00f3digo enviado por e-mail no login com senha; login com Google ou GitHub tamb\u00e9m \u00e9 aceito.<\/li>\n<\/ul>\n<p>No lado do c\u00f3digo, o pipeline roda CodeQL, gitleaks, semgrep, Dependabot, Trivy na imagem e no Dockerfile, e cada PR faz ciclos completos de backup e restore contra containers reais de todas as vers\u00f5es suportadas. O README tamb\u00e9m \u00e9 franco sobre IA: o projeto entrou nos programas Claude for Open Source e Codex for Open Source em mar\u00e7o de 2026, usa IA para revis\u00e3o e busca de falhas e rejeita PRs &#8220;vibe code&#8221;.<\/p>\n<h2>N\u00e3o esque\u00e7a do backup do pr\u00f3prio Databasus<\/h2>\n<p>Parece \u00f3bvio, mas \u00e9 o ponto que derruba a estrat\u00e9gia inteira. Em <code>\/opt\/databasus\/databasus-data\/<\/code> (ou onde voc\u00ea montou o volume):<\/p>\n<ul>\n<li><code>secret.key<\/code>: <strong>obrigat\u00f3rio<\/strong>. S\u00f3 com ele j\u00e1 d\u00e1 para <a href=\"https:\/\/databasus.com\/how-to-recover-without-databasus\">recuperar os backups sem o Databasus<\/a>;<\/li>\n<li><code>pgdata\/<\/code>: configura\u00e7\u00f5es, agendamentos e hist\u00f3rico, necess\u00e1rio para reconstruir a interface;<\/li>\n<li><code>backups\/<\/code>: se voc\u00ea usa storage local.<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">cd \/opt\/databasus\ndocker compose stop\ntar czf \/root\/databasus-data-$(date +%F).tar.gz databasus-data\/\ndocker compose start<\/code><\/pre>\n<p>Guarde o <code>secret.key<\/code> num cofre de senhas, como o <a href=\"\/2026\/09\/vaultwarden-bitwarden-self-hosted\/\">Vaultwarden<\/a>, fora do servidor. Para migrar de m\u00e1quina, basta recriar a pasta <code>databasus-data<\/code> com esses arquivos e subir o container. Se a senha de admin se perder:<\/p>\n<pre><code class=\"language-bash\">docker exec -it databasus .\/main --list-admins\ndocker exec -it databasus .\/main --new-password=\"NovaSenhaForte123\" --email=\"admin@exemplo.com.br\"<\/code><\/pre>\n<h2>Quando usar, quando n\u00e3o usar<\/h2>\n<p><strong>Vale a pena<\/strong> se voc\u00ea tem v\u00e1rios bancos pequenos e m\u00e9dios espalhados (WordPress, GLPI, Zabbix, sistemas internos) e hoje eles dependem de scripts com cron que ningu\u00e9m monitora. O Databasus troca isso por uma tela com agenda, reten\u00e7\u00e3o, criptografia, alerta e hist\u00f3rico, e no PostgreSQL ainda entrega restore testado automaticamente e, a partir do 17, PITR.<\/p>\n<p><strong>N\u00e3o substitui<\/strong> o <code>mariabackup<\/code>\/XtraBackup com binlog em MySQL\/MariaDB grandes nem quando o RPO precisa ser de segundos nesses bancos. Tamb\u00e9m n\u00e3o \u00e9 ferramenta de backup de arquivos: para diret\u00f3rios e volumes, continue com restic, borg ou similares. E, como toda pe\u00e7a de backup, monitore o pr\u00f3prio Databasus: o healthcheck do container entra f\u00e1cil no <a href=\"\/2026\/09\/uptime-kuma-no-linux-monitoramento-self-hosted-com-docker-e-nginx\/\">Uptime Kuma<\/a> ou no <a href=\"\/2026\/09\/gatus-no-ubuntu-monitoramento-como-codigo-com-docker\/\">Gatus<\/a>.<\/p>\n<p>O resumo: backup que nunca foi restaurado \u00e9 esperan\u00e7a, n\u00e3o backup. O Databasus n\u00e3o resolve tudo, mas deixa o restore testado barato o suficiente para virar rotina.<\/p>\n<p><strong>Links:<\/strong> <a href=\"https:\/\/github.com\/databasus\/databasus\">GitHub<\/a> \u00b7 <a href=\"https:\/\/databasus.com\/installation\">instala\u00e7\u00e3o<\/a> \u00b7 <a href=\"https:\/\/databasus.com\/mysql-backup\">MySQL e MariaDB<\/a> \u00b7 <a href=\"https:\/\/databasus.com\/restore-verification\/\">verifica\u00e7\u00e3o de restore<\/a> \u00b7 <a href=\"https:\/\/databasus.com\/faq\/\">FAQ<\/a> \u00b7 <a href=\"https:\/\/databasus.com\/security\">seguran\u00e7a<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Databasus programa, comprime, cifra y env\u00eda backups de PostgreSQL, MySQL, MariaDB y MongoDB, y en PostgreSQL adem\u00e1s restaura cada backup en un contenedor desechable para demostrar que funciona. Instalaci\u00f3n, build mediante Dockerfile, MySQL\/MariaDB probados en laboratorio y agente de verificaci\u00f3n.<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[46,120],"tags":[410,509,156,326,252,510,203],"class_list":["post-1751","post","type-post","status-publish","format-standard","hentry","category-devops","category-servidores","tag-backup","tag-databasus","tag-docker","tag-mariadb","tag-mysql","tag-postgresql","tag-self-hosted"],"_links":{"self":[{"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/posts\/1751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/comments?post=1751"}],"version-history":[{"count":3,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/posts\/1751\/revisions"}],"predecessor-version":[{"id":1755,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/posts\/1751\/revisions\/1755"}],"wp:attachment":[{"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/media?parent=1751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/categories?post=1751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/es\/wp-json\/wp\/v2\/tags?post=1751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}