Journal Une histoire de backup qui se termine bien

Posté par  . Licence CC By‑SA.
34
17
juil.
2024

Contexte

Depuis plus de 20 ans j'héberge moi-même mes emails. Avec les évolutions des règles anti-spams (réputation des adresses IP des FAI) et des contraintes des abonnement internet grand publique (port 25 bloqué), cet hébergement est passé de mon salon à un petit serveur dédié dans un datacenter. J'ai commencé avec une solution à base d'une Debian, puis j'ai séparé les services dans des containeurs LXC pour finalement migrer vers une solution intégrée par Docker compose : mailcow.

Tout cela ronronnait tranquillement depuis quelques années, je me contentais de faire des updates du système et des containers. Lors d'une de ces mises à jour, j'ai du redémarrer la machine pour passer sur un nouveau noyau (mise à jour de sécurité). Et là patatras, la machine ne redémarre pas. Un ticket chez l'hébergeur m'apprend que la machine est morte et qu'ils ne peuvent pas récupérer le disque dur (la topologie du rack empêche de retirer un disque sans éteindre toutes les machines du rack; oui, c'était du low-cost…). Seule solution : réinstallation complète sur un nouveau serveur avec récupération des données de sauvegarde.

Réinstallation

À ma grande surprise, tout a très bien fonctionné en suivant ce plan sur une Debian :

  • Suppression du paquet bind9 (mailcow installe son propre résolveur)
  • Installation des paquets git, restic, docker.io, curl
  • Installation de docker-compose
  • Copie de la configuration de restic (/root/backup/restic.sh)
  • Récupération du dernier snapshot restic : restic restore abcdef01 --target /recovery
  • Il ne reste plus qu'à déplacer les deux répertoires restaurés vers /var/lib/docker/volumes/ et /opt/mailcow-dockerized et à lancer les containers avec docker-compose.

Coté DNS, j'ai changé les enregistrements DNS A et AAAA du serveur défini en MX. Après le temps de propagation et l'expiration du ttl, j'ai commencé à recevoir les mails en attente sur les serveurs de mes correspondants.

Les détails de la sauvegarde

Voici comment la sauvegarde des données est faite. J'utilise restic avec comme dépôt, un stockage dans les nuages de type S3 mais pas chez Amazon. Toutes les informations sont contenues dans le fichier de configuration restic.sh :

export AWS_ACCESS_KEY_ID=XXXXXX
export AWS_SECRET_ACCESS_KEY=YYYYYY
export AWS_DEFAULT_REGION=aa-bbb
export RESTIC_REPOSITORY=s3:www.example.com/s3
export RESTIC_PASSWORD=ZZZZZ

Ce fichier de configuration est critique est doit être sauvegardé et protégé. Il est en fait stocké dans mon gestionnaire de mots de passe.

Le script de sauvegarde est quant à lui très simple, il se contente de sauvegarder les volumes docker et les fichiers de mailcow :

#!/bin/sh
set -e

. ./restic.sh

restic backup /opt/mailcow-dockerized /var/lib/docker/volumes/

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 5

Pour s'assurer que la tache est lancée régulièrement, il faut créer les fichiers suivants (désolé, c'est du systemd):

/etc/systemd/system/backup-restic.service :

[Unit]
Description=Restic backup

[Service]
User=root
Group=root
Type=oneshot
WorkingDirectory=/root/backup
ExecStart=/root/backup/do_backup.sh

/etc/systemd/system/backup-restic.timer :

[Unit]
Description=Backup restic

[Timer]
OnCalendar=*-*-* 3:30:00

[Install]
WantedBy=timers.target

Et on n'oublie pas d'activer cette tâche : systemctl daemon-reload && systemctl enable backup-restic.timer && systemctl start backup-restic.timer

Conclusions

J'ai pu valider pour la première fois mon PRA en situation réelle. Le système était fonctionnel en moins de 24 heures (la panne est survenue à 23h30). Je ne pense pas avoir perdu beaucoup d'emails (mais je les avait en fait déjà lus) entre la dernière sauvegarde à 3h30 et la panne à 23h30. Je suis aussi assez content d'avoir automatisé le backup quelques semaines avant (je le lançais à la main quand j'y pensais…).

Au niveau de ce qui aurait pu être amélioré :

  • Mettre à jour les enregistrements DNS beaucoup plus tôt pour pouvoir récupérer un fonctionnement nominal plus rapidement.
  • Penser à lancer un backup manuel avant chaque opération à risque (redémarrage, mise à jour…)
  • Avoir testé au moins une fois la procédure de reconstruction du serveur
  • Mieux documenter la configuration IPv6 du serveur pour la rendre compatible avec mailcow (ajout de net.ipv6.conf.eno1.accept_ra=2)
  • Mettre en place un backup des mails uniquement par IMAP (ceintures et bretelles)

