Ir al contenido

Google Workspace

Backup y restauración cloud-to-cloud de cuentas Google Workspace. Rust puro — un plugin de FD (gworkspace-fd.so) más un binario de backend, sin JVM, sin Python, sin agentes dentro de Google.

CargaBackupIncrementalRestauración
Gmail.eml con fidelidad total (RFC822, etiquetas preservadas)history APIreinserción con etiquetas recreadas
Google Drivebinarios nativos + Docs/Sheets/Slides exportados (docx/xlsx/pptx, configurable)changes APIsubida bajo NGBackup Restore <fecha>/
Google CalendarJSON por eventorecorrido completoevents.import
Google ContactsJSON por contactorecorrido completopeople:createContact

Todas las cargas soportan restauración al origen y restauración entre usuarios (restore_user=). La descarga de archivos virtuales al filesystem (where=/path) está actualmente limitada (ver Restauración abajo). Shared Drives, la configuración de Gmail y los tombstones de borrado están en el roadmap.

  • Service account + Domain-Wide Delegation (OAuth 2.0, JWT RS256) — una clave protege todo el dominio; impersonación por usuario, sin contraseñas de usuario.
  • Nuevos usuarios incluidos automáticamente: los jobs de dominio enumeran los usuarios activos vía Admin SDK Directory API en cada ejecución.
  • Formato Gmail compatible con Takeout: cada mensaje es un .eml independiente con cabecera X-Gmail-Labels: — el formato autocontenido se abre en cualquier cliente de correo tras una exportación vía restauración al origen.
  • Consciente de cuotas: backoff exponencial truncado en 429 / 403 rate-limit / 5xx respetando Retry-After (modelo de cuota de Gmail: 6.000 unidades/min/usuario).
  • Higiene de secretos: las claves inline se rechazan al parsear; la clave de la service account vive en un archivo 0600 (sa_key_file=).
  1. Google Cloud Console: crea un proyecto (o reutiliza el proyecto de backup de la organización), habilita las APIs Gmail API, Google Drive API, Google Calendar API, People API y Admin SDK API, crea una service account y descarga su clave JSON.
  2. Copia el Client ID OAuth2 numérico de la service account (en la página de detalles de la SA).
  3. Consola de administración de Workspace (admin.google.com): Seguridad → Controles de API → Delegación de todo el dominio → añade el client ID numérico con exactamente estos scopes (la propagación puede tardar hasta 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

Instala el paquete ngbackup-gworkspace-plugin (deb/rpm) en el host cliente que ejecutará los jobs y coloca la clave y la configuración:

Ventana de terminal
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

Comprobación previa (código de salida 0 = todo correcto):

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

Formato key = value; las claves de la línea Plugin = sobrescriben el archivo.

ClaveSignificado
domainDominio primario del Workspace (rutas virtuales y consultas a la Directory API)
sa_key_fileClave JSON de la service account con DWD habilitada — modo 0600
admin_userAdmin impersonado para la enumeración de usuarios vía Directory API (jobs de dominio y list pluginobjects); innecesario cuando los jobs pasan user= explícito
working_dirDirectorio de checkpoints (historyId de Gmail / pageToken de Drive), por defecto /opt/ngbackup/working
log_levelOpcional; debug para ejecuciones verbosas
page_sizeOpcional; tamaño de página de las APIs (p. ej. 500)
export_docsFormato de exportación de Docs: docx | odt | pdf | txt | html | md
export_sheetsFormato de exportación de Sheets: xlsx | ods | pdf | csv | tsv
export_slidesFormato de exportación de Slides: pptx | odp | pdf | txt
max_file_mbLímite por archivo de Drive en MiB, 0 = ilimitado
include_trashRespaldar elementos en la papelera (no por defecto)

El prefijo gworkspace: enruta al plugin; todo lo que sigue son pares key=value separados por espacios. Valores de mode=: account (los cuatro servicios) | gmail | drive | calendar | contacts | verify. Los jobs de dominio (mode=account sin user=) reenumeran los usuarios activos en cada ejecución — los nuevos empleados quedan protegidos automáticamente.

Enumera los usuarios del dominio desde la consola con líneas Plugin = listas para pegar:

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 en bconsole → marca los elementos → where=/. Los mensajes de Gmail se reinsertan con sus etiquetas (las etiquetas personalizadas ausentes se recrean); los archivos de Drive caen bajo NGBackup Restore <fecha>/ (nunca sobrescribe archivos vivos); los eventos de Calendar se reimportan; los Contacts se recrean.

A otro usuario (empleado que se fue, migración)

Sección titulada «A otro usuario (empleado que se fue, migración)»

Añade restore_user=target@domain a la cadena de opciones del plugin en el momento de la restauración. Todos los objetos seleccionados caen en la cuenta de destino (Drive bajo la carpeta de restauración, Gmail con etiquetas, Calendar en primary).

Descarga al filesystem (where=/path) — limitación

Sección titulada «Descarga al filesystem (where=/path) — limitación»

Restaurar los archivos virtuales del plugin a una ubicación alternativa del filesystem produce actualmente archivos de 0 bytes: el File Daemon enruta las restauraciones a ubicación alternativa a su extractor interno (core), que no invoca al plugin y no puede materializar un data-stream de plugin como contenido de archivo normal. Es una limitación compartida entre los plugins de archivo virtual de NGBackup, no específica de Google Workspace. Para obtener archivos en disco, restaura al origen (en la cuenta original o en una cuenta temporal) y exporta desde Google. Enrutar las restauraciones where= por el plugin está en el roadmap.

Ver también: Restauración, Instant Recovery & V2V.

Logs: /opt/ngbackup/working/gworkspace-backend.log. Checkpoints: /opt/ngbackup/working/gworkspace/<domain>/state.json — borrar el archivo fuerza un resync completo en el próximo Incremental (seguro; nunca borra datos ya respaldados).

SíntomaCausa probableAcción
token exchange HTTP 401 invalid_grantDWD no autorizada / client ID incorrecto / desfase de relojRevisa el paso de delegación; timedatectl con NTP activo
token exchange HTTP 400 + unauthorized_clientLista de scopes en la consola admin ≠ scopes solicitadosPega la lista exacta de 9 scopes
Directory users.list HTTP 403admin_user= no es admin del WorkspaceUsa un super-admin (o admin delegado con Usuarios→Lectura)
Ráfagas de Gmail 403 rateLimitExceeded>6.000 unidades de cuota/min/usuarioEl plugin hace backoff automáticamente; para 1.500+ cuentas divide los jobs por rangos de usuarios
history.list 404 en cada IncrementalhistoryId expirado (intervalo >1 semana)Esperado — la ejecución recae en un recorrido completo y recrea el checkpoint
Archivo de Drive omitido exceeds the 10 MB export capArchivo nativo de Google demasiado grande para files.exportExpórtalo manualmente o acepta la omisión (arreglo en el roadmap)
Job falla backend completed without producing any virtual filesCredenciales malas / selección vacíaEjecuta mode=verify; revisa los selectores del FileSet
inline secret ... is forbidden (ADR-008)sa_key=/password= en la línea Plugin=Usa sa_key_file= (0600)