Login

Configuring a Remote Backup Solution Using restic and Rclone

by Eric Bette

Configuring a Remote Backup Solution Using restic and Rclone

Share this post

Configuring a Remote Backup Solution Using restic and Rclone

Configuring a Remote Backup Solution Using restic and Rclone

One of the biggest downsides (by far) with self-hosting content on a server is redundancy, or having multiple copies of your data located on multiple machines (preferably in separate physical locations).

The guide will show you how to configure restic and Rclone with an external data store to create backups of the data on your self-hosted server in a remote location.

The stack

As mentioned above, we'll be using the following 2 software to set up our backup infrastructure:

Initial setup

First things first, we need to set up Cronicle on our host, and install and set up the software we'll use for connecting the remote repository (Rclone) and managing the backups (restic).

Step 1: Connect Rclone to your storage location

Step 1.1: Install Rclone on the server (the machine which will be backed up)

For a local, native installation:

eric@ubuntu-server:~$ sudo -v ; curl https://rclone.org/install.sh | sudo bash

For a Docker-based job run, no installation is necessary (the container will be downloaded as part of the execution command).

However, you'll need to prepare a few local directories to store the Rclone and restic config and a few other files:

eric@ubuntu-server:~$ mkdir /etc/docker/restic/cache
eric@ubuntu-server:~$ mkdir /etc/docker/rclone/config

Step 1.2: Configure your remote

For a local, native installation:

eric@ubuntu-server:~$ rclone config

For a Docker-based job run:

eric@ubuntu-server:~$ docker run \
--rm --network host \
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \ 
--entrypoint rclone \
tofran/restic-rclone:latest config

Thanks to the super handy restic-rclone container made by tofran, we can use both restic and Rclone through one container

Regardless of your installation choice, you'll be prompted to go through a workflow to connect your remote data store. Enter n to create a new remote, name it, and then follow the guide to make the connection.

The great thing about using Rclone with restic is that it doesn't matter which endpoint you use (B2, OneDrive, NextCloud, etc). They should all integrate similarly well with restic for your backups.

eric@ubuntu-server:~$ rclone config

No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> q

e/n/d/r/c/s/q> n

Enter name for new remote.
name> example-remote

Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.

 1 / ...

For in-depth documentation on each storage option available in rclone, check the official documentation.

Step 1.3: Confirm your remote

Assuming everything went smoothly, you should be able to confirm your remote got set up correctly by listing out your remotes using rclone:

eric@ubuntu-server:~$ rclone listremotes

or for Docker:

eric@ubuntu-server:~$ docker run \
--rm --network host \
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \ 
--entrypoint rclone \
tofran/restic-rclone:latest listremotes

Once that's been confirmed, we can move on to setting up the backup repository. Output:

example-remote:

Step 2: Setting up a backup repository with restic

The next step is to initialize a repository using restic. To do this, we'll first need to set up a password for the repo.

Step 2.1: Set up a repository password

A remote restic repository requires a password by default. This password will need to be provided either by a static text file (less secure) or by a script (more secure depending on the implementation). There are a few ways to do this (covered in detail in the official documentation), and you can change how it's done even after the repository is initialized.

💡
Make sure to keep back up your password somewhere, because you'll need it to restore data in case of an emergency.

Option 1: Store the password in a file

This literally means hard-coding your password in a file, then passing that file as an argument to your restic commands using the --password-file argument or the RESTIC_PASSWORD_FILE environmental variable.

Example:

eric@ubuntu-server:~$ echo my_password > /etc/restic/password.txt

Option 2: Store the password directly in an environmental variable

You can also store your password in an environmental variable RESTIC_PASSWORD that will be pulled by restic when running any commands against the repository.

Example:

eric@ubuntu-server:~$ echo export RESTIC_PASSWORD=my_password >> ~/.bashrc
eric@ubuntu-server:~$ source ~/.bashrc

Option 3: Write a script to generate your password (presumably from a more secure database)

This is by far the most secure and best option, but also the most difficult to set up. There are virtually unlimited options for doing this, since in reality all that we're doing is writing a script to generate the password, and how the password is generated is up to you.

The first step here is to write the script to get the password. In my case, I am storing my password as an entry in Bitwarden, launching a local REST API on my server (article on this coming soon), and querying the password using the script:

eric@ubuntu-server:~$ cat /etc/docker/restic/scripts/get_restic_password.sh 
#!/bin/bash

wget -q -O- http://0.0.0.0:8087/unlock --header "Content-Type: application/json" --post-data '{"password": '\"${BW_PASSWORD}\"} &>/dev/null 

wget -q -O- http://0.0.0.0:8087/object/item/$BW_RCLONE_ID | grep -Eo '"password":"([^"]*?)"' | awk -F: '{print $2}' | tr -d \"

wget -q -O- http://0.0.0.0:8087/lock --header "Content-Type: application/json" --post-data '{"password": '\"${BW_PASSWORD}\"} &>/dev/null

I have the Bitwarden entry entered as an environmental variable BW_RCLONE_ID and my Bitwarden password entered as an environmental variable BW_PASSWORD

From here, you just need set an environmental variable RESTIC_PASSWORD_COMMAND as the path to your script:

eric@ubuntu-server:~$ echo export RESTIC_PASSWORD_COMMAND=sh /etc/docker/restic/scripts/get_restic_password.sh >> ~/.bashrc

