Sysadmin's Home Backup

By Karl-Marx

Disclaimer: this is not a tutorial.

Another disclaimer: I say home as in the place where I live, not as in /home/marx. Although I suppose it works either way.

Which software?

Restic

The backup tool. I chose it first and invented a justification after, so, no point in pretending there is a good motive. But that is philosophical matter.

It does backup stuff, that is what’s important.

Rclone

Restic supports a handful of repository types, alas the one I need is not one of them. Fortunately, restic allows us to use rclone as backend, which supports mostly any cloud storage provider.

Systemd

Sorry if you are on board of the “I hate systemd, it is the most disgusting piece of software ever written” train. Use cron instead, it will work just as well.

Initializing repositories

First I created a rclone remote called google for Google Drive (no need to judge me I already do it 🤷).

rclone config

Default options are fine, but encryption is a nice addition.

Initializing local repository:

restic init --repo /media/seagate/backup

This is just a big hard drive I have for local backup, for things that would be cumbersome to lose but it wouldn’t hurt.

Initializing remote repository:

restic init --repo rclone:google:backup

For data I cannot or will not afford to loose.

My backup logic

Level 0

If I loose these files I will have a panic attack. I am exaggerating, or perhaps not. I hope to never find out.

Lever 1

Mostly as important as the Level 0, but as it considerably more space-hungry I am willing to pretend it is not that important. Don’t say anything, it makes sense in my head 🙉.

Lever 2

This one exists to make my life easier in case I do something stupid.

My backup strategy

Simple:

  • l0 -> local and remote
  • l1 -> local and remote
  • l2 -> local

My intention is to run these backups hourly, that will make the snapshot list unreasonably long. Unless, offcourse, i make up a rule to determine which ones to keep.

I decided to keep

  • 12 hourly
  • 7 daily
  • 4 weekly
  • 12 monthly
  • 5 yearly

The backup command

Local 0:

restic backup --verbose \
  --group-by host,paths,tags \
  --tag l0,systemd \
  --password-file ~/.config/restic/password \
  --repo /media/seagate/backup \
  ~/Documents ~/Secrets ~/Logbook ~/Creations

Local 1:

restic backup --verbose \
  --group-by host,paths,tags \
  --tag l1,systemd \
  --password-file ~/.config/restic/password \
  --repo /media/seagate/backup \
  ~/Documents ~/Secrets ~/Logbook ~/Creations ~/Pictures ~/Templates ~/Sophie ~/Code

Local 2:

restic backup --verbose \
  --group-by host,paths,tags \
  --tag l2,systemd \
  --password-file ~/.config/restic/password \
  --repo /media/seagate/backup \
  ~/

Remote 0:

restic backup --verbose \
  --group-by host,paths,tags \
  --tag l0,systemd \
  --password-file ~/.config/restic/password \
  --repo rclone:google:backup \
  ~/Documents ~/Secrets ~/Logbook ~/Creations

Remote 1:

restic backup --verbose \
  --group-by host,paths,tags \
  --tag l1,systemd \
  --password-file ~/.config/restic/password \
  --repo rclone:google:backup \
  ~/Documents ~/Secrets ~/Logbook ~/Creations ~/Pictures ~/Templates ~/Sophie ~/Code

The forget command

Local:

restic forget --verbose \
  --password-file ~/.config/restic/password \
  --repo /media/seagate/backup \
  --keep-hourly 12 \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 12 \
  --keep-yearly 5 \
  --prune

Remote:

restic forget --verbose \
  --password-file ~/.config/restic/password \
  --repo rclone:google:backup \
  --keep-hourly 12 \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 12 \
  --keep-yearly 5 \
  --prune

Systemd unities

Service [ ~/.config/systemd/user/restic@.service ]

[Unit]
Description=Restic backup (%I)

[Service]
Type=oneshot

Environment="RESTIC_local0_TAGS=l0"
Environment="RESTIC_local0_REPOSITORY=/media/seagate/backup"
Environment="RESTIC_local0_TARGET=%h/Documents %h/Secrets %h/Logbook %h/Creations"

Environment="RESTIC_local1_TAGS=l1"
Environment="RESTIC_local1_REPOSITORY=/media/seagate/backup"
Environment="RESTIC_local1_TARGET=%h/Documents %h/Secrets %h/Logbook %h/Creations %h/Pictures %h/Templates %h/Sophie %h/Code"

Environment="RESTIC_local2_TAGS=l2"
Environment="RESTIC_local2_REPOSITORY=/media/seagate/backup"
Environment="RESTIC_local2_TARGET=%h"

Environment="RESTIC_google0_TAGS=l2"
Environment="RESTIC_google0_REPOSITORY=rclone:google:backup"
Environment="RESTIC_google0_TARGET=%h/Documents %h/Secrets %h/Logbook %h/Creations"

Environment="RESTIC_google1_TAGS=l1"
Environment="RESTIC_google1_REPOSITORY=rclone:google:backup"
Environment="RESTIC_google1_TARGET=%h/Documents %h/Secrets %h/Logbook %h/Creations %h/Pictures %h/Templates %h/Sophie %h/Code"

ExecStart=flock /tmp/restic-systemd.lock bash -c 'restic backup --verbose --group-by "host,paths,tags" --tag "${RESTIC_%i_TAGS},systemd" --password-file %h/.config/restic/password --repo ${RESTIC_%i_REPOSITORY} ${RESTIC_%i_TARGET}'
ExecStartPost=flock /tmp/restic-systemd.lock restic forget --verbose --password-file %h/.config/restic/password --repo ${RESTIC_%i_REPOSITORY} --keep-hourly 12 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 5 --prune

Timer [ ~/.config/systemd/user/restic@.timer ]

[Unit]
Description=Restic backup (%I)

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

Enable the timer

systemctl --user daemon-reload
systemctl --user enable --now restic@local0.timer
systemctl --user enable --now restic@local1.timer
systemctl --user enable --now restic@local2.timer
systemctl --user enable --now restic@google0.timer
systemctl --user enable --now restic@google1.timer