Mi nube

mar 12, 2026 16:453.3K visitas

He abandonado mi cuenta de Exchange, sincronizada con Thunderbird a través de Aluco, porque Aluco no gestiona el spam en el lado del usuario. Así que, he vuelto a mi cuenta IMAP + CalDAV + CardDAV + WebDAV -ahora sí- con ActiveSync, para la sincronización entre dispositivos. Para mí, esto supone recuperar el control sobre la gestión del spam, disponer de un espacio extra para el almacenamiento cloud y disfrutar de una reducción en el precio de la factura del groupware.

Sin embargo, me he dado cuenta de que mi proveedor no facilita un espacio de almacenamiento accesible por davs, sino por https, lo que significa que no puedo acceder a ese espacio fuera del navegador. Y por eso, me he puesto manos a la obra y he recuperado mi viejo proyecto de una nube propia, completamente integrada con el sistema operativo.

Antes de continuar, quiero explicar las mejoras que he introducido. En primer lugar, la sincronización se resuelve con sync --delete-during, lo que significa que cuando se actualiza un fichero local, se borra la versión anterior en el contenedor. O si en el contenedor está activado el versioning, se coloca una marca de borrado. En este último caso, el archivo deja de ocupar espacio en la lista de objetos actuales, pero se guarda en el historial de versiones, por si necesitamos recuperarlo después. Y para finalizar, la sincronización con el contenedor es directa, desde la carpeta Documentos. Empezamos definiendo los tipos de ficheros que no queremos guardar con sudo nano ~/.config/rclone/rclone-excludes.txt:

# Carpetas inútiles
- **/.git/**
- **/node_modules/**
- **/.cache/**
- **/.npm/**
- **/target/**
- **/dist/**
- **/build/**

# Archivos temporales
- **/*.tmp
- **/*.swp
- **/*~
- **/.DS_Store
- **/Thumbs.db
- **/._*

