Pular para o conteúdo

Google Workspace

Backup e restauração cloud-to-cloud de contas Google Workspace. Rust puro — um plugin de FD (gworkspace-fd.so) mais um binário de backend, sem JVM, sem Python, sem agentes dentro do Google.

CargaBackupIncrementalRestauração
Gmail.eml com fidelidade total (RFC822, labels preservadas)history APIreinserção com labels recriadas
Google Drivebinários nativos + Docs/Sheets/Slides exportados (docx/xlsx/pptx, configurável)changes APIupload sob NGBackup Restore <data>/
Google CalendarJSON por eventovarredura completaevents.import
Google ContactsJSON por contatovarredura completapeople:createContact

Todas as cargas suportam restauração à origem e restauração entre usuários (restore_user=). O download de arquivos virtuais para o filesystem (where=/path) é atualmente limitado (veja Restauração abaixo). Shared Drives, configurações do Gmail e tombstones de exclusão estão no roadmap.

  • Service account + Domain-Wide Delegation (OAuth 2.0, JWT RS256) — uma chave protege o domínio inteiro; impersonação por usuário, sem senhas de usuário.
  • Novos usuários incluídos automaticamente: jobs de domínio enumeram os usuários ativos via Admin SDK Directory API a cada execução.
  • Formato Gmail compatível com Takeout: cada mensagem é um .eml independente com header X-Gmail-Labels: — o formato autocontido abre em qualquer cliente de e-mail após exportação via restore-para-origem.
  • Ciente de quotas: backoff exponencial truncado em 429 / 403 rate-limit / 5xx honrando Retry-After (modelo de quota do Gmail: 6.000 unidades/min/usuário).
  • Higiene de segredos: chaves inline são rejeitadas no parse; a chave da service account vive em um arquivo 0600 (sa_key_file=).
  1. Google Cloud Console: crie um projeto (ou reutilize o projeto de backup da organização), habilite as APIs Gmail API, Google Drive API, Google Calendar API, People API e Admin SDK API, crie uma service account e baixe a chave JSON.
  2. Copie o Client ID OAuth2 numérico da service account (na página de detalhes da SA).
  3. Console de administração do Workspace (admin.google.com): Segurança → Controles de API → Delegação em todo o domínio → adicione o client ID numérico com exatamente estes escopos (a propagação pode levar até 24 h, normalmente minutos):
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/drive.readonly
https://www.googleapis.com/auth/calendar.readonly
https://www.googleapis.com/auth/contacts.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/gmail.modify
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/calendar.events
https://www.googleapis.com/auth/contacts

Instale o pacote ngbackup-gworkspace-plugin (deb/rpm) no host cliente que executará os jobs e posicione a chave e a configuração:

Terminal window
install -o bacula -g bacula -m 0600 sa-key.json /opt/ngbackup/etc/gworkspace/sa-key.json
cp gworkspace.conf.example /opt/ngbackup/etc/gworkspace/gworkspace.conf # edit domain/admin_user

Verificação pré-voo (código de saída 0 = tudo certo):

Terminal window
sudo -u bacula gworkspace-backend mode=verify \
config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf user=someone@yourdomain

Formato key = value; chaves na linha Plugin = sobrescrevem o arquivo.

ChaveSignificado
domainDomínio primário do Workspace (caminhos virtuais e consultas à Directory API)
sa_key_fileChave JSON da service account com DWD habilitada — modo 0600
admin_userAdmin impersonado para enumeração de usuários via Directory API (jobs de domínio e list pluginobjects); desnecessário quando os jobs passam user= explícito
working_dirDiretório de checkpoints (historyId do Gmail / pageToken do Drive), padrão /opt/ngbackup/working
log_levelOpcional; debug para execuções verbosas
page_sizeOpcional; tamanho de página das APIs (ex.: 500)
export_docsFormato de exportação de Docs: docx | odt | pdf | txt | html | md
export_sheetsFormato de exportação de Sheets: xlsx | ods | pdf | csv | tsv
export_slidesFormato de exportação de Slides: pptx | odp | pdf | txt
max_file_mbLimite por arquivo do Drive em MiB, 0 = ilimitado
include_trashFazer backup de itens na lixeira (no por padrão)

O prefixo gworkspace: roteia para o plugin; tudo depois dele são pares key=value separados por espaço. Valores de mode=: account (os quatro serviços) | gmail | drive | calendar | contacts | verify. Jobs de domínio (mode=account sem user=) reenumeram os usuários ativos a cada execução — novos funcionários são protegidos automaticamente.

