π Escaping USA Tech, Bye Bye Dropbox, Hello! Jottacloud
I recently got more concerned about what is happening in the US since a certain president He-Who-Must-Not-Be-Named and what this does in the world and my personal life. I was already on a streak, cutting loose from BIG-TECH social media like METAβs βsuiteβ and Google. This was also for privacy concerns.
I got concern about having all my data, partly client side encrypted but partly not, stored in the USA with Dropbox. I really liked Dropbox because it has a great adoption rate in other apps and products. But I did not like it that all my data was in the US. And with the recent presidency of He-Who-Must-Not-Be-Named, I got more concerned about my data with Dropbox.
Finding a European alternative with the same level of integration in software and services as Dropbox is a challenging task. Not that these services are inferior, but integrating them can sometimes be difficult. My goal was to achieve incremental backups of my shared folders on a Synology NAS and have the sync folder from my cloud storage synchronised with the Synology NAS.
This would be typically done with Hyperbackup for incremental backups and Cloud Sync for your sync folder. Most of the services listed there are either US-based, expensive, no up to the job, etc. A least for me.
After looking around and comparing European-based cloud providers, I got my eye on Jottacloud. This is a Norwegian cloud provider which is fast, in Europe of course, nice supporting clients for iOS and macOS (Yes, also US BIG-TECH, but I love Apple, there is nothing that compares with Apple Products. And I think Apple is doing a better job on privacy), has a great deal on βunlimitedβ storage space. The only downside Jottacloud has, they donβt (like Dropbox) have zero-knowledge encryption. If they had it, would enhance privacy a lotβ¦ But since they are in Europe with strict privacy laws, I took that as a step forward compared to the US-based Dropbox. Plus, the unlimited storage deal at JottaCloud is the same price as the 2 TB deal I had at Dropbox. Just a hint: if you look around on the internet you can find Jottacloud deals. I got a deal with 15% off for the first year.
Jottacloud also runs on 100% renewable energy, if you care for such a thing (I do).
Jottacloud is not one of the default services supported by Synology in their backup suite and other software. This is a shame, but there is a way to still create nice incremental backups of your shared folders to Jottacloud directly from your Synology.
This is achieved using a brilliant free application called Restic. Restic is a free, open-source backup tool offering secure, efficient, and flexible data protection. It supports multiple storage backends, including cloud services, and features encryption, deduplication, and compression. Restic is user-friendly and suitable for various operating systems, making it ideal for both personal and professional backup needs.
To access Jottacloud with Restic, I used Rclone. Rclone is a versatile command-line tool for managing cloud storage, offering features such as file syncing, encryption, and compression. It supports over 70 cloud services, including Jottacloud, Google Drive, and Amazon S3, and is ideal for automating backups and data transfers across various platforms with ease and reliability.
Rclone and Restic are not natively available on your Synology. There are scripts and methods to install them via the NAS shell. However, I am a fan of Docker. Since I own a Synology that supports Docker, which Synology refers to as βContainer Managerβ in their DSM, I implemented Restic and Rclone using Docker.
Docker is a containerisation platform that enables efficient deployment and management of applications. It allows developers to package software into portable containers, ensuring consistent performance across environments. Docker streamlines development, testing, and deployment processes, enhancing flexibility and scalability for a wide range of applications and services.
If your Synology does not support Docker, you can still achieve what is described below by using a Raspberry Pi. You can in install your favourite OS (mine is Ubuntu on the PI) and install Docker within Ubuntu on this beautiful device. If you have done so, you can connect your shared folders using NFS to the Ubuntu installation you can use the method that is described below.
Okay, how is this done? Five years ago, I came a cross of a nice five-year-old (at that time) project on GitHub. This already made a docker container including Restic and Rclone. At the time It was not recently maintained (older Restic version, not build with the latest package) I decided to fork this project and update and enhance it. My GitHub repository can be found here. The pre-build docker images for ARM and AMD can be found here.
I recently added an option to set up a sync with your sync-folder, supported by your cloud provider. I will explain that later. First, we set up the container in Docker.
Below you find a template docker-compose.yml file. This uses the stable build for the image. If you like the development tree, use the marc0janssen/restic-backup-helper:develop
as an image reference.
version: '3'
services:
restic-remote:
container_name: restic-remote
image: marc0janssen/restic-backup-helper:latest
healthcheck:
test: ["CMD", "restic", "-r", "rclone:jottacloud:backups", "cat", "config"]
interval: 15m
timeout: 10s
start_period: 1m
start_interval: 10s
restart: always
hostname: supernode
cap_add:
- DAC_READ_SEARCH
- SYS_ADMIN
devices:
- /dev/fuse
environment:
- RESTIC_PASSWORD=YOUR_PASSWORD_HERE
- RESTIC_TAG=YOUR_TAGS_HERE
- RESTIC_FORGET_ARGS=--prune --keep-hourly 24 --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --keep-yearly 10
- RESTIC_REPOSITORY=rclone:jottacloud:backups
- RESTIC_JOB_ARGS=--exclude-file /config/exclude_files.txt
- BACKUP_CRON=0 1,13 * * *
- BACKUP_ROOT_DIR=/volume1/data
- MAILX_RCPT=your_mail@here.tld
- MAILX_ON_ERROR=OFF
- CHECK_CRON=37 1 1 * *
- RCLONE_CONFIG=/config/rclone.conf
- SYNC_JOB_FILE=/config/sync_jobs.txt
- SYNC_JOB_ARGS=--exclude-from exclude_sync.txt
- SYNC_CRON=*/10 * * * *
- TZ=Europe/Amsterdam
volumes:
- /etc/localtime:/etc/localtime:ro
- /path/to/your/hooks:/hooks
- /path/to/your/log:/var/log
- /path/to/your/restore:/restore
- /path/to/your/config/:/config
- /path/to/your/config/msmtprc:/etc/msmtprc
- /volume1/data:/volume1/data
Set up the following tree for your installation:
./
βββ config
β βββ exclude_files.txt
β βββ exclude_sync.txt
β βββ include_files.txt
β βββ msmtprc
β βββ rclone.conf
β βββ sync_jobs.txt
βββ hooks
βββ log
β βββ backup-error-last.log
β βββ backup-last.log
β βββ check-error-last.log
β βββ check-last.log
β βββ cron.log
βββ scripts
βββ docker-compose.yml
-
config
exclude_files.txt
- files/folders to exclude from your Restic backupsexclude_sync.txt
- files/folders to exclude from your Rclone bisyncinclude_files.txt
- files/folders to include from your Restic backupsmsmtprc
- configuration file for the msmtp-clientrclone.conf
- configuration file for your rclone clientsync_jobs.txt
- configuration file with sync jobs for rclone
-
hooks
pre-backup.sh
- script started before backuppost-backup.sh
- script started after backuppre-check.sh
- script started before checking the repositorypost-check.sh
- script started after checking the repositorypre-sync.sh
- script started before sync of sync folderpost-sync.sh
- script started after sync of sync folder
-
log
backup-error-last.log
- Most recent backup error logbackup-last.log
- Most recent backup logcheck-error-last.log
- Most recent repository check error logcheck-last.log
- Most recent repository check logcron.log
- Active cron logsync-error-last.log
- Most recent sync error logsync-last.log
- Most recent sync log
-
scripts
docker-compose.yml
- Container Configuration file
The first thing to do is to create a rclone config file. I, personally, do this within Ubuntu on a Raspberry Pi, where I installed rclone. Run the follow command and follow its instructions:
$ rclone config
To choose the following option, n) New remote
. Enter a name for your new remote. Since I use Jottacloud, I entered Jottacloud
. A list of cloud providers is shown. Jottacloud is number 25
. Enter this number on the CLI. The next question is if you have an advanced configuration, for me, this answer is the default no
. After this, you have to select an authentication type. Choose 1 Standard authentication
. Now you have to generate a Personal login token
. This can be generated here. Paste this token in the CLI and press enter. The next question is if you use a non-standard device or mountpoint. For a backup is n) No (default)
but if you want to use the sync option of this image I advise you to select y) Yes
and pick the Sync
mount point. For now, select n) No (default)
. Confirm your config. Your new created rclone.conf
can be found in:
~/.config/rclone/rclone.conf
Copy this file to the /config/
directory of the tree shown above.
Remember to set RESTIC_REPOSITORY
and healthcheck:
in the docker-compose.yml
to the path of your repository. For me, this would be:
rclone:jottacloud:backups
NOTE: If you plan to back up multiple nodes with their containers. And you decide to have a rclone and Restic package on your client desktop or laptop. And also connect to the repository, ALWAYS have a new separate rclone.conf file. Your token will get invalid if you connect with multiple nodes to use the same token.
NOTE: Also make sure the rclone.conf file is writable for the restic-helper-container, since Rclone will update the expiration date for the token. If it fails to do so, your token will get invalid.
If the token gets invalid, you can update your token with:
$ rclone config reconnect jottacloud:
Where jottacloud:
is the name of your remote.
The next stop is to create a configuration file for the mail option in the container. This file should look like the following example.
account default
from _mail_from@here.tld_
host _smtp_host.here.tld_
port 587
tls on
auth on
user _login@here.tld_
password _Pa55w0rd_h3r3_
Next stop is to create a configuration file for the files you would rather not back up from your source. A basic file for a Synology would be something like the following example. Of course, you can add your exclusions to the file exclude_files.txt
.
*@eaDir*
.DS_Store
**/#recycle
Setting the BACKUP_ROOT_DIR
environment variable in the docker-compose.yml
file to a shared directory of your Synology would only back up that directory, ex.: BACKUP_ROOT_DIR=/volume1/data
. That is probably not what you want. You most likely want to back up more shared directories. If you choose BACKUP_ROOT_DIR=/volume1
to do so, I would back up ALL the stuff in /volume1
and that is also not what we want.
To come around this, you leave BACKUP_ROOT_DIR=
empty and set up include_files.txt
. This file holds the files and directories you would like to back up.
/volume1/content
/volume1/docker
/volume1/documents
/volume1/homes
/volume1/homevideo
/volume1/inbox
/volume1/logging
/volume1/photo
/volume1/programming
/volume1/software
Edit your docker-compose.yml
with the following line.
- RESTIC_JOB_ARGS=--exclude-file /config/exclude_files.txt --files-from /config/include_files.txt
We still need to create a repository in the cloud, Jottacloud that is. Here we need to use Restic on the linux CLI. I do this again from an Ubuntu installation on a Raspberry Pi. The command you have to execute is:
$ restic -r rclone:jottacloud:backups init
- rclone - This is the protocol we like to use
- jottacloud - This is the remote you created with rclone
- backups - This is a target that will be created in the Jottacloud Archive section.
Now set up the rest of the docker-compose.yml
file and start your container. The following command will get you started to start the container.
$ docker-compose -p "restic-backup-helper" -f /path/to/your/docker-compose.yml up -d --remove-orphans
Of course, if you use Portainer. You can create a stack and past the content of the docker-compose.yml
in the editor and start your container like so.
Portainer is an open-source container management platform offering a user-friendly graphical interface for managing Docker and Kubernetes environments. It simplifies deployment, monitoring, and maintenance of containerised applications, providing a unified dashboard for multiple environments and supporting various container technologies like Docker Swarm and Azure ACI.
If you set up the container correctly, you would see something like this.
π *************************************************
π *** Restic Backup Helper ***
π *************************************************
π Starting container Restic Backup Helper 'kish' on: 2025-03-25 19:03:16...
π¦ Release: 1.6.52-0.17.3-dev
π Checking repository status...
βΉοΈ Repository check status: 0
β
Restic repository 'rclone:jottacloud:backups' attached and accessible.
β° Setting up backup cron job with expression: 30 17 * * 6
β° Setting up sync cron job with expression: */5 * * * *
β
Container started successfully.
In this example, the backup will be executed every Saturday at 17:30. The repository can be found on rclone:jottacloud:backups
. This will back it up to the archive part of Jottacloud.
If there is a successful backup, you will see output like this.
βΉοΈ Pre-backup script not found...
π Starting Backup at 2025-03-25 17:30:00
π¦ Performing backup of /volume1/inbox...
β
Backup Successful
π Finished backup at 2025-03-25 17:30:38 after 0m 38s
βΉοΈ Post-backup script not found...
So your backup is nice and running. In the example above, there a second CRON with runs every 5 minutes. This is the sync folder the connects to the Jottacloud synchronisation part of the cloud.
The setting this up runs rclone config
again, runs through the same steps as shown above but if the question comes for a non-standard device or mountpoint. Choose YES and choose the option Sync
. This gives Rclone access to the synchronisation part of Jottacloud. The advantage is that whatever you sync from your Synology to Jottacloud, the Jottacloud software will pick this up and sync this to your other devices. If you have the Jottacloud software installed.
Donβt forget to pick a new TOKEN, and after you generate that new config file (with two remotes) copy it to /config/
of your container. Also pick a new name for that remote like jottasync
.
Set up the following environment variables in the docker-compose.yml
file.
- SYNC_JOB_FILE=/config/sync_jobs.txt
- SYNC_JOB_ARGS=--exclude-from exclude_sync.txt
- SYNC_CRON=*/10 * * * *
The sync_jobs.txt
should contain something like this.
# SYNC JOBS
# SOURCE;DESTINATION
/volume1/inbox;jottasync:/inbox
/volume1/photo;jottasync:/photo
/volume1/documents;jottasync:/documents
It is the source and destination of the data you like to sync.
The exclude_sync.txt
should contain the files and directories you donβt like to sync.
# Exclude system directories
@eaDir/**
\#recycle/**
# Exclude macOS system files
.DS_Store
And set your SYNC_CRON
with the desired interval of your sync.
If all is well set up, you will see output for the first run only like the following example.
π Performing sync of /volume1/inbox <-> jottasync:/inbox...
β Sync Failed with Status 2
π¨ Starting recovery procedure...
π Step 1: Updating from /volume1/inbox to jottasync:/inbox
π Step 2: Updating from jottasync:/inbox to /volume1/inbox
π Step 3: Performing full resync between /volume1/inbox and jottasync:/inbox
β
Recovery Successful - All steps completed
π Recovery Exitcode Summary: SourceβDest=0, DestβSource=0, Resync=0
π Finished sync at 2025-03-25 15:55:39 after 0m 39s
π Performing sync of /volume1/photo <-> jottasync:/photo...
β Sync Failed with Status 2
π¨ Starting recovery procedure...
π Step 1: Updating from /volume1/photo to jottasync:/photo
π Step 2: Updating from jottasync:/photo to /volume1/photo
π Step 3: Performing full resync between /volume1/photo and jottasync:/photo
β
Recovery Successful - All steps completed
π Recovery Exitcode Summary: SourceβDest=0, DestβSource=0, Resync=0
π Finished sync at 2025-03-25 15:55:39 after 0m 39s
π Performing sync of /volume1/documents <-> jottasync:/documents...
β Sync Failed with Status 2
π¨ Starting recovery procedure...
π Step 1: Updating from /volume1/documents to jottasync:/documents
π Step 2: Updating from jottasync:/documents to /volume1/documents
π Step 3: Performing full resync between /volume1/documents and jottasync:/documents
β
Recovery Successful - All steps completed
π Recovery Exitcode Summary: SourceβDest=0, DestβSource=0, Resync=0
π Finished sync at 2025-03-25 15:55:39 after 0m 39s
The first sync will βfailβ because the caches are not yet up to date. The script will handle this correctly for the second run of your sync. Like you see below.
βΉοΈ Pre-sync script not found...
π Performing sync of /volume1/inbox <-> jottasync:/inbox...
β
Sync Successful
π Finished sync at 2025-03-25 19:30:11 after 0m 11s
π Performing sync of /volume1/photo <-> jottasync:/photo...
β
Sync Successful
π Finished sync at 2025-03-25 19:30:24 after 0m 24s
π Performing sync of /volume1/documents <-> jottasync:/documents...
β
Sync Successful
π Finished sync at 2025-03-25 19:30:33 after 0m 33s
βΉοΈ Post-sync script not found...
Note: The default for Rclone bisync if that is 50% more difference between the source and the destination is found, Rclone will fail and exit. The script syncing your data will then try to copy all data back from the source to the destination and from destination to source. This will look like all syncs did not work, but actually, it is a safety measure. If you donβt want this, add --force
to your SYNC_JOB_ARGS
.
Here are some examples to use Restic inside the container from the host.
This command will list all snapshots with Restic from a container restic-remote
.
$ sudo docker exec -ti restic-remote restic snapshots
This command generates the following output.
ID Time Host Tags Paths Size
-----------------------------------------------------------------------------------
9547a8f4 2025-03-21 16:33:45 eridu eridu /home/pi/docker 324.319 MiB
693fc4e7 2025-03-21 23:59:09 eridu eridu /home/pi/docker 324.366 MiB
a2db8a02 2025-03-22 18:00:00 eridu eridu /home/pi/docker 324.823 MiB
b3076cd0 2025-03-22 19:00:00 eridu eridu /home/pi/docker 324.476 MiB
187efc43 2025-03-22 20:00:00 eridu eridu /home/pi/docker 324.477 MiB
e50c1751 2025-03-22 21:00:00 eridu eridu /home/pi/docker 324.482 MiB
If you want to list the content of a snapshot, you use the following command.
$ sudo docker exec -ti restic-remote restic ls e50c1751 --long | grep mp3
This command will list all files in the snapshot e50c1751
. The grep command will only show you all lines with mp3
in its path.
Restoring files from a snapshot is done with the following command.
$ sudo docker exec -ti restic-remote restic restore e50c1751 --target /data --include /mnt/data/
This command will restore from snapshot e50c1751
to target /data
, but only the files from the path /mnt/data/
For all the information you need on Restic, check this website.
If this blog was any help to you, give away a free Lucky Four-Leaf Clover
βοΈπ