Skip to content

Restic + rclone: backing up to any cloud through the rclone backend

Using rclone as a generic transport for restic so the same backup engine works against B2, Dropbox, OneDrive, pCloud, SFTP, and dozens of other backends — and where this pattern hurts.

Restic ships with native support for S3, Azure Blob, GCS, B2, REST, and SFTP, but the most flexible backend it has is the rclone bridge: restic shells out to rclone, and rclone supports 70+ cloud services. The pattern is operator-friendly — you write one rclone remote config, point restic at rclone:<remote>:<path>, and any service rclone speaks becomes a restic target. This article covers the setup, the credential plumbing, the pitfalls of using non-S3 backends for backup, and where we choose this pattern over a direct S3 endpoint.

How to verify

A working restic + rclone wire-up looks like this:

restic version
rclone version
rclone listremotes
rclone lsd <remote>:
restic -r rclone:<remote>:<path> snapshots
restic -r rclone:<remote>:<path> check --read-data-subset=5%

check --read-data-subset actually re-downloads a sample of packs and verifies their integrity end-to-end. This is the closest thing to a non-destructive restore drill.

What’s happening

Restic talks to its backends through a pluggable interface; the rclone backend launches rclone serve restic as a subprocess and pipes the restic protocol over stdin/stdout. From restic’s perspective the backend is just files in directories; rclone translates that into whatever the remote service speaks (HTTP, WebDAV, IMAP, native APIs).

The on-the-wire format is the same as restic’s other backends: encrypted packs (immutable chunks containing several deduplicated blobs), index files that map blob hashes to packs, and snapshot manifests. The rclone layer adds nothing to the format; it is purely transport.

This matters because most “consumer cloud” services (Dropbox, OneDrive, Google Drive, pCloud) were built for files-as-files. Restic’s many-small-files access pattern can run into rate limits, sluggish list operations, or charge surprises. We pick rclone-backed backends for redundancy/offsite, not for the primary repo.

The procedure

  1. Install both tools. Both are static Go binaries; the upstream packages on Ubuntu work.

    apt install -y restic rclone
    restic version
    rclone version
  2. Configure the rclone remote interactively, then test it. Backblaze B2 is the example here because it’s the cheapest backend rclone supports natively.

    rclone config
    # → n (new remote) → name: acme-b2 → type: b2 → enter account id + app key
    rclone lsd acme-b2:
    rclone mkdir acme-b2:acme-restic-prod

    The config lands in ~/.config/rclone/rclone.conf. Treat it as a credential file — mode 0600, in a vault, not in the repo.

  3. Initialize the restic repository through the rclone bridge.

    export RESTIC_PASSWORD_FILE=/etc/restic/passphrase
    restic -r rclone:acme-b2:acme-restic-prod init
    restic -r rclone:acme-b2:acme-restic-prod snapshots

    RESTIC_PASSWORD_FILE is what restic uses to decrypt the repo. Store the passphrase outside the backup; lose it, lose the data.

  4. Take a backup. Restic does the dedupe locally before any byte hits rclone.

    restic -r rclone:acme-b2:acme-restic-prod backup \
      --exclude-caches \
      --tag prod --tag $(hostname) \
      /etc /var/www /home /var/lib/postgresql
  5. Schedule the rotation via systemd timer. systemd lets you set the env file, the dependencies, and the OnFailure= notification cleanly.

    # /etc/systemd/system/restic-backup.service
    [Service]
    Type=oneshot
    EnvironmentFile=/etc/restic/env
    ExecStart=/usr/bin/restic -r rclone:acme-b2:acme-restic-prod backup --tag prod /etc /var/www
    ExecStartPost=/usr/bin/restic -r rclone:acme-b2:acme-restic-prod forget \
      --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
  6. Verify a restore monthly into a scratch directory.

    restic -r rclone:acme-b2:acme-restic-prod restore latest \
      --target /tmp/restic-drill --include /etc/hostname
    diff /tmp/restic-drill/etc/hostname /etc/hostname

Operational notes

  • The rclone backend adds one process and one IPC layer. For multi-TB backups, expect 10-30% wall-clock overhead vs the native S3 backend. Latency stacks up; bandwidth is similar.
  • Rate limits on consumer storage are the biggest gotcha. OneDrive, Google Drive, and Dropbox throttle aggressively; a multi-thousand-file forget+prune run can fail mid-way. Use --limit-upload and --limit-download to stay under the per-app rate limits.
  • The rclone config file holds the credentials. If you back up /etc and the rclone config is in /root/.config, your backup contains the credentials needed to decrypt itself. Encrypt the rclone config with rclone config password or move the config out of the backup set.
  • restic prune rewrites packs. Backends with object-versioning or WORM behavior interfere with prune; B2 has a 24-hour lifecycle by default that lets prune complete cleanly but other backends need explicit unprotect calls.
  • For small datasets (1-50 GB), the rclone pattern is fine — backup time is dominated by upload, not by per-file ops. Beyond that, dedicated S3-compatible storage outperforms.
  • rclone serve restic runs in-process; killing the restic command leaves no orphan. Wrapping it with systemd-run is fine.

In the engagements we run, the rclone bridge appears when a client has an existing storage relationship we have to honor (an enterprise Dropbox, a Box for Business contract) or when we want a deliberately different second tier from the primary S3 repo. Primary repo on direct S3, second copy via rclone to B2 or to a different vendor entirely — two structurally different copies, two adversaries. The full multi-tier story we wrap is at /en/services/managed-operations/.