Note the sh before the path to the file

eric@ubuntu-server:~$ source ~/.bashrc

A note on Docker usage

If you're doing the Docker deployment, you'll want to make sure that the environmental variables are set in a .env file, and that you're passing this file through the --env-file argument in your docker run commands.

Also, if referencing any local file, make sure that the file's directory is mounted as a volume when running docker run and that the environment variable matches the path in the Docker container (as opposed to the local path).

Example:

eric@ubuntu-server:~$ docker run 
--env-file /home/eric/.env \
--rm --network host \
-v /etc/docker/restic/scripts:/restic-scripts \
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \ 
tofran/restic-rclone:latest \
<command>

Note the addition of the --env-file arg in the command above

eric@ubuntu-server:~$ cat ./.env
...
RESTIC_PASSWORD_COMMAND=sh /restic-scripts/get_restic_password.sh
...

Note that the command points to the directory as mounted in Docker (not the local directory)

Step 2.2: Initializing the repo

Once you've set up a password, restic makes setting up a new repository very simple: just run the following command with your remote as the destination for the repo and restic will take care of the rest.

Assuming that your password/script are set up as environmental variables, no additional arguments need to be passed to restic:

eric@ubuntu-server:~$ restic -r rclone:example-remote:example-repo init

For Docker:

eric@ubuntu-server:~$ docker run \
--env-file /home/eric/.env \
--rm --network host \
-v /etc/docker/restic/scripts:/restic-scripts \
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \ 
tofran/restic-rclone:latest \
-r rclone:example-remote:example-repo init

Note that we've removed the custom rclone entrypoint here, since from now on we'll be calling the restic CLI, which is the default entrypoint for this Docker container

From this point, you should be able to check your remote data store and see the initialized repo:

Step 2.3: Run the backups

There you have it! Now, your repo is set up in the remote storage target and the server is prepared to start backing up data.

Backup strategies will depend on the individual user, so check the official documentation to determine the commands that you'll use for backing up your data.

Other helpful commands

Here are some other useful commands that can come in handy while managing snapshots.

List your backup snapshots

Sometimes it can be helpful to see a summary of all of the data in the repo:

eric@ubuntu-server:~$ restic -r rclone:example-remote:example-repo snapshots

Docker:

eric@ubuntu-server:~$ docker run --rm --network host --env-file /home/eric/.env \
-v /etc/docker/restic/scripts:/restic-scripts \ 
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \
tofran/restic-rclone:latest \
-r rclone:example-remote:example-repo \
snapshots

Output:

ID        Time                 Host        Tags        Paths                                           Size
------------------------------------------------------------------------------------------------------------------
757a7db7  2025-04-11 03:00:16  example-repo                /backup-targets/home/eric                       23.980 MiB
1d5372d8  2025-04-11 03:00:32  example-repo                /backup-targets/etc/docker                      19.481 GiB
2a555964  2025-04-11 03:01:37  example-repo                /backup-targets/media/md0/media/content/Photos  45.455 GiB
efb68ffa  2025-04-11 03:01:58  example-repo                /backup-targets/media/md0/nextcloud             102.479 GiB
5d5777b4  2025-04-12 03:00:26  example-repo                /backup-targets/home/eric                       23.980 MiB
50bb4162  2025-04-12 03:00:43  example-repo                /backup-targets/etc/docker                      19.880 GiB
658bb12f  2025-04-12 03:01:55  example-repo                /backup-targets/media/md0/media/content/Photos  45.464 GiB
bf58ed5a  2025-04-12 03:02:16  example-repo                /backup-targets/media/md0/nextcloud             102.491 GiB
c6206a8a  2025-04-13 03:00:23  example-repo                /backup-targets/home/eric                       23.979 MiB
1e2fb0d1  2025-04-13 03:00:39  example-repo                /backup-targets/etc/docker                      19.969 GiB
3577f078  2025-04-13 03:01:33  example-repo                /backup-targets/media/md0/media/content/Photos  45.464 GiB
c8430b64  2025-04-13 03:01:48  example-repo                /backup-targets/media/md0/nextcloud             102.498 GiB
------------------------------------------------------------------------------------------------------------------
12 snapshots

Restore from backup

I recommend doing this at least once just to make sure that you can do it in case of an emergency.

This will restore the backup for the /etc/docker directory which we configured earlier.

eric@ubuntu-server:~$ restic -r rclone:example-remote:example-repo restore latest --target /etc/docker --path "/etc/docker"

Note that if your machine got totally wiped, you'll need to set up/install restic and rclone again. Make sure to keep your password!

Docker:

eric@ubuntu-server:~$ docker run --rm --network host --env-file /home/eric/.env \
-v /etc/docker/restic/scripts:/restic-scripts \ 
-v /etc/docker/restic/cache:/root/.cache/restic \
-v /etc/docker/rclone/config:/root/.config/rclone \
-v /etc/docker:/backup-targets/etc/docker \
tofran/restic-rclone:latest \
-r rclone:example-remote:example-repo \
restore latest --target /backup-targets/etc/docker --path "/backup-targets/etc/docker"

Note that the --target and --path variables are set to the directory in the Docker container

Conclusion

In this guide, we covered how to set up restic and Rclone to create a remote backup repository for files on a self-hosted server.

If you have any tips or other thoughts regarding this process, let me know below!