Google Drive Uploader CLI

Una herramienta CLI de alto rendimiento escrita en Go para subir archivos a Google Drive. Soporta archivos grandes (hasta 50 GB) y manejo automático de directorios.

Características

  • Soporte para archivos grandes: subidas reanudables para transferencias confiables.
  • Gestión de carpetas: crea automáticamente carpetas si no existen en Drive.
  • Seguro: usa el flujo estándar de autenticación OAuth 2.0.
  • Listo para automatización: ruta configurable para el token, ideal para CI/CD o tareas programadas (Cron).

Requisitos previos

  • Go 1.20 o superior
  • Un proyecto en Google Cloud con la API de Google Drive habilitada
  • Un archivo oauth-client-config.json (también conocido como client_secret.json) obtenido desde tu consola de Google Cloud

Instalación

# Clonar el repositorio
git clone https://github.com/eliasmeireles/google-drive-uploader.git
cd google-drive-uploader

# Compilar el binario
go build -o uploader ./cmd/uploader

Obtener las credenciales

Antes de usar el uploader, necesitás dos archivos: client-secret.json (credenciales OAuth) y token.json (token de autorización del usuario).

Paso 1: Crear las credenciales OAuth (client-secret.json)

  1. Entrá a la Google Cloud Console

  2. Creá un nuevo proyecto o seleccioná uno existente

  3. Activá la Google Drive API:

    • Ir a APIs & Services > Library
    • Buscar “Google Drive API”
    • Clic en Enable
  4. Crear credenciales OAuth 2.0:

    • Ir a APIs & Services > Credentials

    • Clic en Create Credentials > OAuth client ID

    • Si te lo pide, configurá primero la pantalla de consentimiento OAuth:

      • Tipo de usuario: External (o Internal si usás Google Workspace)
      • Completá los campos requeridos (nombre de app, email de soporte, etc.)
      • Agregá tu correo en Test users si elegiste External
    • Tipo de aplicación: Desktop app

    • Asignale un nombre (por ejemplo, “Google Drive Uploader”)

    • Clic en Create

  5. Descargar las credenciales:

    • Clic en el ícono de descarga (⬇️)
    • Guardar el archivo como client-secret.json

Ejemplo de client-secret.json:

{
  "installed": {
    "client_id": "TU_CLIENT_ID.apps.googleusercontent.com",
    "project_id": "tu-proyecto",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_secret": "TU_CLIENT_SECRET",
    "redirect_uris": [
      "http://localhost"
    ]
  }
}

Paso 2: Generar el token OAuth (token.json)

Usá la opción --token-gen para generar el token de manera independiente. El programa abrirá automáticamente tu navegador y gestionará la autorización.

./uploader --token-gen --client-secret ./client-secret.json

Después de autorizar la aplicación, se guardará token.json en el directorio actual. Este archivo contiene el token de acceso, de actualización y tus credenciales, por lo que **solo necesitás token.json ** para futuras subidas.

{
  "access_token": "ya29.a0AfH6SMB...",
  "token_type": "Bearer",
  "refresh_token": "1//0gZ9X...",
  "expiry": "2025-12-24T10:30:00.000Z",
  "client_id": "TU_CLIENT_ID...",
  "client_secret": "TU_CLIENT_SECRET..."
}

[!IMPORTANTE] Guardá client-secret.json y token.json en un lugar seguro. Nunca los subas a Git ni a ningún repositorio público.

[!TIP] En entornos automatizados (Docker, Kubernetes), generá el token.json localmente y montalo como secreto o volumen.

Uso

Primera ejecución (autenticación)

En el primer uso, la herramienta te pedirá abrir una URL para autorizar la app. Después de hacerlo, guardará automáticamente token.json.

Subida básica

./uploader --root-folder-id "TU_FOLDER_ID" path/to/archivo.zip

Con cliente explícito

Si tu token.json incluye credenciales, no necesitás --client-secret. De todas formas, podés especificarlo:

./uploader \
  --client-secret ./client-secret.json \
  --root-folder-id "TU_FOLDER_ID" \
  path/to/archivo.zip

Subida masiva (directorio completo)

./uploader \
  --workdir "./backups" \
  --root-folder-id "ROOT_ID" \
  --delete-on-success

Automatización y rutas por defecto

