#+title: Btrfs #+setupfile: ../org-templates/page.org ** Create systemd.mount unit for Btrfs on external HDD #+BEGIN_QUOTE internet_archive is used here as an example. #+END_QUOTE Get the UUID of the Btrfs partition. #+BEGIN_SRC shell sudo blkid -s UUID -o value /dev/sda1 d3b5b724-a57a-49a5-ad1d-13ccf3acc52f #+END_SRC Edit ~/etc/systemd/system/mnt-internet_archive.mount. #+BEGIN_SRC systemd [Unit] Description=internet_archive Btrfs subvolume DefaultDependencies=yes [Mount] What=/dev/disk/by-uuid/d3b5b724-a57a-49a5-ad1d-13ccf3acc52f Where=/mnt/internet_archive Type=btrfs Options=subvol=@internet_archive,compress=zstd:1 [Install] WantedBy=multi-user.target #+END_SRC - ~DefaultDependencies=yes~ : The mount unit automatically acquires ~Before=umount.target~ and ~Conflicts=umount.target~. Local filesystems automatically gain ~After=local-fs-pre.target~ and ~Before=local-fs.target~. Network mounts, such as NFS, automatically acquire ~After=remote-fs-pre.target network.target network-online.target~ and ~Before=remote-fs.target~. - ~Options=subvol=@internet_archive,compress=zstd:1~ : Use the subvolume ~@internet_archive~ and use zstd compression level 1. #+BEGIN_QUOTE Note that the name of the unit file, e.g. ~mnt-internet_archive.mount~, must correspond to the ~Where=/mnt/internet_archive~ directive, such that the filesystem path separator / in the ~Where~ directive is replaced by an en dash in the unit file name. #+END_QUOTE Reload the daemons and enable the mount unit. #+BEGIN_SRC shell sudo systemctl daemon-reload sudo systemctl enable --now mnt-internet_archive.mount #+END_SRC ** Setup encrypted external drive for backups *** Prepare the external drive #+begin_src shell sudo cryptsetup --type luks2 -y -v luksFormat /dev/sda1 sudo cryptsetup -v luksOpen /dev/sda1 cryptbackup sudo mkfs.btrfs /dev/mapper/cryptbackup sudo mkdir /srv/backup sudo mount -o noatime,compress=zstd:1 /dev/mapper/cryptbackup /srv/backup sudo restorecon -Rv /srv/backup #+end_src *** Setup ~/etc/crypttab~ #+begin_src shell sudo blkid -s UUID -o value /dev/sda1 | sudo tee -a /etc/crypttab #+end_src Add the following line to ~/etc/crypttab~: #+begin_src shell cryptbackup UUID= none discard #+end_src *** Setup ~/etc/fstab~ #+begin_src shell sudo blkid -s UUID -o value /dev/mapper/cryptbackup | sudo tee -a /etc/fstab #+end_src Add the following line to ~/etc/fstab~: #+begin_src shell UUID= /srv/backup btrfs compress=zstd:1,nofail 0 0 #+end_src Reload the daemons: #+begin_src shell sudo systemctl daemon-reload #+end_src Mount the filesystems: #+begin_src shell sudo mount -av #+end_src *** btrfs-backup script #+begin_src bash #!/usr/bin/env bash LOGFILE="/var/log/btrfs-backup.log" SNAP_DATE=$(date '+%Y-%m-%d_%H%M%S') # Check if device is mounted if ! grep "/srv/backup" /etc/mtab >/dev/null; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup device is not mounted." | tee -a "$LOGFILE" notify-send -i computer-fail "Backup device is not mounted" exit 1 fi create_snapshot() { if ! btrfs subvolume snapshot -r "$1" "${1}/.snapshots/$2-$SNAP_DATE" >/dev/null; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error creating snapshot of $1" | tee -a "$LOGFILE" notify-send -i computer-fail "Error creating snapshot of $1" exit 1 else echo "[$(date '+%Y-%m-%d %H:%M:%S')] Create snapshot of $1: OK" | tee -a "$LOGFILE" fi } send_snapshot() { mkdir -p "/srv/backup/$SNAP_DATE" if ! btrfs send -q "${1}/.snapshots/$2-$SNAP_DATE" | btrfs receive -q "/srv/backup/$SNAP_DATE"; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error sending snapshot of $1 to /srv/backup" | tee -a "$LOGFILE" notify-send -i computer-fail "Error sending snapshot of $1 to /srv/backup" exit 1 else echo "[$(date '+%Y-%m-%d %H:%M:%S')] Send snapshot of $1 to /srv/backup: OK" | tee -a "$LOGFILE" fi } # Create root and home snapshots create_snapshot "/" "root" create_snapshot "/home" "home" # Send root and home snapshots send_snapshot "/" "root" send_snapshot "/home" "home" #+end_src Move/copy the script to ~/etc/cron.daily/btrfs-backup~.