Aller au contenu

Sauvegardes du réseau (restic)

Le module darkone.service.restic sauvegarde les hôtes du parc avec restic 🡕 : chaque hôte (client) pousse ses données vers un dépôt, local ou distant via un serveur REST de zone.

Deux rôles, un seul module :

  • Serveur REST : un hôte qui déclare le service restic dans config.yaml. Il stocke les dépôts de tous les hôtes et écoute sur le réseau interne.
  • Client : tout hôte avec enable = true qui déclare des targets (destinations de sauvegarde).
Diagram

Disposition d’un dépôt : un dépôt par catégorie, nommé d’après elle.

<racine>/<hôte>/system # catégorie "system" (/ moins les exclusions)
<racine>/<hôte>/nfs # catégorie "nfs" (/srv/nfs/<...>)
<racine>/<hôte>/medias # catégorie "medias" (/srv/medias/<...>)
  1. Dans etc/config.yaml, ajouter le service restic à l’hôte serveur :

    services:
    restic:
  2. Brancher le disque de sauvegarde et le monter sur /mnt/backup dans la configuration de l’hôte (usr/machines/<hôte>/), avec l’option nofail :

    fileSystems."/mnt/backup" = {
    device = "/dev/disk/by-uuid/<uuid>";
    fsType = "ext4";
    options = [ "nofail" ];
    };
    # Le serveur REST ne démarre qu'une fois le disque monté.
    systemd.services.restic-rest-server = {
    requires = [ "mnt-backup.mount" ];
    after = [ "mnt-backup.mount" ];
    };
  3. Le dépôt est stocké sous serverDataDir (défaut /mnt/backup/restic). Le pare-feu ouvre le port REST sur l’interface interne automatiquement.

  4. Si des clients d’autres zones doivent y accéder par le tailnet, ajouter listenAll : le serveur n’écoute par défaut que sur l’adresse LAN de l’hôte, invisible depuis le VPN.

    darkone.service.restic = {
    enable = true;
    enableServer = true;
    listenAll = true;
    };

Déclarer une ou plusieurs targets dans la configuration de l’hôte :

darkone.service.restic = {
enable = true;
targets = [
{
# Dépôt distant via le serveur REST de la zone.
root = "rest:http://restic.home.example.net:8888";
zone = "home";
categories = [ "system" "nfs" ];
}
];
};

Champs d’un target :

ChampRôle
nameIdentifiant (défaut main), suffixe des jobs/units.
rootChemin local ou URL rest://.
zoneZone qui choisit la passphrase restic-password-<zone>.
categoriesDonnées sauvegardées : system, nfs, medias.

Une seconde target vers le serveur REST d’une autre zone donne le « 1 » de la règle 3-2-1. Deux précautions propres au hors-site.

Adresser le serveur par son IP tailnet, jamais par son nom de zone :

{
name = "offsite";
root = "rest:http://100.64.0.20:8888";
zone = "home";
categories = [ "system" ];
}

Un nom comme restic.<zone-distante>.example.net n’est résolu que par la passerelle de cette zone. Si le site distant tombe, le résolveur tombe avec lui et la panne se présente comme une erreur de résolution de noms, ce qui égare le diagnostic. L’IP tailnet supprime cette indirection, ainsi que la dépendance à la route de sous-réseau du site distant. Elle exige listenAll côté serveur (voir plus haut).

La génération des secrets internes est idempotente : elle crée ce qui manque, jamais d’écrasement.

Fenêtre de terminal
just configure-admin-host

Elle génère, dans usr/secrets/secrets.yaml :

  • une passphrase restic-password-<zone> par zone ;
  • un credential restic/<hôte>/rest-password par hôte du parc.

Le module crée un service systemd par couple cible × catégorie, nommé restic-backups-<catégorie>-<nom> (le <nom> vient du champ name du target, main par défaut). Exemples : restic-backups-system-main, restic-backups-nfs-main.

  1. Lister les services de sauvegarde présents sur l’hôte :

    Fenêtre de terminal
    systemctl list-units 'restic-backups-*'
  2. Déclencher une sauvegarde immédiate, sans attendre le timer :

    Fenêtre de terminal
    sudo systemctl start restic-backups-system-main.service
  3. Suivre son déroulement en direct :

    Fenêtre de terminal
    journalctl -fu restic-backups-system-main.service

Le serveur REST tourne en dépôts privés (privateRepos = true) : chaque hôte n’accède qu’au dépôt dont le chemin commence par son propre nom d’hôte. Le module aligne automatiquement le compte REST (<hôte>) sur le préfixe du dépôt (<racine>/<hôte>/...), donc l’isolation est permanente → aucun réglage à activer. Une tentative d’accès au dépôt d’un autre hôte renvoie une erreur 403.

Sur l’hôte concerné, les secrets sont déjà en place. Lister puis restaurer :

Fenêtre de terminal
# Adapter la zone du dépôt (et la catégorie : system, nfs, medias).
ZONE=home
# Variables d'accès REST (générées par sops) et passphrase de dépôt.
set -a; . /run/secrets/rendered/restic-rest-env; set +a
export RESTIC_PASSWORD_FILE=/run/secrets/restic-password-$ZONE
export RESTIC_REPOSITORY=rest:http://restic.$ZONE.example.net:8888/$(hostname)/system
restic snapshots
restic restore latest --target /restore
  1. Sur un serveur, un compte par hôte du parc dans le fichier htpasswd :

    Fenêtre de terminal
    sudo cut -d: -f1 /run/restic-rest/htpasswd
  2. Sur un client, lancer une sauvegarde manuelle (voir plus haut) et vérifier qu’elle se termine sans erreur.

  3. Isolation : depuis un client, l’accès au dépôt d’un autre hôte doit être refusé (erreur 401/403).