La herramienta busca archivos de configuración en rutas predefinidas:

  • Token: /etc/google-drive-uploader/token.json
  • Credenciales: /etc/google-drive-uploader/client-secret.json (solo necesario si necesitás regenerar el token)

[!NOTA] En entornos automatizados solo necesitás el archivo token.json.

Ejemplo: CronJob en Kubernetes

Podés usar esta herramienta en un CronJob de Kubernetes para automatizar backups.

apiVersion: v1
kind: Secret
metadata:
  name: google-drive-uploader-config
stringData:
  token.json: |
    {
      "access_token": "<ACCESS_TOKEN>",
      "token_type": "Bearer",
      "refresh_token": "<REFRESH_TOKEN>",
      "expiry": "<EXPIRY_DATE>",
      "client_id": "<CLIENT_ID>",
      "client_secret": "<CLIENT_SECRET>"
    }
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: google-drive-backup
spec:
  schedule: "0 4 * * *" # Todos los días a las 4 AM
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: uploader
              image: ghcr.io/eliasmeireles/cli/google-drive-uploader:latest
              args:
                - --workdir
                - /backups
                - --root-folder-id
                - "TU_FOLDER_ID"
                - --folder-name
                - "MI_CARPETA"
                - --smart-organize
                - --delete-on-success
              volumeMounts:
                - name: config
                  mountPath: /etc/google-drive-uploader
                  readOnly: true
          volumes:
            - name: config
              secret:
                secretName: google-drive-uploader-config

[!NOTA] Solo necesitás el secreto google-drive-uploader-config con el token.json.

Uso con Docker

También podés correr el uploader directamente con Docker.

docker run --rm \
  -v /path/token.json:/etc/google-drive-uploader/token.json:ro \
  -v /path/data:/data \
  ghcr.io/eliasmeireles/cli/google-drive-uploader:latest \
  --workdir /data \
  --root-folder-id "TU_FOLDER_ID" \
  --smart-organize \
  --delete-on-success
  • Monta tu configuración como solo lectura (:ro)
  • Monta los datos locales en /data
  • Procesa automáticamente todos los archivos en esa carpeta

Organización inteligente

La opción --smart-organize crea carpetas automáticamente según el nombre del archivo. Ejemplo: mi_servicio_backup_20251224_084205.tar.gzMI_SERVICIO/2025-12-24/mi_servicio_backup_20251224_084205.tar.gz

./uploader \
  --workdir "./backups" \
  --root-folder-id "ROOT_ID" \
  --smart-organize \
  --delete-on-success

Modo limpieza

El modo --cleanup elimina carpetas antiguas según una política de retención, ideal para mantener ordenados tus backups.

Ejemplo:

# Mantener solo la copia más reciente
./uploader --cleanup --keep 1 --match yyyy-MM-dd --root-folder-id "ROOT_ID"

# Mantener las 3 más recientes
./uploader --cleanup --keep 3 --match yyyyMMdd --root-folder-id "ROOT_ID"

Estructura típica:

Carpeta Raíz
├── Servicio A
│   ├── 2025-01-10  ← eliminado
│   ├── 2025-01-15  ← eliminado
│   └── 2025-01-20  ← conservado
└── Servicio B
    ├── 2025-01-12  ← eliminado
    └── 2025-01-18  ← conservado

[!ADVERTENCIA] El modo limpieza mueve carpetas a la papelera de Drive. Podés recuperarlas, pero usalo con precaución.

Flags disponibles

FlagDescripciónValor por defecto
--root-folder-idID de la carpeta raíz en Google Drive.Requerido
--client-secretRuta al client-secret.json (solo para generar un nuevo token)./etc/google-drive-uploader/client-secret.json
--token-pathRuta del archivo de token OAuth 2.0.token.json o /etc/google-drive-uploader/token.json
--workdirDirectorio local a subir.-
--smart-organizeOrganización automática (Servicio/Fecha/Archivo).false
--delete-on-successBorra el archivo local luego de una subida exitosa.false
--delete-on-doneBorra el archivo local incluso si falla la subida.false
--folder-nameNombre de subcarpeta a usar o crear.-
--file-nameNombre del archivo en Drive.Nombre local
--cleanupActiva modo limpieza (elimina backups viejos).false
--keepCantidad de carpetas con fechas recientes a conservar.1
--matchPatrón de fecha a detectar (yyyy-MM-dd, yyyyMMdd, etc.).yyyy-MM-dd