J'espère que ce retour d'expérience pourra être utile à quelqu'un. Restic est vraiment simple à utiliser que ce soit pour la sauvegarde ou la restauration. Vu les coûts du stockage dans les nuages, il ne faut pas hésiter à mettre cela en place. Mailcow est aussi très simple à installer et déplacer le serveur s'est avéré enfantin.

  • # Amélioration

    Posté par  . Évalué à 6.

    Super retour d'experience.

    Si je peux me permettre une remarque qui se veut constructive.

    restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 5

    Si quelqu'un prends le contrôle de ta machine d'une manière ou d'une autre tu n'aura plus de sauvegarde.

    Personnellement je fais en sorte le client ne peux pas faire autre chose que pousser des nouvelles sauvegardes et c'est le serveur qui gère la rétention (mais j'ai un truc maison à coup de rsync).

    Pour le risque de véroler les sauvegardes j'ai un monitoring de la taille des différentiels (qui me sert aussi pour le suivi de l'espace que ça prends) et de temps en temps de flag à la main un full backup comme non supprimable.

    https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: Amélioration

      Posté par  (Mastodon) . Évalué à 4. Dernière modification le 18 juillet 2024 à 14:17.

      Oui ce genre de truc c'est bon uniquement si du côté serveur tu fais des snapshots du système de fichiers non accessibles en écriture depuis le client.

      Et tu ne veux pas non plus que le client puisse avoir accès à la gestion du filesystem côté serveur (via une clé ssh ou autre).

    • [^] # Re: Amélioration

      Posté par  . Évalué à 3.

      Bonne remarque. C'est quelque chose que j'avais fait dans mon précédant système de sauvegarde. J'utilisais Burp qui permet d'avoir un client qui ne peut que pousser des sauvegardes sans pouvoir les effacer. Le nettoyage est effectué côté serveur par une logique définie à l'avance. J'aimais bien cette solution mais j'avais eu des problèmes avec incompatibilité de versions entre clients et serveur. Je voulais aussi m'affranchir de la gestion du stockage de sauvegarde pour lequel je pense que les solutions "cloud" sont plus intéressantes : abordable, sans risque de sécurité (sauvegardes chiffrées), sans besoin de maintenance…

      Je pense que restic sur du stockage S3 ne permet pas ce genre de séparation.

      • [^] # Re: Amélioration

        Posté par  . Évalué à 2.

        On trouve plusieurs conversation au sujet de S3 Object Lock pour restic, rclone, duplicity… Par exemple ici : https://forum.restic.net/t/ransomware-protection/7098

        À ce jour aucune de ces trois solutions n'est compatible, mais des travaux sont en cours dans cette direction pour rclone, par exemple.

        Une fois que c'est en place, tu as bien la possibilité d'avoir le nettoyage géré côté serveur, avec le client en écriture seule.

      • [^] # Re: Amélioration

        Posté par  (site web personnel) . Évalué à 2.

        Question probablement naïve : pourquoi donner au client le pouvoir de pousser des sauvegardes. Ne serait-ce pas au moins aussi sûr de charger le serveur d'aller se connecter sur le client ?

        « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

        • [^] # Re: Amélioration

          Posté par  . Évalué à 4.

          Oui c'est possible mais il faut faire attention car on ne veut pas que la machine de backup compromise puisse attaquer toutes les machines qu'elle peut contacter. Une manière simple de le faire avec rsync est de n'autoriser dans .ssh/authorized_key que la commande exacte utilisée pour faire le backup. C'est un peu plus contraignant car rajouter un dossier à sauvegarder implique de changer la commande sur les 2 machines.

          • [^] # Re: Amélioration

            Posté par  (site web personnel) . Évalué à 3. Dernière modification le 19 juillet 2024 à 12:17.

            Merci. J'y regarderais à l'occasion car ma question, était bien évidemment la suite de ma mauvaise pratique : ma machine de sauvegarde se connecte sans mot de passe sur toutes ses cibles avec les droits de lecture sur tout le système. Ce n'est donc pas idéalement résilient.

            PS : la possibilité de préciser la commande dans "authorized_keys" me semble très intéressante ! Merci encore.

            « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

        • [^] # Re: Amélioration

          Posté par  (Mastodon) . Évalué à 6.

          La solution serveur --> client marche bien si le client est toujours sur le même réseau local. Aussi si le client n'est pas allumé constamment ni à des heures fixes, ton serveur se retrouve à devoir tenter des sauvegardes un peu tout le temps. Ça fait vite des logs très verbeux.

          Du coup c'est souvent plus facile pour l'utilisateur de mettre en place une solution "serverless"[1] et d'avoir les backups initiés via le client. Ça a ses défauts et contraintes mentionnées plus haut. Si tes clients sont presque tout le temps sur le réseau local, ça vaut le coup d'investir le temps pour mettre en place une gestion depuis un serveur. Si c'est un laptop qui est beaucoup en voyage, ça implique d'avoir une connection VPN est un peu constante sur le laptop.

          C'est pour cela qu'une solution on va dire hybride d'initier les sauvegardes depuis le client, mais de gérer la rétention et les copies multiples en lecture seule par le serveur/stockage en ligne peut être raisonnable.

          [1] dans le sens où il n'y a pas de logiciel de backup serveur, ce n'est qu'un stockage accessible via un protocole réseau

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.