Rclone is a command-line tool that copies and synchronizes files between local disks and more than 70 storage backends, including Amazon S3 and any S3-compatible object storage, SFTP servers and WebDAV. In this tutorial you will configure rclone on Ubuntu 24.04 to back up a directory to an S3 bucket with client-side encryption, control what is uploaded with a filter file, limit bandwidth during working hours, keep previous versions of changed files, run the backup every night with a systemd timer and mount the encrypted bucket to browse and restore files.

Prerequisites

To follow this guide you need:

  • A server running Ubuntu 24.04 LTS, such as a CubePath VPS, and a non-root user with sudo privileges.
  • An S3 or S3-compatible bucket, plus an access key and secret key that can list, read, write and delete objects in it.
  • The data you want to back up. This guide uses /srv/data as the example source.

In the commands below, replace your_bucket, your_access_key, your_secret_key and your_user with your own values.

Step 1 - Installing rclone

The rclone package in the Ubuntu archive lags well behind upstream, which matters because S3 providers and rclone flags change often. Install the current release with the official install script. Download it first so you can read it before running it:

curl -fsSLO https://rclone.org/install.sh
less install.sh
sudo bash install.sh

The script detects your architecture and installs the binary to /usr/bin/rclone and its man page. Check the version:

rclone version
rclone v1.71.0
- os/version: ubuntu 24.04 (64 bit)
- os/kernel: 6.8.0-45-generic (x86_64)
- os/type: linux
- os/arch: amd64
...

To upgrade later, run sudo rclone selfupdate.

Step 2 - Adding the S3 remote

Rclone calls each storage destination a remote and stores them in ~/.config/rclone/rclone.conf. You can create remotes with the interactive rclone config wizard, or non-interactively with rclone config create, which is easier to document and repeat. Run the following as your regular user (not with sudo), because the backup will run as that user:

rclone config create s3-backup s3 \
  provider=AWS \
  access_key_id=your_access_key \
  secret_access_key=your_secret_key \
  region=us-east-1

If you use an S3-compatible provider instead of AWS, set provider=Other and add endpoint=https://your_s3_endpoint with the endpoint URL your provider gives you.

The config file now contains your keys, so make sure only you can read it:

chmod 600 ~/.config/rclone/rclone.conf

Test the remote by listing your buckets and then the target bucket:

rclone lsd s3-backup:
rclone ls s3-backup:your_bucket
          -1 2026-09-20 10:12:41        -1 your_bucket

An empty result for the second command is fine for a new bucket. An AccessDenied or SignatureDoesNotMatch error means the keys, region or endpoint are wrong.

Step 3 - Adding an encrypted crypt remote

A crypt remote wraps another remote and encrypts file contents and names on your server before anything is uploaded, so the storage provider only ever sees encrypted data. Generate two random passphrases, one for the password and one for the salt:

openssl rand -base64 32
openssl rand -base64 32

Store both in your password manager now. If you lose them, the backup cannot be decrypted by anyone, including you.

Create the crypt remote on top of a backup folder in your bucket. The --obscure flag tells rclone to obscure the passphrases before writing them to the config file:

rclone config create secret crypt \
  remote=s3-backup:your_bucket/backup \
  filename_encryption=standard \
  directory_name_encryption=true \
  password='first_passphrase' \
  password2='second_passphrase' \
  --obscure

Upload a test file through the crypt remote and compare the two views of the bucket:

echo "hello" > /tmp/test.txt
rclone copy /tmp/test.txt secret:
rclone ls secret:
rclone ls s3-backup:your_bucket/backup
        6 test.txt
       38 v0tmh3kppa2mbr1b3n3sl2hl3c

Through secret: you see the real name. On the underlying bucket you only see encrypted names and slightly larger objects. Remove the test file:

rclone delete secret:test.txt

Step 4 - Choosing what to back up with a filter file

Filter rules keep caches, build artifacts and other disposable files out of the backup. Rclone reads rules from top to bottom and applies the first one that matches: lines starting with - exclude, + includes. Create a filter file:

