Skip to content

Instantly share code, notes, and snippets.

@fabe
Created February 12, 2026 13:54
Show Gist options
  • Select an option

  • Save fabe/1c0600dbd28580fc464908de117a81c8 to your computer and use it in GitHub Desktop.

Select an option

Save fabe/1c0600dbd28580fc464908de117a81c8 to your computer and use it in GitHub Desktop.
rclone Put.io Sync on Umbrel Home

rclone Put.io Sync on Umbrel Home

Overview

Automatically syncs files from Put.io to Umbrel Home every 5 minutes using rclone running in a Docker container, deployed directly on the host (not through Portainer).

Why Not Portainer?

Portainer on Umbrel runs with a Docker-in-Docker (DinD) setup (docker:27.2.0-dind). This means containers created via Portainer's UI run inside Portainer's own Docker daemon, not on the host. Volume bind mounts reference the filesystem inside the DinD container, not the real Umbrel filesystem. Files written inside Portainer-managed containers never appear on the host.

The solution is to deploy the rclone container directly on the Umbrel host via SSH, bypassing Portainer entirely.


Sync Paths

Put.io Path Umbrel Host Path
/Shows /home/umbrel/umbrel/home/Downloads/putio/Shows
/Movies /home/umbrel/umbrel/home/Downloads/putio/Movies

The Downloads folder is accessible through the Umbrel Files app.


File Locations

File Path
Docker Compose file /home/umbrel/rclone-putio/docker-compose.yml
rclone config /home/umbrel/umbrel/home/Documents/.config/rclone/rclone.conf
Systemd service /etc/systemd/system/rclone-putio.service
Downloaded files /home/umbrel/umbrel/home/Downloads/putio/

Docker Compose File

/home/umbrel/rclone-putio/docker-compose.yml:

services:
  rclone-putio:
    image: rclone/rclone:latest
    container_name: rclone-putio-sync
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    entrypoint: /bin/sh
    command:
      - -c
      - |
        echo "Starting rclone copy loop..."
        while true; do
          echo "[$(date)] Starting rclone copy: Shows"
          rclone copy putio:/Shows /downloads/putio/Shows \
            --config /config/rclone/rclone.conf \
            --verbose \
            --transfers 4 \
            --checkers 8
          echo "[$(date)] Starting rclone copy: Movies"
          rclone copy putio:/Movies /downloads/putio/Movies \
            --config /config/rclone/rclone.conf \
            --verbose \
            --transfers 4 \
            --checkers 8
          echo "[$(date)] Copy complete. Sleeping 5 minutes..."
          sleep 300
        done
    volumes:
      - /home/umbrel/umbrel/home/Documents/.config/rclone:/config/rclone
      - /home/umbrel/umbrel/home/Downloads:/downloads
    environment:
      - TZ=UTC

Systemd Service File

/etc/systemd/system/rclone-putio.service:

[Unit]
Description=rclone Put.io Sync
After=docker.service umbrel.service
Requires=docker.service
Wants=umbrel.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/sleep 30
WorkingDirectory=/home/umbrel/rclone-putio
ExecStart=/usr/bin/docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /home/umbrel/rclone-putio/docker-compose.yml down

[Install]
WantedBy=multi-user.target

Why the 30-second delay?

Umbrel's own boot process (umbrel.service) can prune or restart Docker containers after docker.service is ready. The ExecStartPre=/bin/sleep 30 ensures the rclone container is created after Umbrel has fully settled, preventing it from being cleaned up during Umbrel's startup.


Management Commands (via SSH)

Action Command
Check if running docker ps | grep rclone
View recent logs docker logs rclone-putio-sync
Follow logs live docker logs -f rclone-putio-sync
Last 50 log lines docker logs --tail 50 rclone-putio-sync
Container stats docker stats rclone-putio-sync --no-stream
Restart container docker restart rclone-putio-sync
Stop the stack docker compose -f /home/umbrel/rclone-putio/docker-compose.yml down
Start the stack docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
Check systemd service sudo systemctl status rclone-putio.service
View systemd logs sudo journalctl -u rclone-putio.service --no-pager

