đŸ—ƒïž Sauvegarde au branchement avec Systemd et BTRFS

| ~ 8 mins | 1631 mots

Introduction

Dans l’article sur la sauvegarde automatique dĂšs le branchement pour mes photos, j’indiquais comment j’avais rĂ©ussi Ă  gĂ©rer des sauvegardes automatiques au branchement pour mes photos. Cela est trĂšs bien, mais pourquoi pas ne pas Ă©tendre la mĂ©canique pour la sauvegarde de fichiers ? La mĂ©canique de base s’avĂšre trĂšs proche, mais complĂ©tĂ© pas les fonctionnalitĂ©s du systĂšme de fichier btrfs, cela donne un systĂšme de sauvegarde trĂšs flexible.

Contrairement aux sauvegardes de photos qui allait de la carte SD au NAS, l’idĂ©e lĂ  est inverse. On veut pouvoir connecter un disque et le systĂšme va Ă©crire de lui-mĂȘme sur ce disque la nouvelle sauvegarde.

Principe

Enregistrement automatique de sauvegarde d’un disque dur

Le principe est assez simple :

Ajoutons un peu de BTRFS par-dessus

Le systĂšme de fichiers btrfs par ses fonctionnalitĂ©s : gestion de sous-volume et instantanĂ© (snapshot), nous permet de figer l’image d’un sous-volume Ă  un instant T directement sans copie. Cette image peut ĂȘtre en lecture seule. C’est un instantanĂ©.

L’intĂ©rĂȘt ? Il est possible de stocker nos donnĂ©es Ă  sauvegarder dans un sous-volume btrfs, qui sera alors sauvegardĂ© sous la forme d’un instantanĂ© en lecture seule qu’on pourra ainsi transmettre sur un autre disque sans risque de corruption de donnĂ©es liĂ© Ă  des modifications durant la sauvegarde.

Les instantanĂ©s permettent aussi localement un mĂ©canisme de sauvegarde simple permettant de “revenir dans le temps”. L’autre avantage des instantanĂ©s btrfs est qu’ils permettent d’utiliser le mĂ©canisme send-receive qui permet de copier efficacement des sous-volumes (et donc des instantanĂ©s) d’un volume btrfs Ă  un autre, potentiellement d’une façon incrĂ©mentale en utilisant les sous-volumes dĂ©jĂ  transmis.

Donc le principe est le suivant :

Les limitations de la mĂ©canique sont les suivantes :

La pratique

PrĂ©requis : utiliser btrfs et les sous-volumes

Pour pouvoir utiliser la fonctionnalité, il faut que le disque à sauvegarder utilise btrfs, et il est conseillé de créer des sous-volumes pour définir les différents traitements.

ConsidĂ©rons que l’on veut sauvegarder la partition /home seulement, il faut donc un sous-volume sur home :

Imaginons qu’on a cette arborescence :

/
├── srv : point de montage direct du volume btrfs (voir fstab)
│   └── @home : emplacement du sous-volume `@home` dans le sous-volume par dĂ©fault de btrfs.
└─ home : On va monter @home ici (voir fstab)

On aurait ainsi des paramĂštres de montage dans le fichier /etc/fstab similaire Ă  ça :

UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /srv auto defaults 0 0
UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /home auto subvol=@home 0 0

Vous noterez que l’UUID est le mĂȘme, car on pointe littĂ©ralement sur la mĂȘme partition.

Quant au sous-volume @home, il a pu ĂȘtre crĂ©Ă© tout simplement avec cette commande (volume /srv montĂ©)

sudo btrfs subvolume create /srv/@home

Pour ce qui est des instantanés, nous les placerons dans le dossier snapshots à la raçine de /srv et les sauvegardes seront dans le dossier snapshots à la racine de /mnt/backup.

Je ne rentrerai pas plus dans le détail de la mécanique de btrfs, il existe une littérature importante à ce sujet.

Créer une rÚgle Udev

Comme prĂ©cĂ©demment, il nous faut passer par udev pour gĂ©rer l’aspect montage automatique.

99-automount_backup_drive.rules

# Automount usb backup drive on insertion
ACTION!="remove", SUBSYSTEM=="block", ENV{ID_PART_ENTRY_NAME}=="backup", ENV{SYSTEMD_WANTS}+="backup.service"

Ce qui signifie :

📝 Note : l’action est sur les pĂ©riphĂ©riques de type block, ce qui signifie que c’est agnostique du moyen de communication utilisĂ© : USB, SATA, NVME, RĂ©seau. Du moment que le systĂšme voit une partition labellisĂ©e backup, il tentera de la monter.

Point de montage

Comme précédemment, il nous faut un fichier .mount.

/etc/systemd/system/mnt-backup.mount

[Unit]
Description=Mount Backup
BindsTo=btrbk_resume.service

