Self-hosting applications comes with the responsibility to manage backups for all services. Since all my applications are deployed via Docker containers at the moment, I was looking for a backup solution that also ships as a Docker container. Restic meets that requirement.1 It's a lightweight application written in Go that supports incremental remote backups over many protocols. For my personal use case, I'm choosing SFTP to my backup server running NixOS.

I started with creating an SSH key pair using ssh-keygen and added a user for restic to my NixOS config along with the public key:

users.users.restic = {
  isNormalUser = true;
  openssh.authorizedKeys.keys = [
    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOnGnXfUcOWm+qu2DR6tYRMk6Gye0tScVSEHYE/xfwVC florian@truenas_restic"
  ];
};

Next, I gave this user ownership of the /mnt/small/TrueNASBackup directory which I'll use as the backup target. I copied the private key to the other server in order to mount it into the restic container. Before any backups can be created, restic needs to initialize the target. I achieved this deploying the following compose.yaml. Not very pretty but just needed once.

---
services:
  restic:
    image: ghcr.io/restic/restic
    hostname: truenas_restic
    container_name: restic
    environment:
      - RESTIC_REPOSITORY=sftp:restic@192.168.178.42:/mnt/small/TrueNASBackup
      - RESTIC_PASSWORD=V3RY_S3CUR3_PA55W0RD
    volumes:
      - /mnt/SSD/Apps/Restic/ssh_key:/root/.ssh
    command: init

After the initialization was complete, I briefly confirmed on my NixOS system that new files appeared in the backup target directory. Then I slightly modified the compose.yaml to mount the sources where all my other docker mounts live into the container and changed the command to backup. Backups can now be done by deploying this configuration. Just make sure to stop other containers so that databases can flush all data to disk. And that's my very simple backup solution for my Docker containers!

---
services:
  restic:
    image: ghcr.io/restic/restic
    hostname: truenas_restic
    container_name: restic
    environment:
      - RESTIC_REPOSITORY=sftp:restic@192.168.178.42:/mnt/small/TrueNASBackup
      - RESTIC_PASSWORD=V3RY_S3CUR3_PA55W0RD
    volumes:
      - /mnt/SSD/Apps/Restic/ssh_key:/root/.ssh
      - /mnt/SSD/Apps:/SSD_Apps:ro
      - /mnt/HDD/Apps:/HDD_Apps:ro
    command: backup /SSD_Apps /HDD_Apps