Replacing duply/duplicity with restic.
One needs to:
All of this is out of scope for this article, instructions can be obtained from official B2 documentation if needed.
Create a new directory for all restic configuration files:
mkdir /etc/restic
Create restic-env
file that contains the common settings.
vim /etc/restic/restic-env
export B2_ACCOUNT_ID="xxxxxxxxxxx"
export B2_ACCOUNT_KEY="xxxxxxxxxxxx"
export RESTIC_REPOSITORY="b2:sablun-eu-restic"
export RESTIC_PASSWORD_FILE=/etc/restic/restic-password
You can now run this to load the settings every time you want to do something with restic:
source /etc/restic/restic-env
Or rather put it in your shell rc file (.zshrc
, .bashrc
,…) so it is allways loaded.
Create a password file and fill it with a password of your selection, do not loose this password, as backup is dead without it:
vim /etc/restic/restic-password
Create exclude list:
vim /etc/restic/restic-exclude
proc/
dev/
mnt/
run/
sys/
tmp/
var/log/
var/cache/apt/archives/
Secure the settings folder, you don’t want anyone else reading it:
chown -R root:root /etc/restic
chmod -R 700 /etc/restic
Initialize the backup:
restic init
Simple backup:
restic backup /
Backup with the use of tags and exclude file:
restic --exclude-file=/etc/restic/restic-exclude --tag auto backup /
Dump all databases and backup them:
mysqldump --all-databases | restic backup --stdin --stdin-filename all_databases.sql --tag mysql
restic forget --prune --keep-last 60 --keep-tag keep --keep-daily 60 --keep-monthly 24 --keep-yearly 10
$ restic check
using temporary cache in /tmp/restic-check-cache-309345860
repository d0444097 opened (repository version 1) successfully, password is correct
created new cache in /tmp/restic-check-cache-309345860
create exclusive lock for repository
load indexes
check all packs
check snapshots, trees and blobs
[1:22] 100.00% 79 / 79 snapshots
no errors were found
You can use tag keep
when manually creating important point in time backup/snapshot, so the prune and forget does not remove it.
restic snapshots
repository d0444097 opened successfully, password is correct
ID Time Host Tags Paths
-------------------------------------------------------------------------
8331ca07 2022-03-25 21:03:20 sablun.org /
f2ff363f 2022-03-25 21:20:16 sablun.org /
929759b7 2022-03-25 21:21:01 sablun.org auto /
5d568b22 2022-03-25 21:22:59 sablun.org auto /
bb9b4e58 2022-03-25 21:26:44 sablun.org auto /
1f62a54d 2022-03-25 21:27:43 sablun.org auto /
beb141d4 2022-03-25 21:36:21 sablun.org auto /
0d90d87e 2022-03-25 21:38:58 sablun.org mysql /all_databases.sql
8833e852 2022-03-25 21:41:38 sablun.org auto /
72cb95af 2022-03-25 21:42:10 sablun.org mysql /all_databases.sql
990927ee 2022-03-26 00:00:01 sablun.org auto /
8e7942cc 2022-03-26 00:00:54 sablun.org mysql /all_databases.sql
00aff052 2022-03-26 08:24:25 sablun.org auto /
b1a6bafc 2022-03-26 08:30:37 sablun.org mysql /all_databases.sql
-------------------------------------------------------------------------
14 snapshots
To automate backup, prune and validation, we will use shush
.
vim /etc/shush/restic-backup.conf
# "set -o pipefail" is here because we want bash to return an error if any of
# the commands in the pipeline fails.
command=nice -n19 ionice -c3 bash -c -- 'set -o pipefail; (source /etc/restic/restic-env && restic --exclude-file=/etc/restic/restic-exclude --tag auto backup / ; mysqldump --all-databases | restic backup --stdin --stdin-filename all_databases.sql --tag mysql ; restic forget --keep-last 60 --keep-tag keep --keep-daily 60 --keep-monthly 24 --keep-yearly 10 ) 2>&1 | ts "[%b %d %H:%M:%S]"'
lock=notify=root,abort
lockfile=/var/lock/shush-restic-backup.lock
lockmsg=WARNING: backup on host %h has been invoked again, but the previous invocation is still running! (via restic, ran by shush with config file %N)
format=text
[success]
if=$exit == 0
subject=OK: backup on host %h completed. (via restic, ran by shush with config file %N)
to=root
format=text
[failure]
if=$exit != 0
to=root
subject=ERROR: backup on host %h failed! (via restic, ran by shush with config file %N)
format=text
You can test the configuration manually:
shush -c /etc/shush -m restic-backup.conf
Implementing retention and validation once per week.
vim /etc/shush/restic-prune.conf
# "set -o pipefail" is here because we want bash to return an error if any of
# the commands in the pipeline fails.
command=nice -n19 ionice -c3 bash -c -- 'set -o pipefail; (source /etc/restic/restic-env && restic prune && restic check) 2>&1 | ts "[%b %d %H:%M:%S]"'
lock=notify=root,abort
lockfile=/var/lock/shush-restic-prune.lock
lockmsg=WARNING: prune on host %h has been invoked again, but the previous invocation is still running! (via restic, ran by shush with config file %N)
format=text
[success]
if=$exit == 0
subject=OK: prune on host %h completed. (via restic, ran by shush with config file %N)
to=root
format=text
[failure]
if=$exit != 0
to=root
subject=ERROR: prune on host %h failed! (via restic, ran by shush with config file %N)
format=text
vim /etc/cron.d/restic-backup
# run the shush configuration file for the restic backup.
# Settings are in the /etc/shush/restic-backup.conf and /etc/restic/*.
# unset MAILTO, as shush sends its own mail.
MAILTO=""
# set PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# m h dom mon dow user command
00 00 * * * root shush -c /etc/shush -m restic-backup.conf
00 03 1 * * root shush -c /etc/shush -m restic-prune.conf
TODO
https://restic.readthedocs.io/en/stable/050_restore.html
Edit 11.12.2023: First time I had to do a recovery, after a mistake with rm
.
source /etc/restic/restic-env && restic restore latest --target /tmp/restore --include "/home/b4d/important-data"