Enumere os usuários do domínio pelo console com linhas Plugin = prontas para colar:

list pluginobjects client=<fd> plugin="gworkspace: config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf"
# Whole-domain, all services (Gmail + Drive + Calendar + Contacts).
FileSet {
Name = "FS-GWorkspace-Domain"
Include {
Options { Signature = MD5; Compression = GZIP }
Plugin = "gworkspace: mode=account \
config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf"
}
}
# Gmail only, two explicit users, excluding a label.
FileSet {
Name = "FS-GWorkspace-Gmail-Pilot"
Include {
Options { Signature = MD5; Compression = GZIP }
Plugin = "gworkspace: mode=gmail \
config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf \
labels_exclude=Newsletters"
}
}
# Drive only, PDFs kept native, Google Docs exported as ODT.
FileSet {
Name = "FS-GWorkspace-Drive"
Include {
Options { Signature = MD5; Compression = GZIP }
Plugin = "gworkspace: mode=drive \
config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf \
export_docs=odt"
}
}
# 2x/day: Full weekly + Incremental at 07:00 and 19:00.
# Gmail incrementals use history.list, Drive uses changes.list.
Schedule {
Name = "Sched-GWorkspace-2xDay"
Run = Level=Full sun at 01:00
Run = Level=Incremental mon-sat at 07:00
Run = Level=Incremental mon-sat at 19:00
}
Job {
Name = "BackupGoogleWorkspace"
Type = Backup
Level = Incremental
Client = ngbackup-fd # FD where gworkspace-fd.so is installed
FileSet = "FS-GWorkspace-Domain"
Schedule = "Sched-GWorkspace-2xDay"
Storage = File1
Pool = Default
Messages = Standard
Accurate = no
}

restore no bconsole → marque os itens → where=/. Mensagens do Gmail são reinseridas com suas labels (labels personalizadas ausentes são recriadas); arquivos do Drive caem sob NGBackup Restore <data>/ (nunca sobrescreve arquivos vivos); eventos do Calendar são reimportados; Contacts recriados.

Para outro usuário (funcionário desligado, migração)

Seção intitulada “Para outro usuário (funcionário desligado, migração)”

Adicione restore_user=target@domain à string de opções do plugin no momento da restauração. Todos os objetos selecionados caem na conta de destino (Drive sob a pasta de restauração, Gmail com labels, Calendar no primary).

Download para o filesystem (where=/path) — limitação

Seção intitulada “Download para o filesystem (where=/path) — limitação”

Restaurar os arquivos virtuais do plugin para um local alternativo no filesystem atualmente produz arquivos de 0 bytes: o File Daemon roteia restaurações para local alternativo ao seu extrator interno (core), que não aciona o plugin e não consegue materializar um data-stream de plugin como conteúdo de arquivo comum. É uma limitação compartilhada entre os plugins de arquivo virtual do NGBackup, não específica do Google Workspace. Para obter arquivos em disco, restaure à origem (na conta original ou numa conta temporária) e exporte a partir do Google. Rotear restaurações where= pelo plugin está no roadmap.

Veja também: Restauração, Instant Recovery & V2V.

Logs: /opt/ngbackup/working/gworkspace-backend.log. Checkpoints: /opt/ngbackup/working/gworkspace/<domain>/state.json — apagar o arquivo força um resync completo no próximo Incremental (seguro; nunca apaga dados já copiados).

SintomaCausa provávelAção
token exchange HTTP 401 invalid_grantDWD não autorizada / client ID errado / clock skewReconfira o passo de delegação; timedatectl com NTP ligado
token exchange HTTP 400 + unauthorized_clientLista de escopos no console admin ≠ escopos solicitadosCole a lista exata de 9 escopos
Directory users.list HTTP 403admin_user= não é admin do WorkspaceUse um super-admin (ou admin delegado com Usuários→Leitura)
Rajadas de Gmail 403 rateLimitExceeded>6.000 unidades de quota/min/usuárioO plugin faz backoff automaticamente; para 1.500+ contas divida os jobs por faixas de usuários
history.list 404 em todo IncrementalhistoryId expirado (intervalo >1 semana)Esperado — a execução recai para varredura completa e recria o checkpoint
Arquivo do Drive pulado exceeds the 10 MB export capArquivo nativo do Google grande demais para files.exportExporte manualmente ou aceite o pulo (correção no roadmap)
Job falha backend completed without producing any virtual filesCredenciais ruins / seleção vaziaRode mode=verify; confira os seletores do FileSet
inline secret ... is forbidden (ADR-008)sa_key=/password= na linha Plugin=Use sa_key_file= (0600)