mkdir -p ~/.config/rclone
nano ~/.config/rclone/backup-filter.txt
# Exclude disposable data anywhere in the tree
- **/node_modules/**
- **/.cache/**
- **/__pycache__/**
- *.tmp
- *.swp

# Everything else is included
+ **

Preview which files the filter selects without uploading anything:

rclone ls /srv/data --filter-from ~/.config/rclone/backup-filter.txt | head

Only the files you expect should appear. Adjust the rules until the list is right.

Step 5 - Running the first backup

rclone sync makes the destination identical to the source, which means it deletes files from the destination that no longer exist locally. To avoid losing data to an accidental local deletion, add --backup-dir: instead of deleting or overwriting files on the remote, rclone moves the old versions into a dated archive folder on the same remote.

Always start with a dry run to see what would happen:

rclone sync /srv/data secret:current \
  --filter-from ~/.config/rclone/backup-filter.txt \
  --backup-dir secret:archive/$(date +%F) \
  --dry-run
2026/09/25 10:31:02 NOTICE: docs/report.pdf: Skipped copy as --dry-run is set (size 1.204Mi)
2026/09/25 10:31:02 NOTICE: app/config.yml: Skipped copy as --dry-run is set (size 2.110Ki)
...

If the list looks right, run it for real with -P to show live progress:

rclone sync /srv/data secret:current \
  --filter-from ~/.config/rclone/backup-filter.txt \
  --backup-dir secret:archive/$(date +%F) \
  -P

Verify that the remote matches the source. rclone cryptcheck compares checksums through the encryption layer, so it proves the uploaded data is intact:

rclone cryptcheck /srv/data secret:current \
  --filter-from ~/.config/rclone/backup-filter.txt
2026/09/25 10:40:17 NOTICE: Encrypted drive 'secret:current': 0 differences found
2026/09/25 10:40:17 NOTICE: Encrypted drive 'secret:current': 1843 matching files

Step 6 - Tuning bandwidth and parallelism

By default rclone uses 4 parallel transfers and as much bandwidth as it can get. Two flags let you adapt it to your server:

  • --bwlimit caps bandwidth. It accepts a timetable, so you can throttle during working hours and run at full speed at night. The following limits uploads to 10 MiB/s from 08:00, and removes the limit from 20:00:

    --bwlimit "08:00,10M 20:00,off"
    
  • --transfers sets how many files are uploaded in parallel. Many small files benefit from more transfers (8 to 16), while a few large files do not need more than the default.

Test the effect on a single run:

rclone sync /srv/data secret:current \
  --filter-from ~/.config/rclone/backup-filter.txt \
  --backup-dir secret:archive/$(date +%F) \
  --bwlimit "08:00,10M 20:00,off" \
  --transfers 8 \
  -P

The Transferred: line in the progress output shows the current rate, which should stay under the limit during the throttled window.

Step 7 - Scheduling the backup with a systemd timer

A systemd service plus timer is more reliable than cron: runs are logged to the journal, a missed run (for example while the server was off) is caught up, and you can start a run on demand.

Create the service. It runs as your user so it uses your rclone config. In unit files %% and $$ stand for a literal % and $, which systemd would otherwise expand itself:

sudo nano /etc/systemd/system/rclone-backup.service
[Unit]
Description=Encrypted rclone backup of /srv/data
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
User=your_user
ExecStart=/bin/sh -c 'exec /usr/bin/rclone sync /srv/data secret:current \
  --filter-from /home/your_user/.config/rclone/backup-filter.txt \
  --backup-dir "secret:archive/$$(date +%%F)" \
  --bwlimit "08:00,10M 20:00,off" \
  --transfers 8 \
  --log-level INFO'
Nice=10
IOSchedulingClass=idle

Create the timer, which starts the service every night at 02:30 with a random delay of up to 15 minutes:

sudo nano /etc/systemd/system/rclone-backup.timer
[Unit]
Description=Nightly rclone backup

[Timer]
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Load the units, enable the timer and trigger one run immediately to test the service:

sudo systemctl daemon-reload
sudo systemctl enable --now rclone-backup.timer
sudo systemctl start rclone-backup.service

Check the result and the next scheduled run:

systemctl status rclone-backup.service --no-pager
systemctl list-timers rclone-backup.timer
NEXT                        LEFT     LAST PASSED UNIT                ACTIVATES
Fri 2026-09-26 02:38:11 UTC 15h left -    -      rclone-backup.timer rclone-backup.service

The full log of each run is in the journal:

journalctl -u rclone-backup.service -n 30 --no-pager

Step 8 - Mounting the backup to browse and restore

rclone mount exposes a remote as a local filesystem through FUSE, which is convenient for finding and restoring a few files. Install FUSE 3 and create a mount point:

sudo apt install fuse3
sudo mkdir -p /mnt/backup
sudo chown your_user: /mnt/backup

Mount the crypt remote read-only in the background:

rclone mount secret: /mnt/backup --read-only --daemon

Browse the current copy and the archived versions like any directory:

ls /mnt/backup
ls /mnt/backup/archive
archive  current
2026-09-25  2026-09-26

Copy what you need back with cp, or for larger restores use rclone directly, which is faster than going through the mount:

rclone copy secret:current/docs /srv/restore/docs -P

Unmount when you are done:

fusermount3 -u /mnt/backup

Troubleshooting

Failed to create file system ... directory not found on the first run. The bucket does not exist. Create it with rclone mkdir s3-backup:your_bucket or in your provider's console.

The systemd run fails with didn't find section in config file. The service is not running as the user that owns the config. Check User= in the unit, or point rclone at the file explicitly with --config /home/your_user/.config/rclone/rclone.conf.

rclone mount fails with fusermount3: exec: not found. The fuse3 package is missing. Install it as shown in Step 8.

Files show up as ERROR : ... not decrypted. The crypt passphrases in the config do not match the ones used to upload. Restore the original passphrases; data written with other keys cannot be read.

Conclusion

Your server now uploads an encrypted, filtered copy of /srv/data to S3 every night, keeps dated versions of changed and deleted files, and lets you browse the backup as a local directory. As next steps, add a lifecycle rule on the bucket to expire old objects under backup/archive after the retention period you need, add a second destination such as an SFTP remote for a copy at another provider, and schedule a monthly rclone cryptcheck to confirm the backup is still restorable.