Modifications pour le document Sauvegarde
Modifié par john le 2026/10/03 20:01
Résumé
-
Propriétés de la Page (1 modifications, 0 ajouts, 0 suppressions)
Détails
- Propriétés de la Page
-
- Contenu
-
... ... @@ -14,20 +14,109 @@ 14 14 Chaque exécution : 15 15 16 16 * exporte toutes les bases en SQL dans ##<APPDATA>/dumps## ; 17 -* sauvegarde les données des conteneurs, la bibliothèque Immich et le contenu de Joplin, en excluant les fichiers bruts des bases ; 17 +* attend la fin de la sauvegarde Borg de [[Nextcloud>>Wiki Batcave John.Infrastructure.ServeurPrincipal.Nextcloud.WebHome]] AIO (planifiée à 3 h 00), au plus une heure ; 18 +* sauvegarde les données des conteneurs, la bibliothèque Immich, le contenu de Joplin et le dépôt Borg de Nextcloud AIO, en excluant les fichiers bruts des bases et les données brutes de Nextcloud ; 18 18 * supprime les instantanés de plus de 30 jours. 19 19 20 20 {{info}} 21 21 Les fichiers bruts d'une base en fonctionnement ne sont pas fiables pour une restauration. Ce sont les dumps SQL qui font foi. 23 + 24 +Nextcloud AIO fait exception : il n'y a pas de dump, sa base, ses fichiers et sa configuration sont dans son propre dépôt Borg, cohérent car produit conteneurs arrêtés. Plakar copie ce dépôt tel quel, d'où l'attente de la fin de la sauvegarde Borg : copier un dépôt en cours d'écriture donnerait une copie incohérente. 22 22 {{/info}} 23 23 24 -== Script ==27 +== Mise en place du dépôt == 25 25 29 +=== Sur le Raspberry Pi (dépôt) === 30 + 31 +Utilisateur dédié, sans shell : 32 + 26 26 {{code language="bash"}} 27 -#!/bin/bash 34 +sudo useradd -m -d /srv/plakar -s /usr/sbin/nologin plakar 35 +sudo mkdir -p <CHEMIN_DEPOT> 36 +sudo chown plakar:plakar <CHEMIN_DEPOT> 37 +sudo install -d -m 700 -o plakar -g plakar /srv/plakar/.ssh 38 +{{/code}} 39 + 40 +Limitation au SFTP, dans ##/etc/ssh/sshd_config.d/plakar.conf## : 41 + 42 +{{code}} 43 +Match User plakar 44 + ForceCommand internal-sftp 45 + AllowTcpForwarding no 46 + X11Forwarding no 47 +{{/code}} 48 + 49 +{{code language="bash"}} 50 +sudo systemctl reload ssh 51 +{{/code}} 52 + 53 +Même en cas de vol de la clé, elle ne donne ni shell ni tunnel : seulement un accès SFTP. 54 + 55 +=== Sur le serveur principal (source) === 56 + 57 +Clé SSH dédiée, sans phrase de passe puisqu'elle sert à la tâche cron : 58 + 59 +{{code language="bash"}} 60 +sudo ssh-keygen -t ed25519 -f /root/.ssh/plakar_matrix -N "" 61 +{{/code}} 62 + 63 +Contenu de ##/root/.ssh/plakar_matrix.pub## à copier dans ##/srv/plakar/.ssh/authorized_keys## sur le Pi (propriétaire ##plakar##, droits ##600##). 64 + 65 +##/root/.ssh/config## : 66 + 67 +{{code}} 68 +Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com 69 + 70 +Host <HOTE_DEPOT> 71 + User plakar 72 + IdentityFile /root/.ssh/plakar_matrix 73 +{{/code}} 74 + 75 +La ligne ##Ciphers## limite, pour toutes les connexions SSH de root, les algorithmes de chiffrement à des variantes modernes. 76 + 77 +Première connexion, pour valider l'empreinte du Pi (sinon la tâche cron échouera) : 78 + 79 +{{code language="bash"}} 80 +sudo sftp <HOTE_DEPOT> 81 +{{/code}} 82 + 83 +Phrase secrète du dépôt et création : 84 + 85 +{{code language="bash"}} 86 +sudo sh -c 'umask 077; openssl rand -base64 12 > /root/.plakar-pass' 87 +sudo plakar -keyfile /root/.plakar-pass at "sftp://plakar@<HOTE_DEPOT>:<CHEMIN_DEPOT>" create 88 +{{/code}} 89 + 90 +{{warning}} 91 +Le dépôt est chiffré avec cette phrase secrète. Sans elle, les sauvegardes sont illisibles, même pour leur propriétaire : en conserver une copie dans le gestionnaire de mots de passe, jamais uniquement sur le serveur. 92 +{{/warning}} 93 + 94 +== Restaurer si le serveur principal est perdu == 95 + 96 +Le dépôt peut s'ouvrir directement sur le Raspberry Pi, où Plakar est aussi installé, avec la phrase secrète récupérée dans le gestionnaire de mots de passe : 97 + 98 +{{code language="bash"}} 99 +sudo plakar at <CHEMIN_DEPOT> ls 100 +sudo plakar at <CHEMIN_DEPOT> restore -to /tmp/restore <ID_INSTANTANE> 101 +{{/code}} 102 + 103 +Plakar demande alors la phrase secrète de façon interactive. 104 + 105 +== Script == 106 + 107 +{{code language="bash"}}#!/bin/bash 28 28 set -euo pipefail 29 -umask 077 # Ajout : dumps lisibles par root seul109 +umask 077 30 30 111 +# Alertes Telegram 112 +. /root/.backup-telegram 113 +notifier() { 114 + curl -fsS -m 10 "https://api.telegram.org/bot$TG_TOKEN/sendMessage" \ 115 + -d chat_id="$TG_CHAT" --data-urlencode text="$1" >/dev/null || true 116 +} 117 +attention() { echo "ATTENTION: $1" >&2; notifier "⚠️ Sauvegarde : $1"; } 118 +trap 'notifier "❌ Sauvegarde interrompue à la ligne $LINENO"' ERR 119 + 31 31 REPO="sftp://<UTILISATEUR>@<HOTE_DEPOT>:<CHEMIN_DEPOT>" 32 32 KEYFILE="<FICHIER_PHRASE_SECRETE>" 33 33 DUMPS="<APPDATA>/dumps" ... ... @@ -39,34 +39,43 @@ 39 39 > "$DUMPS/$c.sql" 2>/dev/null \ 40 40 || docker exec "$c" sh -c 'exec mariadb-dump -uroot -p"${MYSQL_ROOT_PASSWORD:-$MARIADB_ROOT_PASSWORD}" --all-databases' \ 41 41 > "$DUMPS/$c.sql" 2>/dev/null \ 42 - || e cho "ATTENTION:dump $c échoué">&2131 + || attention "dump $c échoué" 43 43 done 44 44 45 -# Nextcloud : dump via l'utilisateur applicatif 46 -docker exec "$(docker ps -q -f name=nextcloud_db)" sh -c 'exec mariadb-dump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' \ 47 - > "$DUMPS/nextcloud.sql" 2>/dev/null \ 48 - || echo "ATTENTION: dump nextcloud échoué" >&2 49 - 50 50 # Dumps PostgreSQL 51 -for c in joplin-db flus-db wallabag-db immich_postgres vikunja-db jellystat-db n8n-postgres dawarich_db; do # Ajout : dawarich_db135 +for c in joplin-db flus-db wallabag-db immich_postgres vikunja-db jellystat-db n8n-postgres dawarich_db; do 52 52 docker exec "$c" sh -c 'exec pg_dumpall -U "$POSTGRES_USER"' \ 53 53 > "$DUMPS/$c.sql" 2>/dev/null \ 54 - || e cho "ATTENTION:dump $c échoué">&2138 + || attention "dump $c échoué" 55 55 done 56 56 57 -# Sauvegarde, sans core dumps, binlogs ni fichiers bruts des bases 141 +# Attente de la fin de la sauvegarde Borg d'AIO (planifiée à 3h00) 142 +attente=0 143 +while docker ps --format '{{.Names}}' | grep -qx nextcloud-aio-borgbackup; do 144 + if [ "$attente" -ge 3600 ]; then 145 + attention "Borg AIO encore en cours après 1 h : dépôt Borg possiblement incohérent" 146 + break 147 + fi 148 + sleep 60 149 + attente=$((attente + 60)) 150 +done 151 + 152 +# Backup avec exclusions : core dumps, binlogs, fichiers bruts des bases 153 +# et données brutes de Nextcloud AIO (déjà dans le dépôt Borg, de façon cohérente) 58 58 plakar --concurrency 2 -keyfile "$KEYFILE" at "$REPO" backup \ 59 59 -ignore "**/joplin-app/core.*" \ 60 - -ignore "**/Nextcloud/ DB/**" \156 + -ignore "**/Nextcloud-AIO/data/**" \ 61 61 -ignore "**/log/mysql/**" \ 62 62 -ignore "**/xwiki/mariadb/**" \ 63 63 -ignore "**/store.bak.*/**" \ 64 64 <APPDATA> \ 65 - <BIBLIOTHEQUE_IMMICH>\ 66 - <CONTENU_JOPLIN> 161 + <BIBLIOTHEQUE_IMMICH> \ 162 + <CONTENU_JOPLIN> \ 163 + <DEPOT_BORG_AIO> 67 67 68 68 # Rétention : 30 jours glissants 69 69 plakar -keyfile "$KEYFILE" at "$REPO" rm -before 30d -apply 167 +notifier "✅ Sauvegarde terminée" 70 70 {{/code}} 71 71 72 72 Tâche cron, ##/etc/cron.d/backup-plakar## : ... ... @@ -75,6 +75,29 @@ 75 75 30 3 * * * root /root/backup-plakar.sh >> /var/log/backup-plakar.log 2>&1 76 76 {{/code}} 77 77 176 +== Alertes == 177 + 178 +Le script envoie un message Telegram à chaque exécution : 179 + 180 +|=Message|=Signification 181 +|✅ Sauvegarde terminée|Tout s'est bien passé 182 +|⚠️ Sauvegarde : dump … échoué|Un dump de base a échoué, la sauvegarde a continué sans lui 183 +|⚠️ Sauvegarde : Borg AIO encore en cours après 1 h …|La sauvegarde Borg de Nextcloud n'était pas finie : la copie du dépôt Borg de cette nuit peut être incohérente, celle des nuits précédentes reste utilisable 184 +|❌ Sauvegarde interrompue à la ligne …|Erreur bloquante, la sauvegarde n'a pas eu lieu 185 + 186 +Si aucun message n'arrive un matin, le script n'a pas démarré (serveur éteint, tâche cron cassée). 187 + 188 +Jeton du bot et identifiant du groupe dans ##/root/.backup-telegram##, lisible par root seul : 189 + 190 +{{code language="bash"}} 191 +TG_TOKEN="<JETON_BOT>" 192 +TG_CHAT="<ID_GROUPE>" 193 +{{/code}} 194 + 195 +{{warning}} 196 +Dans le script, chaque ligne continuée doit se terminer par ##\## sans rien après, pas même un espace. Une barre oblique inverse suivie d'un espace ne continue plus la ligne : c'est ce qui a interrompu plusieurs sauvegardes en septembre 2026. Contrôle après toute modification : ##sudo bash -n /root/backup-plakar.sh##, et ##cat -A## pour voir les caractères invisibles en fin de ligne. 197 +{{/warning}} 198 + 78 78 == Ajouter une base == 79 79 80 80 Ajouter le nom du conteneur dans la boucle MariaDB ou PostgreSQL du script, puis exclure ses fichiers bruts avec un ##-ignore## s'ils se trouvent dans ##<APPDATA>##. ... ... @@ -107,6 +107,8 @@ 107 107 docker exec -i <CONTENEUR> sh -c 'exec psql -U "$POSTGRES_USER" -d postgres' < /tmp/restore/<CHEMIN>/dumps/<CONTENEUR>.sql 108 108 {{/code}} 109 109 231 +Restaurer Nextcloud AIO : restaurer le dossier ##<DEPOT_BORG_AIO>## sur l'hôte, déployer le mastercontainer sur une installation neuve, puis choisir la restauration dans l'interface AIO (chemin du dépôt, mot de passe Borg, archive). Voir la page [[Nextcloud>>Wiki Batcave John.Infrastructure.ServeurPrincipal.Nextcloud.WebHome]]. 232 + 110 110 {{warning}} 111 111 Une sauvegarde qui n'a jamais été restaurée n'est pas une sauvegarde vérifiée. Faire un essai de restauration de temps en temps, dans un dossier temporaire. 112 112 {{/warning}} ... ... @@ -118,3 +118,4 @@ 118 118 |Avertissements VFS|Cache local incohérent|Vider ##~~/.cache/plakar## de root 119 119 |Transfert coupé (EOF SFTP) sur de gros fichiers|Lien Wi-Fi du dépôt instable|Économie d'énergie Wi-Fi désactivée sur le Pi ; passer à ##~-~-concurrency 1## pour une première sauvegarde volumineuse 120 120 |Déconnexion du SSD pendant la sauvegarde|Pont USB en mode UAS|Voir la configuration SSD sur la page [[Raspberry Pi>>Wiki Batcave John.Infrastructure.RaspberryPi.WebHome]] 244 +