# IDEs
- **/.idea/**
- **/.vscode/**

Instalamos rclone con sudo dnf install rclone y nos aseguramos de configurarlo, bien con rclone config, bien almacenando el fichero de configuración en la carpeta ~/.config/rclone. Para probar la conexión, ejecutamos rclone ls storage:usuario-storage. Después creamos el servicio: con sudo nano ~/.config/systemd/user/cloud.service:

[Unit]
Description=Sincronización Mirror a S3
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/rclone sync "/home/usuario/Documentos" storage:usuario-storage \
    --delete-during \
    --checksum \
    --fast-list \
    --transfers 4 \
    --bwlimit 1M \
    --filter-from /home/usuario/.config/rclone/rclone-excludes.txt \
    --log-level INFO

StandardOutput=journal
StandardError=journal

Podemos consultar los logs emitidos con journalctl --user -u cloud.service -f. Creamos el timer que activa la sincronización cada cinco minutos con sudo nano ~/.config/systemd/user/cloud.timer:

[Unit]
Description=Run sync every 5 minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Unit=cloud.service
Persistent=true

[Install]
WantedBy=timers.target

Reiniciamos los demonios y activamos el timer:

systemctl --user daemon-reload
systemctl --user enable --now cloud.timer
systemctl --user restart cloud.timer

Para comprobar que todo está en orden y que no hay sorpresas, podemos introducir los comandos systemctl --user list-timers y systemctl --user status cloud.service que listarán los timers de usuario activos y el estado de la sincronización, respectivamente.

Ahora ya tenemos nuestra propia nube, hecha de software libre, infraestructura de primer nivel e integración absoluta con el sistema operativo, lista para ser usada. Pero ¿qué pasa si se apaga la máquina mientras el sistema está sincronizando? Si la máquina se apaga mientras rclone sync está en curso:

Los archivos parcialmente subidos podrán quedar incompletos, pero rclone los detectará y reintentará la sincronización en otro momento. Y para finalizar -en caso de accidente- si queremos restaurar los archivos en la carpeta local, basta con:

rclone sync storage:usuario-storage /home/usuario/carpeta-restaurada-en-local \
  --progress \
  --fast-list \
  --transfers 4 \
  --checkers 8 \
  --bwlimit 1M \
  --filter-from /home/usuario/.config/rclone/rclone-excludes.txt

Actualización: Si queremos una capa extra de seguridad, podemos activar el versioning, lo que nos permitirá guardar versiones diferentes de los ficheros, que incluyan los cambios que vamos introduciendo. También podemos controlar el ciclo de vida de nuestro contenedor, limpiando el disco de archivos incompletos y borrando automáticamente versiones de cierta antigüedad. Para ello, creamos el archivo lifecycle.json en ~/.config/rclone:

{
  "Rules": [
    {
      "ID": "regla-1",
      "Status": "Enabled",
      "Filter": { },
      "Expiration": {
        "Days": 20
      },
      "NoncurrentVersionExpiration": {
        "NoncurrentDays": 10
      }
    },
    {
      "ID": "regla-2",
      "Status": "Enabled",
      "Filter": { },
      "Expiration": {
        "ExpiredObjectDeleteMarker": true
      }
    },
    {
      "ID": "regla-3",
      "Status": "Enabled",
      "Filter": { },
      "AbortIncompleteMultipartUpload": {
        "DaysAfterInitiation": 10
      }
    }
  ]
}

Instalamos el CLI de AWS con sudo dnf install awscli y lo configuramos con aws configure, introduciendo el access key, el secret key, la region por defecto y el output por defecto. Después aplicamos el lifecycle rule:

aws --endpoint-url url-del-endpoint \
    s3api put-bucket-lifecycle-configuration \
    --bucket usuario-storage \
    --lifecycle-configuration file:///home/usuario/.config/rclone/lifecycle.json

Y verificamos que se ha aplicado:

aws --endpoint-url url-del-endpoint \
    s3api get-bucket-lifecycle-configuration \
    --bucket usuario-storage

Para finalizar, si queremos recuperar todas las versiones con 10 días de antigüedad, empezamos listando y guardando una lista de todas las versiones disponibles:

aws --endpoint-url url-del-endpoint \
  s3api list-object-versions --bucket usuario-storage \
  > ~/.config/rclone/versions.json

Y después mostramos qué se copiará al directorio local:

TARGET_DATE=$(date -u -d "10 days ago" +%s)

jq -r --argjson target "$TARGET_DATE" '
  .Versions[]
  | select((.LastModified | sub("\\+00:00$";"Z") | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime) <= $target)
  | "\(.Key) \(.VersionId)"' ~/.config/rclone/versions.json

Lo que dará un listado del tipo:

recetas/boquerones-en-vinagre.md 1769932289.488867
recetas/costillas-al-horno.md 1769932289.491374
recetas/pure-de-calabacin.md 1769932291.014892

Ahora sí, para terminar, copiamos al directorio local los ficheros que queremos recuperar, es decir los que tienen más de 10 días de antigüedad:

TARGET_DATE=$(date -u -d "10 days ago" +%s)

jq -r --argjson target "$TARGET_DATE" '
  .Versions[]
  | select((.LastModified
            | sub("\\+00:00$"; "Z")
            | strptime("%Y-%m-%dT%H:%M:%SZ")
            | mktime) <= $target)
  | "\(.Key) \(.VersionId)"' ~/.config/rclone/versions.json |
while read key version; do
  DEST="/home/usuario/restauracion-10-dias-antiguedad/$key"
  mkdir -p "$(dirname "$DEST")"
  echo "Descargando $key (versión $version)"
  aws --endpoint-url url-del-endpoint \
    s3api get-object \
    --bucket usuario-storage \
    --key "$key" \
    --version-id "$version" \
    "$DEST"
done

Antes de continuar...

Detrás de cada artículo de Bitácora hay tiempo, investigación y desarrollo contínuo. Si quiere ayudar a mantener este proyecto libre e independiente, apóyeme:

Apóyeme