Changelog
Todas as mudanças notáveis do BackupAlly são documentadas aqui.
O formato segue Keep a Changelog.
[0.35.0] - 2026-09-25
Adicionado
- `storage download`: baixa um backup do storage (local/B2/S3) para um diretório local, com conferência de integridade por SHA-256 contra o `history`
- `restore --from-storage`: baixa do storage e restaura num único comando, sem passo manual de download
- `history --task
` (match exato) eartifacts[]no histórico — qual arquivo foi para qual storage, comremote_pathesha256 [[storage]]local só exigepath— não pede maisbucket- `--capabilities` ganha as features de storage/download/restore/history desta versão
Corrigido
- Retenção nunca apagava task com espaço ou pontuação no nome — a primeira execução depois do upgrade limpa o acumulado de uma vez (ver Políticas de Retenção)
- Temporário de run não era apagado depois de sucesso: cada execução bem-sucedida deixava para trás um diretório com ~3x o tamanho do backup — corrigido, apagado sempre no fim
- Log de
-o jsonnão sai mais misturado a linha de log no stdout task runpassa a respeitar-c/--configstorage list/storage infonão erram mais 3h na hora exibida (fuso local convertido para UTC só na exibição)- Backup em B2/S3 sem
pathconfigurado agora é encontrado porstorage download/restoremesmo com prefixo ou${hostname}/${date}no layout de gravação
Segurança
- Contenção de path reforçada no download/restore, incluindo recusa de
symlink apontando para fora do storage local, e validação/sanitização de
--database— ver Segurança e Criptografia
[0.34.1] - 2026-09-23
Corrigido
quick -t s3/-t b2recusam em vez de fingir sucesso. Os dois eram stubs: diziam "concluído" sem subir nada de verdade. Agora recusam antes de qualquer trabalho, com erro claro — use uma task para gravar em nuvem peloquick
[0.34.0] - 2026-09-23
Adicionado
- `--capabilities`: descoberta, em JSON, do que o binário instalado sabe fazer de verdade
quick --credentials-ref: credencial por referência ao cofre local, em vez de valor em texto puro por--access-key/--secret-keyquick.executedescreve o artefato gravado:artifact_path,bytes_totalesha256do arquivo final
[0.33.0] - 2026-09-23
Alterado
- Histórico e áreas de trabalho saem de
/tmp, para/var/lib/backupally/temp(logs dequick,verify --deep, rollback de restore, cópia pré-restore de banco). Migração automática na primeira execução — ver Configuração Global task list -o jsondevolve o objeto rico em todo caminho — o mesmo formato que--enabled/--disabledjá usavam, comenabled,kindeschedule— ver `task list`
[0.32.0] - 2026-09-19
Adicionado
quick --series <SÉRIE> --retention-days <N>: depois de um backup bem-sucedido, remove os backups da mesma série com mais de N dias — ver Retenção por Série
[0.30.0] - 2026-09-05
Corrigido
- Túnel SSH vazava um processo
sshpor backup (MongoDB e ClickHouse não fechavam o processo; PostgreSQL só fechava se a conexão falhasse). Agora há um túnel só por execução da task, aberto antes do primeiro dump e fechado ao fim, com sucesso ou erro - MySQL ignorava a configuração de túnel SSH, conectando direto sem avisar. Passa a tunelar como os demais drivers
- Porta local do túnel colidia entre execuções simultâneas; agora é escolhida dinamicamente
- Host desconhecido podia travar a conexão à espera de confirmação; a confirmação passa a ser automática na primeira conexão
Alterado
- Primeira conexão ao bastion grava a identidade dele; se ela mudar depois, o backup recusa a conexão em vez de seguir em silêncio
[target.ssh]documentado como seção própria (host, usuário, porta, chave, host visto do bastion).task validateverifica a configuração;task validate --deeptesta a conexão de verdade, passando pelo túnel- Modo individual (um banco por vez) reaproveita o mesmo túnel no run inteiro, para MySQL e PostgreSQL
- MongoDB por
urinão passa pelo túnel (só a forma host/porta) - Os subcomandos
taskganharam a flag global--config(caminho do arquivo de configuração) - Ver Banco atrás de Bastion (SSH)
[0.29.0] - 2026-09-04
Alterado
- Backup cifrado em blocos e restore em streaming: o pico de memória deixa de crescer com o tamanho do backup — um backup de 300 MB usou 22 MB no backup e 21 MB no restore. O restore não depende mais do
tardo sistema - Versões anteriores à 0.29.0 não leem backups feitos pela 0.29.0. A 0.29.0 lê todos os formatos anteriores. Ver Segurança e Criptografia
- Erros nomeados no restore:
truncado no bloco N(arquivo incompleto — vercleanup --residues) ebloco N adulterado ou chave errada - Upload ao B2 abaixo de 100 MB em stream; verificação pós-upload sem reler o arquivo
[0.28.0] - 2026-09-04
Corrigido
- Restore de fileset entregava pedaços, não arquivos: o backup de arquivos fatiava cada arquivo em blocos de 1 MiB e guardava só o hash de cada bloco, sem caminho nem ordem. O
restoredecifrava e descomprimia certo e devolviachunk_<hash>.data. Agora o backup guarda a árvore real (caminho relativo à raiz, symlink, diretório vazio, permissão e mtime) e orestoredevolve os arquivos abaixo de--path. Ver Restaurar Arquivos- Backups de fileset feitos antes da 0.28.0 não restauram como arquivos: nunca houve informação para remontá-los. Refaça o backup com a versão nova
- Include inexistente agora é erro, não aviso
restorede backup em claro exigia a chave de cifra e falhava por falta de um arquivo que nem ia usarrestoreignorava o--configpara achar a chave: procurava só em/etc/backupally/keys/default.key. Agora usadefault_key_refdo config, o mesmo caminho que o backup usou- Entrada com
..ou caminho absoluto dentro de um.allyadulterado é recusada na extração, em vez de escrita fora do destino
Alterado
- As instruções do MCP deixam de anunciar "deduplicação" no formato
.ally: o fatiamento antigo nunca deduplicou nada
[0.27.2] - 2026-09-04
Adicionado
- Chave pública de release publicada no CDN:
pubkey.pubemhttps://get.backupally.com/x86_64/,/aarch64/e na raiz, fingerprint1C6665A7E22166F5. Permite verificar manualmente um binário baixado à mão comminisign. Ver Verificação do binário
Corrigido
self-update -o jsonemitia JSON cru em vez do envelope: era o último subcomando fora do padrão. Agora todos os desfechos (concluído, já atualizado, adiado, falhou) saem no envelopeschema_version: "2.0", e as mensagens humanas continuam em stderr
[0.27.1] - 2026-08-25
Corrigido
- A unit systemd não declarava
SyslogIdentifier: o journald identificava as linhas pelo nome do processo, o que quebra em silêncio se o binário for renomeado ou invocado por wrapper. AgoraSyslogIdentifier=backupallyestá na unit gerada. Não é retroativo: em servidor já instalado, rodesudo backupally install-servicepara reescrever a unit
[0.27.0] - 2026-08-24
Adicionado
measure— medição de volumes: quanto cada database ocupa na origem (dados + índices), quanto foi o último backup comprimido, a taxa de compressão e o crescimento sobre o run anterior. Saída em tabela ou envelopemeasureno-o json. Quando falta um dos lados o campo sai como—, nunca como número inventado. Ver backupally measure
[0.26.0] - 2026-08-24
Adicionado
- Cadastro de storages (
/etc/backupally/storages.d): destino declarado uma vez e referenciado por id em[task] storage_refs = ["b2-prod"]. O[[storage]]inline continua valendo e os dois convivem na mesma task. Comandosstorage registry add | remove | list | show | test. Ver storage registryaddgrava a credencial no secret store cifrado e escreve só a referência${secret:...}no cadastro; o arquivo é criado com0600shownunca revela valor de credencial;testvalida o acesso em modo read-only- Referência desconhecida numa task é erro (no executor e no
validate --deep), com a lista do que está cadastrado removerecusa remover destino referenciado por task e nomeia quais;--forceremove e avisa que elas vão falhar
- Prevenções (
[guard]):self-updatenão troca o binário com backup em andamento: adia e informa qual backup está rodando e há quanto tempo.--forceignora;--checknão é afetado. Trava deixada por processo morto é removida sozinha- Backup não começa com a máquina no limite: limites opcionais
max_load_1m,max_load_normalized,min_free_memory_mbemin_free_disk_gbno[guard]do config global. Ausentes = sem limite. A mensagem diz o recurso, o medido e o limite. Ver Configuração Global
Corrigido
self-updateignorava o-o jsonglobal
[0.25.0] - 2026-08-24
Alterado
- Envelope JSON agora é
schema_version: "2.0": mesma forma que os demais clients CCS. Os campos já eram os mesmos; só o carimbo mudou. Nenhuma integração conhecida quebra - Histórico saiu do
/tmp: o registro dos backups já feitos morava em/tmp/backupally/logse um reboot apagava tudo. Agora fica em/var/lib/backupally/logs. Migração automática e única na primeira execução; se não houver permissão em/var/lib, cai para o diretório antigo e avisa que ele é volátil
Adicionado
cleanup --residues: procura o que o cleanup comum não vê — upload em partes inacabado no B2 (ocupa cota e não aparece na listagem normal) e diretório de run abandonado no temp.--dry-runrelata sem remover. O relatório diz quantos destinos remotos foram consultados
[0.24.1] - 2026-08-24
Corrigido
- Verificação reprovava arquivo enviado em partes: a B2 devolve
contentSha1 = "none"para large file, e o verificador comparava isso com o hash local. O upload terminava certo e o run era dado como falho. Agora large file é reconhecido: confere-se o tamanho, e o SHA1 do arquivo inteiro vai emfileInfo.large_file_sha1
[0.24.0] - 2026-08-24
Corrigido
- Todo upload ao B2 morria em 60 segundos: o timeout era o tempo total da requisição, então qualquer envio mais longo era interrompido. Agora o timeout é dimensionado pelo tamanho do arquivo (piso 60s, teto 6h)
- Upload em partes acima de 100 MB: cada parte tem sua janela e seu retry — uma falha em 3 GB reenvia 100 MB, não o arquivo inteiro. Falha em qualquer parte cancela o large file para não deixar upload pela metade
[0.23.0] - 2026-08-23
Adicionado
task validate --deep: checagens de conectividade, todas read-only — resolve o host (inclusivedocker:<container>[/<rede>]), autentica no banco, confere credenciais de storage, resolve os${secret:...}e verifica se os caminhos de fileset existem. Sai com código ≠ 0 se algo falhar. Driver sem teste de conexão aparece como pulado, nunca como aprovado. O modo raso agora diz o que não checou. Ver task validate
Corrigido
- Scheduler nunca relia as tasks do disco: editar um arquivo em
pipeline/não tinha efeito até reiniciar o serviço, enquantotask runlia o arquivo fresco — o teste manual passava e o agendado seguia com a config antiga. Agora o scheduler detecta mudança (arquivo editado, criado ou removido) e recarrega sozinho, registrando em log
[0.22.0] - 2026-08-23
Corrigido
- Literal booleano não valia dentro de expressão em
when:true/falsesó eram reconhecidos sozinhos; dentro de&&,||,!ou parênteses caíam no tratamento "comando de shell" e viravam falso silenciosamente. Como owhendecide se a task roda, uma condição composta podia pular o backup sem explicação - Condição em formato desconhecido agora avisa: era registrada em nível debug, virou aviso nomeando a condição e explicando que a task não roda se a saída do shell for diferente de
"0" - Verificador reprovava arquivo íntegro: formato não reconhecido e fim-de-arquivo suspeito eram registrados como aviso, mas invalidavam a verificação inteira. Agora são informativos — quem reprova é erro de verdade (checksum divergente, arquivo vazio ou truncado com tamanho esperado)
[0.21.0] - 2026-08-23
Corrigido
iddo[[storage]]passou a valer: o identificador declarado no config era descartado e os logs mostravam sempre um nome sintético. Com dois destinos na mesma task, os dois apareciam iguais e não dava para saber qual havia falhado
[0.20.0] - 2026-08-23
Adicionado
timezonena task: o cron passa a poder ser interpretado no fuso declarado (timezone = "America/Sao_Paulo"). Ausente = UTC, que é o comportamento histórico — nenhum agendamento existente muda de horário ao atualizar. Nome IANA inválido não cai para UTC em silêncio: a task não é agendada e o erro nomeia a task
Corrigido
- Horários agora dizem de que fuso são: o cron era lido em UTC e o histórico exibido em hora local, sem nada indicar qual era qual. Num servidor em
-03,schedule = "30 3 * * *"rodava 00:30 local e o histórico mostrava00:30, confirmando o engano - A carga da task registra o próximo disparo nos dois fusos
historymostra o offset;history --showexibe local e UTCscheduler list(CLI) escheduler_list(MCP) calculavam em hora local enquanto o agendamento era em UTC — dois horários para a mesma task- Task com agendamento inválido não derruba mais a carga das outras nem some calada
[0.19.0] - 2026-08-23
Corrigido
- Backup parcial deixou de se passar por sucesso: o registro do run era gravado no meio do processo e nunca reescrito, então ficava eternamente "In Progress", com duração
0.0s. E database que falhava comon_error = continuenão ia para registro nenhum - Novo status
partial: run que termina com itens falhos nunca éCompleted - O resumo grava nome e erro de cada item que falhou; o relatório em texto ganhou a seção "Itens que FALHARAM"
task runexibeBackup PARCIAL: N de M item(ns) falharame sai com código ≠ 0 — automação por cron não tinha como saber- Notificação de backup parcial vai como aviso, nomeando os itens, em vez de sucesso
[0.18.0] - 2026-08-23
Corrigido
- Upload sem retry tirava database do backup da noite: um timeout transitório do storage derrubava aquele database definitivamente. Upload e verificação agora repetem até 3 vezes, com backoff exponencial (2s → 4s, teto 30s) e jitter
- Erro permanente (configuração ausente, arquivo de origem inexistente) não é repetido
- A repetição da verificação renova a autorização no storage remoto
self-updateem host com binárioimmutable: o atributo era restaurado antes do ajuste de permissão, e o comando terminava comOperation not permittedmesmo tendo instalado a versão nova
[0.17.0] - 2026-08-22
Adicionado
- Dump de roles/extensions/triggers do PostgreSQL: extensions por database, triggers via
pg_get_triggerdef, e roles cluster-wide em arquivo separado - Sintaxe
host = "docker:<container>/<rede>"para declarar a rede do container
Corrigido
- Container em mais de uma rede quebrava a resolução de host: os IPs de todas as redes eram concatenados sem separador, e a falha aparecia depois como erro de DNS. Agora, container em duas ou mais redes falha alto, listando as redes e dizendo como declarar a desejada
[0.16.0] - 2026-08-01
Adicionado
- Dump consistente do PostgreSQL: cada database é dumpado dentro de uma única transação
REPEATABLE READ READ ONLY— schema e dados saem do mesmo snapshot (equivalente ao--single-transactiondopg_dump). Ligado por padrão
Corrigido
extractusava-opara dois parâmetros diferentes
[0.15.0] - 2026-08-01
Adicionado
- Restore de ClickHouse e SQLite
[0.14.1] - 2026-07-31
Corrigido
backup --targeterestorefalhavam sempre com erro de runtime- Coleta de lixo não reconhecia arquivos
.tar.ally
[0.14.0] - 2026-07-31
Corrigido
- Restore de backup criptografado era impossível (envelope AEAD)
- Retenção remota não removia nada
- Driver S3 no binário padrão não fazia nada, em silêncio
[0.13.0 – 0.13.1] - 2026-06
Adicionado
- Envelope CCS em toda a superfície CLI (
-o json|yaml) - Streaming NDJSON de eventos de fase em
-o json
Corrigido
- Self-update em streaming para disco (antes carregava o binário inteiro em memória)
[0.11.0 – 0.12.0] - 2026-05
Adicionado
- Comando
self-updatecom verificação de assinatura Ed25519 - Verificação de assinatura nos releases
[0.10.0] - 2026-04-09
Adicionado
- Build multi-arch static musl: Binários x86_64 + aarch64 statically linked (zero deps glibc), rodam em qualquer Linux (Ubuntu 18.04+, Debian 10+, CentOS 7+, Alpine). Resolve problema de hosts com glibc antiga não conseguirem atualizar
- Módulo de segurança (
src/security/):- TLS Pinning ativo: SPKI pin verification via
rustls::ServerCertVerifiercustomizado paraget.backupally.comeapi.github.com. Pins extraídos em build-time pelobuild.rs - Cliente HTTP centralizado:
get_http_client()singleton, 10 call sites migrados - Message signing: Assinatura RSA-SHA256 (PKCS#1 v1.5) de mensagens
- Anti-replay: Nonce store com TTL + verificação NTP via
timedatectl init_security(): Chamado no startup, reporta status dos pins e NTP
- TLS Pinning ativo: SPKI pin verification via
- CDN multi-arch:
install upgradeagora baixa dehttps://get.backupally.com/{arch}/{version}/backupally, detecta arch viastd::env::consts::ARCH, fallback para latest e parsing deversion.txt - GitOps v2.0:
.gitops.ymlcom channels stable/rc, architectures [x86_64, aarch64], compat com clientes < v0.10.0
Corrigido
- Bug crítico: retention/GC remoto:
apply_retention()usava catálogo local efêmero que NUNCA tocava no remoto — política era "executada com sucesso" no log mas nenhum arquivo antigo era removido do B2/S3. Agora itera sobre cada storage e chamagc_targetreal - Arquivo VERSION desincronizado: Continha 0.7.3 enquanto Cargo.toml tinha 0.9.9. Removido (single source of truth = Cargo.toml)
Modificado
- Tokio sem feature
"full"(features explícitas), ~1.5MB de binário eliminado - OpenSSL vendored para suporte a musl com deps transitivos (mysql_async, tokio-tungstenite, b2client)
[0.9.9] - 2026-02-12
Adicionado
- Comando
storage: Gerenciar e verificar backups no storage remotostorage list: Listar backups com checksums remotosstorage info: Estatísticas do storage (total de arquivos, tamanho)storage verify: Verificar integridade com validação de header .allystorage check: Verificar existência de backup específico
- Verificação profunda de headers .ally (magic bytes, formato)
- Cruzamento de backups com histórico de execução
- Checksums por driver: SHA256 (local), SHA1 (B2), ETag (S3)
[0.9.8] - 2026-02-11
Adicionado
- MCP Server com 11 resources e 4 prompts guiados
- Integração com Claude e assistentes de IA
- Módulo de instruções embarcado para MCP
Modificado
- Melhorias na documentação de API
[0.9.0] - 2026-02-01
Adicionado
- GitOps distribution via Backblaze B2
- Build benchmarks e métricas de performance
- Infraestrutura completa de testes
Corrigido
- Estabilidade do scheduler em alta carga
- Memory leaks em backups de longa duração
[0.8.0] - 2026-01-15
Adicionado
- Key Fingerprinting: Identificação de chaves por 8 bytes
- Secrets Management: Armazenamento criptografado de credenciais
- Installation Wizard: Comando
backupally initinterativo - Central Server Integration: Backup de chaves para disaster recovery
- Pattern Resolution: Suporte a
${secret:name},${env:VAR},${file:path}
Modificado
- Formato de header .ally v2 com fingerprint
[0.7.0] - 2026-01-01
Adicionado
- Modular Task Architecture: Arquivos individuais em
/etc/backupally/tasks.d/ - Hot Reload: Detecção automática de mudanças a cada 5 segundos
- Task Management CLI: Comandos create, clone, validate, enable, disable, delete
- Interactive Wizard: Criação guiada de tasks
- Concurrency Control: Priority queue com limite configurável
Modificado
- Pipeline path movido para tasks.d
- Configuração separada por task
[0.6.0] - 2025-12-01
Adicionado
- Driver nativo para ClickHouse
- Suporte a SQLite
- Backup de volumes Docker
- Política de retenção
yearly
Modificado
- Melhoria de performance no FastCDC
- Redução de uso de memória
[0.5.0] - 2025-11-01
Adicionado
- Driver nativo para MongoDB
- Suporte a oplog para point-in-time recovery
- Backup incremental com detecção de mudanças
- Notificações via webhook
Corrigido
- Timeout em bancos grandes
- Tratamento de caracteres especiais em senhas
[0.4.0] - 2025-10-01
Adicionado
- Driver nativo para PostgreSQL
- Suporte a globals (roles, tablespaces)
- Conexão SSL para databases
Modificado
- Refatoração do sistema de drivers
[0.3.0] - 2025-09-01
Adicionado
- Suporte a Backblaze B2
- Suporte a MinIO
- Múltiplos storages por task
- Upload paralelo
Corrigido
- Retry em falhas de rede
- Limpeza de arquivos temporários
[0.2.0] - 2025-08-01
Adicionado
- Criptografia RSA-4096 + AES-256-GCM
- Compressão Zstd, Gzip, LZ4
- Deduplicação com FastCDC
- Scheduler com cron
Modificado
- Formato de arquivo .ally v1
[0.1.0] - 2025-07-01
Adicionado
- Release inicial
- Comando
quickpara backup rápido - Driver MySQL nativo
- Storage local e S3
- CLI básica com Clap
By Borlot.com.br on 05/09/2026