Skip to main content

Automatización de backups a Google Drive

Realizar Backups

Hay dos tipos de contenido del cual hacer backup: files and database records.

Database Records

Ejecutar como usuario root:

mysqldump -u root bookstack > bookstack.backup.sql
Files

Hay que hacer backup de los siguientes ficheros, todos ubicados en /var/www/bookstack

  • .env - File, contains important configuration information.
  • public/uploads - Folder, contains any uploaded images.
  • storage/uploads - Folder, contains uploaded page attachments.
  • themes - Folder, contains any configured visual/logical themes.

Automatización de Backups

Con la información previa, el objetivo de esta sección es ver como automatizar la creación de ambos backups (database y files).

1. Instalación y configuración de rclone

Rclone is a command-line program to manage files on cloud storage. It is a feature-rich alternative to cloud vendors' web storage interfaces. Over 70 cloud storage products support rclone including S3 object stores, business & consumer file storage services, as well as standard transfer protocols.

Rclone has powerful cloud equivalents to the unix commands rsync, cp, mv, mount, ls, ncdu, tree, rm, and cat. Rclone's familiar syntax includes shell pipeline support, and --dry-run protection. It is used at the command line, in scripts or via its API.

Users call rclone "The Swiss army knife of cloud storage", and "Technology indistinguishable from magic".

Para instalar rclone en la Pi:

sudo -v ; curl https://rclone.org/install.sh | sudo bash

Para la configuración inicial se ejecuta el siguiente comando, que es interactivo, y con el que se hace el setup del remote storage (Google Drive ene ste caso):

rclone config
sergio@bookstack:~ $ rclone config
2026/03/30 18:44:26 NOTICE: Config file "/home/sergio/.config/rclone/rclone.conf" not found - using defaults
No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n

Enter name for new remote.
name> GoogleDrive

Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.
<omitted for brevity>
19 / Files.com
   \ (filescom)
20 / Gofile
   \ (gofile)
21 / Google Cloud Storage (this is not Google Drive)
   \ (google cloud storage)
22 / Google Drive
   \ (drive)
23 / Google Photos
   \ (google photos)
24 / HTTP
   \ (http)
<omitted for brevity>
Storage> 22

Option client_id.
Google Application Client Id
Setting your own is recommended.
See https://rclone.org/drive/#making-your-own-client-id for how to create your own.
If you leave this blank, it will use an internal key which is low performance.
Enter a value. Press Enter to leave empty.
client_id>

Option client_secret.
OAuth Client Secret.
Leave blank normally.
Enter a value. Press Enter to leave empty.
client_secret>

Option scope.
Comma separated list of scopes that rclone should use when requesting access from drive.
Choose a number from below, or type in your own value.
Press Enter to leave empty.
 1 / Full access all files, excluding Application Data Folder.
   \ (drive)
 2 / Read-only access to file metadata and file contents.
   \ (drive.readonly)
   / Access to files created by rclone only.
 3 | These are visible in the drive website.
   | File authorization is revoked when the user deauthorizes the app.
   \ (drive.file)
   / Allows read and write access to the Application Data folder.
 4 | This is not visible in the drive website.
   \ (drive.appfolder)
   / Allows read-only access to file metadata but
 5 | does not allow any access to read or download file content.
   \ (drive.metadata.readonly)
scope> 1

Option service_account_file.
Service Account Credentials JSON file path.
Leave blank normally.
Needed only if you want use SA instead of interactive login.
Leading `~` will be expanded in the file name as will environment variables such as `${RCLONE_CONFIG_DIR}`.
Enter a value. Press Enter to leave empty.
service_account_file>

Edit advanced config?
y) Yes
n) No (default)
y/n>

Use web browser to automatically authenticate rclone with remote?
 * Say Y if the machine running rclone has a web browser you can use
 * Say N if running rclone on a (remote) machine without web browser access
If not sure try Y. If Y failed, try N.

y) Yes (default)
n) No
y/n> n

Option config_token.
For this to work, you will need rclone available on a machine that has
a web browser available.
For more help and alternate methods see: https://rclone.org/remote_setup/
Execute the following on the machine with the web browser (same rclone
version recommended):
        rclone authorize "drive" "<redacted>"
Then paste the result.
Enter a value.
config_token> <redacted>

Configure this as a Shared Drive (Team Drive)?

y) Yes
n) No (default)
y/n> n

Configuration complete.
Options:
- type: drive
- scope: drive
- token: {"access_token":"<redacted>","token_type":"Bearer","refresh_token":"<redacted>","expiry":"2026-03 30T19:49:54.0171046+02:00","expires_in":3599}
- team_drive:
Keep this "GoogleDrive" remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d>

Current remotes:

Name                 Type
====                 ====
GoogleDrive          drive

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> q

