Duplicati is a very simple and straightforward backup tool, which is why I use it. In this example, duplicati will be running in a Docker container.
- Installing duplicati
- Backing up files
- Backing up the database and crontab
Installing duplicates
Let's create a duplicate folder
mkdir duplicati
cd duplicatiIn the duplicati folder, create a "backups" folder. This folder will be used for database and crontab backups.
mkdir backupsWe'll run duplicati in Docker. Here's an example docker-compose.yml
services:
duplicati:
image: lscr.io/linuxserver/duplicati:latest
container_name: duplicati
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- SETTINGS_ENCRYPTION_KEY=${ENCRYPTION_KEY}
- CLI_ARGS= #optional
- DUPLICATI__WEBSERVICE_PASSWORD= #optional
volumes:
- /path/to/duplicati/config:/config
- /path/to/backups:/backups
- /path/to/source:/source #forward the necessary folders
ports:
- 8200:8200
restart: unless-stoppeddocker-compose.yml
Launching the container
docker compose up -dCreating a backup copy of files
Go to the control panel. Everything is intuitive there.
If you don't want to make backups of hidden files, you need to select hidden in the Exclude files by attribute drop-down list in the options section.
I recommend using smart backup retention because it saves you from having to set it up yourself.
Creating a backup copy of databases and crontab
To create database backups, we'll use a script and crontab. The idea is that we'll run a script in crontab on a schedule to create a database dump and a crontab backup. For example, at 2:00 AM, the db_backup.sh and crontab_backup.sh scripts run and save the dumps to a specific folder. At 2:05 AM, duplicati simply copies files from this specific folder, and at 3:00 AM, we delete this specific folder. And so on, repeating the process.
Create files in the backups folder
cd backups
touch db_backup.sh && touch crontab_backup.sh && touch delete_backup.sh
We grant permission to execute these files.
sudo chmod +x db_backup.sh && sudo chmod +x crontab_backup.sh && sudo chmod +x delete_backup.shSample code for db_backup.sh. In this example, we create a dump from Docker containers.
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_DIR="$SCRIPT_DIR/sql"
mkdir -p "$BACKUP_DIR"
CONTAINERS=("container1" "container2" "and so on")
DB_USER=
DB_PASS=
for CONTAINER in "${CONTAINERS[@]}"; do
echo "Backup $CONTAINER"
if [ "$CONTAINER" = "container1" ]; then
databases=$(docker exec -i "$CONTAINER" mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "^(Database|information_schema|performance_schema|sys|mysql)$" | tr -d '\r')
else
databases=$(docker exec -i "$CONTAINER" mariadb -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "^(Database|information_schema|performance_schema|sys|mysql)$" | tr -d '\r')
fi
if [ -z "$databases" ]; then
echo "Error"
continue
fi
for db in $databases; do
echo "Dump db $db"
FILENAME="$BACKUP_DIR/${db}-$(date +%Y.%m.%d-%H:%M:%S).sql"
if [ "$db" = "container1" ]; then
docker exec -i $CONTAINER mysqldump -u "$DB_USER" -p"$DB_PASS" "$db" 2>/dev/null > "$FILENAME"
else
docker exec -i $CONTAINER mariadb-dump -u "$DB_USER" -p"$DB_PASS" "$db" 2>/dev/null > "$FILENAME"
fi
done
done
exit 0db_backup.sh
This code fragment is responsible for obtaining a list of tables excluding service tables that are not needed in the backup.
if [ "$CONTAINER" = "container1" ]; then
databases=$(docker exec -i "$CONTAINER" mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "^(Database|information_schema|performance_schema|sys|mysql)$" | tr -d '\r')
else
databases=$(docker exec -i "$CONTAINER" mariadb -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "^(Database|information_schema|performance_schema|sys|mysql)$" | tr -d '\r')
fi
if [ -z "$databases" ]; then
echo "Error"
continue
fidb_backup.sh
This code creates an exception for container1 because it runs on MySQL, so we need to retrieve the tables using the MySQL utility. If you don't need this, simply remove this condition.
This piece of code is directly responsible for creating the dump file.
for db in $databases; do
echo "Dump db $db"
FILENAME="$BACKUP_DIR/${db}-$(date +%Y.%m.%d-%H:%M:%S).sql"
if [ "$db" = "container1" ]; then
docker exec -i $CONTAINER mysqldump -u "$DB_USER" -p"$DB_PASS" "$db" 2>/dev/null > "$FILENAME"
else
docker exec -i $CONTAINER mariadb-dump -u "$DB_USER" -p"$DB_PASS" "$db" 2>/dev/null > "$FILENAME"
fi
donedb_backup.sh
If you have a database server running directly on the host, then you just need to remove docker exec -i $CONTAINER at the beginning of the command.
Setting up crontab and creating a crontab file dump
The final step is to create a crontab job.
Let's go to crontab
crontab -e
And at the very bottom of the file we insert these instructions.
00 2 * * * /home/user/duplicati/backups/make_dump.sh > /dev/null 2>&1
00 3 * * * /home/user/duplicati/backups/delete_dumps.sh > /dev/null 2>&1
00 2 * * * /home/user/duplicati/backups/crontab_backup.sh > /dev/null 2>&1Now we paste this code into the crontab_backup.sh file
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_DIR="$SCRIPT_DIR/crontabs"
mkdir -p "$BACKUP_DIR"
cd /home/user/duplicati/backups/crontabs
crontab -l > 'crontab-'$(date +"%Y.%m.%d-%H:%M:%S")'.txt'crontab_backup.sh
Open the delete_backup.sh file and paste the code
#!/bin/bash
rm -rf /home/user/duplicati/backups/sql
rm -rf /home/user/duplicati/backups/crontabsdelete_backup.sh
I hope everything works out for you!🙃