A => README.md +178 -0
@@ 0,0 1,178 @@
+Backups with restic
+===================
+
+Backups with restic are pretty easy, but it may save someone some time if I document my configuration.
+
+This outlines how to set up backups to B2 (Backblaze) using restic. It isolates configuration data and credentials, and uses systemd for the scheduling. I'm not going to justify any of the decisions, except to say that Backblaze is a great service, and is both extremely cost effective and easy to use with restic, as restic has built-in support for it.
+
+At the end of this, you'll have *encrypted*, automated backups in the cloud.
+
+Dependencies
+------------
+
+- restic
+- systemd
+- A Backblaze account
+
+
+Structure
+---------
+
+This is based on directory structures in Debian, which is what I have to use because my VPS provider doesn't support Arch. However, while untested, this should be the same for other systems with the same base packages. When you're done, the relevant file structure will look like this:
+
+- /etc/backup
+- /etc/backup/environment
+- /etc/backup/paths
+- /lib/systemd/system/backup.service
+- /lib/systemd/system/backup.timer
+- /lib/systemd/system/backup-prune.service
+- /lib/systemd/system/backup-prune.timer
+
+
+Steps
+-----
+
+### 1. Set up your Backblaze account
+
+You'll create an account, a bucket, and then an access key for the bucket.
+
+Visit [Backblaze](https://www.backblaze.com/) and create an account. Create a bucket for your backups a key for the bucket; I create a unique key for every server, to limit damage if one server is compromized. For the same reason, I also limit bucket access for each key to exactly one bucket. If you're using multiple buckets on one machine, re-using the key would make sense.
+
+Copy the account ID and access key from the key you create, as well as the name of the bucket. If you have multiple servers, each of these attributes will be unique as B2 assigns a unique ID and key for each bucket.
+
+
+### 2. The configuration files
+
+```bash
+sudo mkdir /var/cache/restic
+sudo mkdir /etc/backup
+sudo chmod 700 /etc/backup
+```
+
+Make sure that the `/etc/backup` directory is secured, as it will contain credentials. In my examples, you'll want to replace the IDs and keys with the ones from your account.
+
+```bash
+cat <<EOL | tee environment
+B2_ACCOUNT_ID=YOUR_B2_BUCKET_KEY_ID
+B2_ACCOUNT_KEY=YOUR_B2_BUCKET_KEY_SECRET
+RESTIC_REPOSITORY=b2:name-of-your-backup:restic
+RESTIC_PASSWORD="Really secure password goes here."
+RESTIC_CACHE_DIR=/var/cache/restic
+FILES=/etc/backup/paths
+KEEP_DAYS=28
+EOL
+```
+
+The first two variables come directly from Backblaze. The third needs to start with `b2` and end with `restic`, and replace the middle part with the name you gave the bucket. Files is the name of a file that contains the paths of the files and directory you want to back up; it's one-line per file or directory, and use full paths. `KEEP_DAYS` tells restic how many backups to keep; this is a matter of choice, and the `restic-forget` man page explains it best.
+
+```bash
+cat <<EOL | tee paths
+/etc/backup
+/lib/systemd/system/backup.service
+/lib/systemd/system/backup.timer
+/lib/systemd/system/backup-prune.service
+/lib/systemd/system/backup-prune.timer
+```
+
+Add your other backup paths or files to the `paths` file; you don't have to back up the files in this list -- it's just an example.
+
+
+### 3. Scheduling
+
+The backup service itself both backs up and then marks entries for future pruning.
+
+```bash
+sudo cat <<EOL | tee /lib/systemd/system/backup.service
+[Unit]
+Description=Restic-based backup
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/backup/environment
+Type=simple
+ExecStart=/usr/local/bin/restic backup --files-from ${FILES} --cache-dir ${RESTIC_CACHE_DIR}
+
+[Install]
+WantedBy=multi-user.timer
+EOL
+```
+
+Next is the timer. Set the period to whatever you want -- I'm doing twice a week below. The man page that explains the `OnCalendar` time format is `systemd.time` (e.g., `man systemd.time`).
+
+```bash
+sudo cat <<EOL | tee /lib/systemd/system/backup.timer
+[Unit]
+Description=Restic-based backup timer
+After=network.target
+
+[Timer]
+OnCalendar=04:00:00
+Persistent=True
+
+[Install]
+WantedBy=timers.target
+EOL
+```
+
+Pruning makes a lot of API calls to B2, so to control costs I run this less frequently. It's a trade-off, because pruning reduces the amount of storage in the buckets, which can also save money. For my use case, it's reasonable to run it once a month.
+
+If you have chosen to prune on a different, less frequent, schedule, then add the following services:
+
+```bash
+sudo cat <<EOL | tee /lib/systemd/system/backup-prune.service
+[Unit]
+Description=Restic-based pruning job
+Requires=network.target
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/backup/environment
+Type=simple
+ExecStartPre=/usr/local/bin/restic forget --keep-daily ${KEEP_DAILY} --keep-monthly ${KEEP_MONTHLY} --keep-yearly ${KEEP_YEARLY} --cache-dir ${RESTIC_CACHE_DIR}
+ExecStart=/usr/local/bin/restic prune --cache-dir ${RESTIC_CACHE_DIR}
+
+[Install]
+WantedBy=multi-user.timer
+EOL
+```
+
+```bash
+sudo cat <<EOL | tee /lib/systemd/system/backup-prune.timer
+[Unit]
+Description=Restic-based backup pruning job timer
+Requires=network.target
+After=network.target
+
+[Timer]
+OnCalendar=Sunday 01:00:00
+Persistent=True
+
+[Install]
+WantedBy=timers.target
+EOL
+```
+
+Once these are all created, tell systemd about them:
+
+```bash
+sudo systemd daemon-reload
+sudo systemctl enable backup.service
+sudo systemctl enable backup.timer
+sudo systemctl enable backup-prune.service
+sudo systemctl enable backup-prune.timer
+sudo systemctl start backup.timer
+sudo systemctl start backup-prune.timer
+```
+
+You can see the timers with `list-timers`:
+
+```bash
+sudo systemctl list-timers
+```
+
+Summary
+-------
+
+Most of the work here is in having everything cleanly separated, with the configuration in separate files, hiding credentials, and creating the service descriptions. Setting up Backblaze and running restic are anticlimactically trivial.
+
+I hope that this can save someone a little time.
A => backup-prune.service +13 -0
@@ 0,0 1,13 @@
+[Unit]
+Description=Restic-based pruning job
+Requires=network.target
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/backup/environment
+Type=simple
+ExecStartPre=/usr/local/bin/restic forget --keep-daily ${KEEP_DAILY} --keep-monthly ${KEEP_MONTHLY} --keep-yearly ${KEEP_YEARLY} --cache-dir ${RESTIC_CACHE_DIR}
+ExecStart=/usr/local/bin/restic prune --cache-dir ${RESTIC_CACHE_DIR}
+
+[Install]
+WantedBy=multi-user.timer
A => backup-prune.timer +11 -0
@@ 0,0 1,11 @@
+[Unit]
+Description=Restic-based backup pruning job timer
+Requires=network.target
+After=network.target
+
+[Timer]
+OnCalendar=Sunday 01:00:00
+Persistent=True
+
+[Install]
+WantedBy=timers.target
A => backup.service +11 -0
@@ 0,0 1,11 @@
+[Unit]
+Description=Restic-based backup
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/backup/environment
+Type=simple
+ExecStart=/usr/local/bin/restic backup --files-from ${FILES} --cache-dir ${RESTIC_CACHE_DIR}
+
+[Install]
+WantedBy=multi-user.timer
A => backup.timer +10 -0
@@ 0,0 1,10 @@
+[Unit]
+Description=Restic-based backup timer
+After=network.target
+
+[Timer]
+OnCalendar=04:00:00
+Persistent=True
+
+[Install]
+WantedBy=timers.target
A => environment +9 -0
@@ 0,0 1,9 @@
+B2_ACCOUNT_ID=YOUR_B2_BUCKET_KEY_ID
+B2_ACCOUNT_KEY=YOUR_B2_BUCKET_KEY_SECRET
+RESTIC_REPOSITORY=b2:name-of-your-backup:restic
+RESTIC_PASSWORD="Really secure password goes here."
+RESTIC_CACHE_DIR=/var/cache/restic
+FILES=/etc/backup/paths
+KEEP_DAILY=7
+KEEP_MONTHLY=3
+KEEP_YEARLY=2
A => paths +5 -0
@@ 0,0 1,5 @@
+/etc/backup
+/lib/systemd/system/backup.service
+/lib/systemd/system/backup.timer
+/lib/systemd/system/backup-prune.service
+/lib/systemd/system/backup-prune.timer