Por partes:

  • En el primer paso n para seleccionar New remote.

  • Le pongo de nombre GoogleDrive

  • De la larga lista de proveedores busco el que corresponde a Google Drive (en mi lista, es el número 22)

  • Para obtener los valores client_id y client_secret seguir el anexo.

  • Elijo 1 para Full Access.

  • Dejo service_account_file en blanco.

  • Pongo n para no entrar a Advanced Config.

  • Authentication: En este caso, y como estoy conectado por SSH a la Raspberry (que no tiene escritorio). Sigo las instrucciones que me indica para obtener el token de acceso, que básicamente es instalar rclone en una máquina que sí tenga escritorio y ejecutar el comando que indica (rclone authorize "drive" "<token>") allí. Lo haré un PC Windows:

    image.png


    Con el token de acceso copiado voy de vuelta a la Pi y lo pego, completando este paso.
  • Pongo y para confirmar y q para salir de la configuración.

2. Creación del script de backup

Antes de comenzar con el script de backup voy a crear una carpeta dedicada a estos en Google Drive. Hago uso de rclone para probar el correcto funcionamiento:

image.png

image.png

Comprobado que funciona correctamente, procedo con la creación del script. En primer lugar creo una carpeta dedicada a los backups /home/sergio/bookstack_backups/ donde guardare el script .sh que indico a continuación, con nombre backup_bookstack.sh:

#!/bin/bash
CONF="/home/sergio/.config/rclone/rclone.conf"
DEST="GoogleDrive:BookStack_Backups"

# 1. Stream del fichero SQL directo a GDrive con rcat
mysqldump -u root bookstack | rclone rcat "$DEST/Database/db_$(date +%F).sql" --config "$CONF"

# 2. Sync del resto de ficheros, con "safety net" para archivos borrados que van a la carpeta "Archive"
rclone sync /var/www/bookstack "$DEST/Files" --include "/.env" --include "/themes/**" --include "/public/uploads/**" --include "/storage/uploads/**" --config "$CONF" -v --backup-dir "$DEST/Archive/$(date +%F)"

# 3. Cleanup de los backups de la BBDD con más de 30 días
rclone delete "$DEST/Database" --min-age 30d --config "$CONF"

Doy permisos de ejecución a todos: chmod a+x backup_bookstack.sh

Con este script cumplimos el objetivo de hacer backups periódicos de la BBDD así como mantener una copia síncrona entre la Pi y GDrive, del resto de archivos de los que se debería hacer backups.

3. Añadir tarea en crontab

Únicamente queda programar la tarea periódica de ejecución del script en el crontab del usuario root (necesario por el comando de backup de la BBDD, que debe ser ejecutado por el usuario root).

sudo crontab -e
0 3 * * * /home/sergio/bookstack_backups/backup_bookstack.sh >> /home/sergio/bookstack_backups/backup.log 2>&1

Con esto queda lista la automatización de los backups.

4. Full backup mensual

El hecho de usar rclone rcat y rclone sync es evitar ciclos de escritura en la microSD para prevenir desgaste. Adicional a esto, programo un backup completo mensual que consiste un fichero .tar comprimido que incluye toda la carpeta /var/www/bookstack y la BBDD. Además, hago uso de una pipe para que el comando tar envíe los datos directamente a rclone, evitando crear un fichero pesado en la microSD (evitando ciclos de escritura). El fichero se crea en RAM y es enviado directamente a internet.

sergio@bookstack:~/bookstack_backups $ nano monthly_full_backup.sh

#!/bin/bash
CONF="/home/sergio/.config/rclone/rclone.conf"

# 1. Dump de la BBDD de forma temporal en la carpeta de BookStack
mysqldump -u root bookstack > /var/www/bookstack/db_backup.sql

# 2. Creación de un comprimido TAR de la carpeta ENTERA y posterior stream a Google Drive
tar -czC /var/www/bookstack . | rclone rcat "GoogleDrive:BookStack_Backups/Snapshots/Full_$(date +%Y-%m).tar.gz" --config "$CONF"

# 3. Elminar el fichero temporal de la BBDD de la Pi
rm /var/www/bookstack/db_backup.sql

sergio@bookstack:~/bookstack_backups $ chmod a+x monthly_full_backup.sh
sergio@bookstack:~/bookstack_backups $ sudo crontab -e
0 4 1 * * /home/sergio/bookstack_backups/monthly_full_backup.sh >> /home/sergio/bookstack_backups/monthly.log 2>&1

Anexo I: Obtención de client_id y client_secret para Google Drive

Cuando se usa rclone con Google Drive con la configuración por defecto, se usa el client_id de rclone, que es compartido entre todos los usuarios de rclone. Hay un rate limit global que aplica el numero de queries por segundo que cada client_id puede hacer (establecido por Google). Aunque rclone tiene una cuota alta se recomienda encarecidamente usar un client_id propio ya que el de rclone tiene un uso muy alto. Para crear un client_id de Google Drive propio, he seguido los pasos indicados en la documentación de rclone.