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.
Capacidades
Seção intitulada “Capacidades”| Carga | Backup | Incremental | Restauração |
|---|---|---|---|
| Gmail | .eml com fidelidade total (RFC822, labels preservadas) | history API | reinserção com labels recriadas |
| Google Drive | binários nativos + Docs/Sheets/Slides exportados (docx/xlsx/pptx, configurável) | changes API | upload sob NGBackup Restore <data>/ |
| Google Calendar | JSON por evento | varredura completa | events.import |
| Google Contacts | JSON por contato | varredura completa | people: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
.emlindependente com headerX-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=).
Requisitos
Seção intitulada “Requisitos”- 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.
- Copie o Client ID OAuth2 numérico da service account (na página de detalhes da SA).
- 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.readonlyhttps://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/calendar.readonlyhttps://www.googleapis.com/auth/contacts.readonlyhttps://www.googleapis.com/auth/admin.directory.user.readonlyhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/calendar.eventshttps://www.googleapis.com/auth/contactsInstalação
Seção intitulada “Instalação”Instale o pacote ngbackup-gworkspace-plugin (deb/rpm) no host cliente que executará os jobs e posicione a chave e a configuração:
install -o bacula -g bacula -m 0600 sa-key.json /opt/ngbackup/etc/gworkspace/sa-key.jsoncp gworkspace.conf.example /opt/ngbackup/etc/gworkspace/gworkspace.conf # edit domain/admin_userVerificação pré-voo (código de saída 0 = tudo certo):
sudo -u bacula gworkspace-backend mode=verify \ config_file=/opt/ngbackup/etc/gworkspace/gworkspace.conf user=someone@yourdomainConfiguração
Seção intitulada “Configuração”gworkspace.conf
Seção intitulada “gworkspace.conf”Formato key = value; chaves na linha Plugin = sobrescrevem o arquivo.
| Chave | Significado |
|---|---|
domain | Domínio primário do Workspace (caminhos virtuais e consultas à Directory API) |
sa_key_file | Chave JSON da service account com DWD habilitada — modo 0600 |
admin_user | Admin 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_dir | Diretório de checkpoints (historyId do Gmail / pageToken do Drive), padrão /opt/ngbackup/working |
log_level | Opcional; debug para execuções verbosas |
page_size | Opcional; tamanho de página das APIs (ex.: 500) |
export_docs | Formato de exportação de Docs: docx | odt | pdf | txt | html | md |
export_sheets | Formato de exportação de Sheets: xlsx | ods | pdf | csv | tsv |
export_slides | Formato de exportação de Slides: pptx | odp | pdf | txt |
max_file_mb | Limite por arquivo do Drive em MiB, 0 = ilimitado |
include_trash | Fazer backup de itens na lixeira (no por padrão) |
Linha Plugin=
Seção intitulada “Linha Plugin=”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"Exemplos de FileSet, Schedule e Job
Seção intitulada “Exemplos de FileSet, Schedule e Job”# 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}Restauração
Seção intitulada “Restauração”De volta à mesma conta (recomendado)
Seção intitulada “De volta à mesma conta (recomendado)”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.
Solução de problemas
Seção intitulada “Solução de problemas”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).
| Sintoma | Causa provável | Ação |
|---|---|---|
token exchange HTTP 401 invalid_grant | DWD não autorizada / client ID errado / clock skew | Reconfira o passo de delegação; timedatectl com NTP ligado |
token exchange HTTP 400 + unauthorized_client | Lista de escopos no console admin ≠ escopos solicitados | Cole a lista exata de 9 escopos |
Directory users.list HTTP 403 | admin_user= não é admin do Workspace | Use um super-admin (ou admin delegado com Usuários→Leitura) |
Rajadas de Gmail 403 rateLimitExceeded | >6.000 unidades de quota/min/usuário | O plugin faz backoff automaticamente; para 1.500+ contas divida os jobs por faixas de usuários |
history.list 404 em todo Incremental | historyId 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 cap | Arquivo nativo do Google grande demais para files.export | Exporte manualmente ou aceite o pulo (correção no roadmap) |
Job falha backend completed without producing any virtual files | Credenciais ruins / seleção vazia | Rode mode=verify; confira os seletores do FileSet |
inline secret ... is forbidden (ADR-008) | sa_key=/password= na linha Plugin= | Use sa_key_file= (0600) |