Initial Setup Steps

1. Set up rclone config for Put.io

mkdir -p /home/umbrel/umbrel/home/Documents/.config/rclone

docker run --rm -it \
  -v /home/umbrel/umbrel/home/Documents/.config/rclone:/config/rclone \
  rclone/rclone:latest \
  --config /config/rclone/rclone.conf \
  config

Since Umbrel is headless, the easiest method is to run rclone config on a local machine with a browser, authorize Put.io via OAuth, then copy the resulting rclone.conf to the Umbrel.

2. Verify rclone can access Put.io

docker run --rm \
  -v /home/umbrel/umbrel/home/Documents/.config/rclone:/config/rclone \
  rclone/rclone:latest \
  --config /config/rclone/rclone.conf \
  ls putio:/Shows --max-depth 1

3. Create the compose file

mkdir -p /home/umbrel/rclone-putio
nano /home/umbrel/rclone-putio/docker-compose.yml
# Paste the compose YAML from above

4. Start the stack

docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
docker logs -f rclone-putio-sync

5. Create the systemd service

sudo nano /etc/systemd/system/rclone-putio.service
# Paste the systemd unit from above
sudo systemctl daemon-reload
sudo systemctl enable rclone-putio.service
sudo systemctl start rclone-putio.service

6. Verify after reboot

sudo reboot
# Wait ~1 minute after SSH becomes available again
docker ps | grep rclone

Troubleshooting

Container not running after reboot

  1. Check systemd service status: sudo systemctl status rclone-putio.service
  2. Check systemd logs: sudo journalctl -u rclone-putio.service --no-pager
  3. If the service ran but the container was cleaned up, increase the sleep delay in ExecStartPre (e.g., from 30 to 60 seconds)
  4. Manually start: docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d

rclone copy errors

  1. Check container logs: docker logs rclone-putio-sync
  2. Verify config: ls -la /home/umbrel/umbrel/home/Documents/.config/rclone/rclone.conf
  3. Test Put.io access manually:
    docker run --rm \
      -v /home/umbrel/umbrel/home/Documents/.config/rclone:/config/rclone \
      rclone/rclone:latest \
      --config /config/rclone/rclone.conf \
      ls putio:/ --max-depth 1

After Umbrel software update

  • The compose file at /home/umbrel/rclone-putio/ should survive (it's in the home directory)
  • The rclone config should survive (also in the home directory)
  • The systemd service at /etc/systemd/system/ should survive (Umbrel stores its own services there too)
  • Downloaded files should survive (they're in the Downloads directory)
  • If anything breaks, re-run the setup steps above

Storage Notes

  • No duplication: Bind mounts mean files exist only once on disk. 100GB of movies = 100GB on disk, not 200GB.
  • Logging: Docker logs are capped at 30MB (3 x 10MB files) with automatic rotation. No separate log file on disk.
  • Sync behavior: rclone copy is incremental. If nothing changed on Put.io, the check completes in seconds with minimal API usage. Large downloads block the loop — the 5-minute sleep only starts after all copies are complete.

Editing the Config

Add a new Put.io folder to sync

Edit /home/umbrel/rclone-putio/docker-compose.yml and add another rclone copy block inside the command, e.g.:

echo "[$(date)] Starting rclone copy: Music"
rclone copy putio:/Music /downloads/putio/Music \
  --config /config/rclone/rclone.conf \
  --verbose \
  --transfers 4 \
  --checkers 8

Then restart: docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d

Change sync interval

Edit the sleep 300 value in the compose file. Values in seconds:

  • 1 minute: sleep 60
  • 5 minutes: sleep 300
  • 15 minutes: sleep 900
  • 1 hour: sleep 3600

Change timezone

Edit the TZ=UTC environment variable to your timezone (e.g., TZ=America/New_York).

Update rclone to latest version

docker compose -f /home/umbrel/rclone-putio/docker-compose.yml pull
docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment