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, par catégorie :

<racine>/<hôte>/system # catégorie "system" (/ moins les exclusions)
<racine>/<hôte>/srv/nfs # catégorie "nfs" (/srv/nfs/<...>)
<racine>/<hôte>/srv/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.

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 recette idempotente crée les secrets manquants (jamais d’écrasement) :

Fenêtre de terminal
just passwd-restic

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, srv/nfs, srv/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).