[Mount]
What=/dev/disk/by-partlabel/backup
Where=/mnt/backup
ReadWriteOnly=true
Type=btrfs

Avec ce point de montage, systemd sait maintenant, qu’en cas d’activation de mnt-backup.mount:

Btrbk

Pour gĂ©rer efficacement la sauvegarde aprĂšs quelques hĂ©sitations et un script perso, j’ai finalement dĂ©cidĂ© d’utiliser btrbk. btrbk est un outil en perl pour gĂ©rer les sauvegarde via btrfs, notamment avec la mĂ©thode “crĂ©ation d’instantanĂ©s puis envois sur disque via btrfs send/receive”.

Il a beaucoup d’avantages :

En bref, il nous simplifie la vie pour utiliser les fonctionnalités de btrfs dans notre cas.

Il faut nĂ©anmoins un peu de temps pour l’apprivoiser les rĂšgles de conservations sont ainsi assez compliquĂ© Ă  comprendre. Je vous laisse chercher dans la documentation.

Dans notre cas simple, on aura donc une configuration de ce style :

transaction_log            /var/log/btrbk.log
# les snapshot du volume src et targets seront placé dans le dossier snapshot à la racine
snapshot_dir               snapshots

# rĂšgle de conservation des snapshots
snapshot_preserve_min   2d
snapshot_preserve       14d

# rĂšgle de conservation des sauvegardes sur le disque de sauvegarde
target_preserve_min     no
target_preserve         20d 10w *m

# on définis ici qu'on fait des snapshot pour le sous volume @home de /srv
# et qu'on les copie en mode send-receive vers /mnt/backup
volume /srv
  target send-receive /mnt/backup
  subvolume @home

On pourrait s’arrĂȘter lĂ  et modifier le systĂšme pour que backup.service lance le btrbk.service du paquet debian et ça fonctionnerait pour la sauvegarde Ă  chaud. Mais mon souhait et d’avoir un snapshot journalier dans tous les cas et Ă©ventuellement une sauvegarde si le disque de sauvegarde est branchĂ©.

Snapshot régulier et sauvegarde si possible

Pour rĂ©aliser cette mĂ©canique d’instantanĂ©s rĂ©guliers en plus de la sauvegarde Ă  chaud, il faut jouer un peu avec systemd.

Btrbk, permet de sĂ©parer la transmission de sauvegarde de la rĂ©alisation de snapshot. Pour ce faire, au lieu de faire btrbk run on peut utiliser btrbk snapshot -pet btrbk resume. Avec quelques override systemd, on peut arriver au bon rĂ©sultat :

# /lib/systemd/system/btrbk.service
[Unit]
Description=btrbk backup
Documentation=man:btrbk(1)

[Service]
Type=oneshot
ExecStart=/usr/sbin/btrbk run

# /etc/systemd/system/btrbk.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/btrbk snapshot -p
# /etc/systemd/system/btrbk_resume.service
[Unit]
After=btrbk.service
# 📝 note: on demande implicitement `mnt-backup.mount`.
RequiresMountsFor=/mnt/backup
RefuseManualStart=true

[Service]
Type=oneshot
# 📝 note: On n'a pas mis de `-p` ici, 
# la rotation des instanées et sauvegardes se fera à la fin de la transmission des sauvegardes.
ExecStart=/usr/sbin/btrbk resume
# /etc/systemd/system/backup.service
[Unit]
After=btrbk.service btrbk_resume.service
Requires=btrbk.service btrbk_resume.service

[Service]
# 📝 Note: Ce service est un peu subtil, car on tire profit des spĂ©cificitĂ©s des services oneshot. 
# Ce service lancera les 2 services btrbk et restera en activating, jusqu'Ă  qu'ils s'arrĂȘtent et donc sera enfin `inactivate`.
# il n'est Ă  ma connaissance pas possible de faire la mĂȘme chose avec des `.target` qui seront en `activate` Ă  la fin du processus.
Type=oneshot
# Fausse commande car c'est obligatoire pour les service
ExecStart=/bin/true
# /lib/systemd/system/btrbk.timer
[Unit]
Description=btrbk daily backup

[Timer]
OnCalendar=daily
AccuracySec=10min
Persistent=true

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/btrbk.timer.d/override.conf
[Timer]
Unit=backup.service

📝 Note : Il ne faut pas oublier d’activer ce service sinon vous n’aurez pas les sauvegardes rĂ©guliĂšres

Récapitulatif Scénario

On à donc les 3 scénarios suivants :

1. Branchement Ă  chaud

2. Sauvegarde réguliÚre

3. Sauvegarde réguliÚre sans disque branché

Conclusion

Btrfs n’est pas si facile Ă  prendre en main, mais les concepts bien compris et Ă  l’aide de systemd, on peut crĂ©er des mĂ©canismes de sauvegardes puissants.