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).
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.
| 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 | 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/ |
/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/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.targetUmbrel'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.
| 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 |
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 \
configSince 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.
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 1mkdir -p /home/umbrel/rclone-putio
nano /home/umbrel/rclone-putio/docker-compose.yml
# Paste the compose YAML from abovedocker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
docker logs -f rclone-putio-syncsudo 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.servicesudo reboot
# Wait ~1 minute after SSH becomes available again
docker ps | grep rclone- Check systemd service status:
sudo systemctl status rclone-putio.service - Check systemd logs:
sudo journalctl -u rclone-putio.service --no-pager - If the service ran but the container was cleaned up, increase the sleep delay in
ExecStartPre(e.g., from 30 to 60 seconds) - Manually start:
docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
- Check container logs:
docker logs rclone-putio-sync - Verify config:
ls -la /home/umbrel/umbrel/home/Documents/.config/rclone/rclone.conf - 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
- 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
- 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 copyis 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.
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 8Then restart: docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d
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
Edit the TZ=UTC environment variable to your timezone (e.g., TZ=America/New_York).
docker compose -f /home/umbrel/rclone-putio/docker-compose.yml pull
docker compose -f /home/umbrel/rclone-putio/docker-compose.yml up -d