Cheap object storage is only a backup if the provider can never read what you put there, and only useful if you have actually restored from it once. rclone gives you both: client-side encryption before anything leaves the host, and a restore you can rehearse on a bare machine.
The pattern I reach for when a firm needs a genuinely offsite copy — separate provider, separate credentials, separate blast radius — is rclone pushing to an S3-compatible store like Backblaze B2 or Wasabi, wrapped in rclone’s crypt remote. The crypt layer encrypts file contents and filenames on your host, so the bucket holds nothing but ciphertext and opaque names. The provider is storage, not a party you have to trust with plaintext. This is the config, the sync, the rolling history, and the restore, using rclone 1.67.
Two remotes: the store, then the crypt wrapper
rclone’s crypt works by wrapping another remote. You define the underlying object-store remote first — B2 or Wasabi — then define a crypt remote whose remote points at a path inside it. You never sync to the store directly; you sync to the crypt remote, and rclone encrypts on the way through.
For Backblaze B2, create an application key scoped to a single bucket rather than a master key. The same discipline I apply to any long-lived credential applies here — scoped, rotatable keys, never the account-wide one. You can build both remotes non-interactively:
# 1. The underlying B2 remote (bucket-scoped application key)
rclone config create b2 b2 \
account 000xxxxxxxxxxxx0000000001 \
key K000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
hard_delete true
# For Wasabi instead, use the s3 backend with provider Wasabi:
# rclone config create wasabi s3 provider Wasabi \
# access_key_id AKIA... secret_access_key ... \
# endpoint s3.eu-central-2.wasabisys.com
# 2. The crypt wrapper over a path inside the bucket.
# Passwords must be obscured, NOT plaintext, in the config.
rclone config create b2crypt crypt \
remote b2:my-backup-bucket \
password "$(rclone obscure 'a-long-encryption-passphrase')" \
password2 "$(rclone obscure 'a-second-salt-passphrase')" \
filename_encryption standard \
directory_name_encryption true
A note on the passwords. rclone “obscures” them in the config file with a static AES key — that stops a shoulder-glance, nothing more. It is not encryption of your secrets. Either encrypt the whole config with rclone config encrypt, or keep the two passphrases in your secrets manager and inject them at runtime. And write them down somewhere durable and offline, because there is no recovery: lose password and password2 and the ciphertext in that bucket is gone for good. That property is the point of client-side encryption, and it is also the sharpest edge.
The resulting ~/.config/rclone/rclone.conf looks like this:
[b2]
type = b2
account = 000xxxxxxxxxxxx0000000001
key = K000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
hard_delete = true
[b2crypt]
type = crypt
remote = b2:my-backup-bucket
password = *** ENCRYPTED ***
password2 = *** ENCRYPTED ***
filename_encryption = standard
directory_name_encryption = true
The sync, with a rolling history
rclone sync makes the destination match the source — which means it deletes remotely anything you have deleted locally. On its own that is a mirror, not a backup: a bad delete or a ransomware event on the host propagates straight to your offsite copy. The fix is --backup-dir. Instead of destroying overwritten and deleted files, rclone moves them, in their original hierarchy, into a separate path. You keep a mirror of “now” plus a dated archive of everything that changed.
Point the destination and the backup directory at two non-overlapping paths on the same crypt remote:
rclone sync /srv/data b2crypt:current \
--backup-dir "b2crypt:archive/$(date +%Y-%m-%d)" \
--transfers 8 \
--bwlimit "08:00,10M 18:00,off" \
--checksum \
--fast-list \
--log-file /var/log/rclone-backup.log \
--log-level INFO
What each flag is earning its place for:
- –backup-dir sends every overwritten or deleted file into
archive/YYYY-MM-DD/, giving you point-in-time recovery. Prune old dated folders on whatever retention you can defend. - –transfers 8 raises parallel uploads from the default of 4. Object stores like many small parallel PUTs; tune to your uplink.
- –bwlimit “08:00,10M 18:00,off” caps upload to 10 MiB/s during the working day and lifts the limit overnight. Backups should not starve the office link.
- –checksum compares hash and size rather than modification time, so a restored or clock-skewed host does not trigger a needless re-upload of everything.
- –fast-list fetches the remote listing in fewer, larger calls — fewer class-C transactions on B2, faster runs on large trees.
Run it once with --dry-run first. rclone will print exactly what it would upload, move and delete, and you want to read that list before the first real sync, not after.
Scheduling it so it actually runs
A backup that depends on someone remembering to run it is not a backup. On Linux, a systemd timer is more robust than cron — it logs to the journal, survives missed runs with Persistent=true, and will not overlap itself:
# /etc/systemd/system/rclone-backup.service
[Unit]
Description=Encrypted offsite backup via rclone
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
# systemd cannot expand $(date), so call a one-line wrapper that does:
# exec rclone sync /srv/data b2crypt:current \
# --backup-dir "b2crypt:archive/$(date +%%Y-%%m-%%d)" \
# --transfers 8 --bwlimit "08:00,10M 18:00,off" --checksum --fast-list
ExecStart=/usr/local/bin/rclone-backup.sh
# /etc/systemd/system/rclone-backup.timer
[Unit]
Description=Run rclone backup nightly
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
Enable with systemctl enable --now rclone-backup.timer. On Windows use Task Scheduler; on macOS a launchd plist — rclone itself is identical across all three. Whatever schedules it, alert on a non-zero exit code. A silent backup failure is the most expensive kind.
The restore is the only test that counts
Restoring on a fresh machine needs exactly two things: rclone, and the crypt config with both passphrases. Recreate the config (or drop in the encrypted rclone.conf), then pull the data back — rclone decrypts transparently:
# Verify you can read the encrypted store
rclone lsd b2crypt:current
# Restore the current mirror to a clean host
rclone copy b2crypt:current /srv/restore --progress --transfers 8
# Or recover a file as it was on a given day
rclone copy "b2crypt:archive/2026-09-14/reports/q3.xlsx" /srv/restore/
Rehearse this on a machine that has never seen the source, and time it. The number you get is your real recovery time, and it belongs in the same conversation as the MTTR you already measure for deployments — recovering data is just another mean time to restore. An offsite copy you have never decrypted is a hypothesis. Restore from it once, on hardware that knows nothing, and it becomes a backup.
Free interactive tool
Website compliance checklist
What your site has to do, based on what it actually does
Answer as much or as little as you like — the list builds as you go. Nothing is stored against your name and no email is required.
Everything that applies
Ordered by what to do first: legal requirements you can close quickly, then larger pieces of work, then what is expected rather than required. Not exhaustive, and not a legal audit.
Dated PDF, yours to keep or circulate.
Can you trust the architecture you have?
Architecture diagrams rarely show the reality of how systems actually operate. An independent review establishes what is really there.