Sauvegarde et restauration
Cette page s’adresse aux administrateurs. Elle explique ce qu’il faut sauvegarder, comment faire une sauvegarde à la main ou automatiquement chaque nuit, comment prouver qu’une sauvegarde peut être restaurée, et comment restaurer une installation ou revenir à la version précédente après une mise à jour ratée.
Une sauvegarde ne vaut quelque chose qu’une fois que vous l’avez restaurée. Prévoyez un test de restauration dès le départ.
Ce qu’il faut sauvegarder
| Quoi | Où | Pourquoi |
|---|---|---|
.env | à côté de docker-compose.yml | Contient SECRET_KEY, qui déchiffre chaque clé de provider stockée, ainsi que le mot de passe de la base de données. Sans lui, une installation restaurée redemande chaque clé de provider. |
| La base de données | volume libris_database (epub-translator_… sur une installation pas encore renommée) | Comptes, séries, livres, traductions, historique, glossaires, mémoire, travaux et réglages. Sauvegardez-la avec pg_dump, pas en copiant le volume. |
| Le volume des livres | volume libris_books, monté sur /data | EPUB d’origine (books/), sources texte et JSON (sources/), exports, résultats d’API livrés et imports en attente. Sans lui, une installation restaurée peut encore exporter du texte, mais pas d’EPUB, d’aperçus ni d’archives de projet. |
| État Codex (facultatif) | volume libris_codex-state | Connexion des providers Codex · compte ChatGPT. Sans lui, reconnectez-vous. |
| OpenViking (facultatif) | votre serveur OpenViking | Ne fait pas partie de Libris ; sauvegardez-le selon sa propre procédure. Libris peut republier sa mémoire à partir de la base de données : après une restauration, Reconstruire réécrit les documents d’un volume que le nettoyage OpenViking a supprimés. |
La base de données et le volume des livres vont ensemble : restaurez toujours les deux à partir de la même sauvegarde.
Pour sauvegarder un seul livre avec tout son travail, exportez-le plutôt comme archive de projet (Exporter › Projet complet (.zip)) et restaurez-le depuis la bibliothèque (Ajouter du contenu › Restaurer une archive Libris). Une série entière — ses volumes, son glossaire, ses identités et leurs liens, sa Series Bible et ses réglages — s’exporte en un seul fichier avec Exporter la série sur la page de la série et se restaure avec Ajouter du contenu › Restaurer une archive Libris › Une série complète (format dans architecture.md (en anglais)). Ni l’une ni l’autre ne remplace une sauvegarde complète : les comptes, les providers, les clés et les glossaires partagés n’y figurent pas.
Sauvegarder à la main
Exécutez ces commandes dans le dossier de Libris. Elles arrêtent l’application web et le worker le temps de la copie, afin que la base de données et les fichiers concordent.
mkdir -p backups && chmod 700 backups
docker compose stop api worker
docker compose exec -T database sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > backups/database.dump
docker compose run --rm --no-deps -T api tar -C /data -czf - . > backups/books.tar.gz
cp .env backups/config.env
chmod 600 backups/*
docker compose up -d --no-build --wait
Copiez le dossier backups sur une autre machine. Une sauvegarde conservée sur le même disque ne survit pas à la perte
de ce disque.
Sur un hôte piloté par le script de déploiement de production (en
anglais), librisctl backup effectue seul le dump de la base de données (sans rien arrêter) et affiche son chemin ; le
volume des livres et la configuration sont couverts par la sauvegarde planifiée ci-dessous.
Sauvegarder chaque nuit
backup/libris-backup fait une sauvegarde vérifiée en gelant l’API et le worker le temps du dump et de l’archive (de quelques secondes à quelques minutes), l’écrit sur un partage monté
depuis une autre machine et supprime les anciennes sauvegardes. Un minuteur systemd l’exécute chaque nuit. Rien n’est
installé automatiquement.
L’installer
En root sur l’hôte Docker, depuis le dossier de l’installation du registre (par défaut /opt/libris) :
install -m 0755 backup/libris-backup backup/libris-restore /usr/local/sbin/
install -m 0644 backup/libris-backup.service backup/libris-backup.timer /etc/systemd/system/
install -m 0600 backup/libris-backup.conf.example /etc/libris-backup.conf
editor /etc/libris-backup.conf
systemctl daemon-reload
-
Montez de façon permanente un partage depuis une autre machine (NFS, SMB, sshfs…), par exemple sur
/mnt/libris-backup, et créez-y un dossier de destination. Root doit pouvoir y écrire, les permissions des fichiers doivent être conservées (les sauvegardes sont créées en0600), et il faut de la place pour autant de sauvegardes que vous en conservez. -
Modifiez
/etc/libris-backup.conf(voir le tableau ci-dessous). DéfinissezLIBRIS_BACKUP_MOUNTPOINTpour que la sauvegarde échoue, au lieu de remplir silencieusement le disque local, quand le partage n’est pas monté. -
Lancez une première sauvegarde et lisez son résultat :
systemctl start libris-backup.service journalctl -u libris-backup.service -n 20 -
Activez l’exécution nocturne (à 03 h 30, avec jusqu’à 20 minutes de délai aléatoire ; une exécution manquée pendant que la machine était éteinte a lieu au démarrage suivant) :
systemctl enable --now libris-backup.timer systemctl list-timers libris-backup.timer -
Surveillez les échecs : vérifiez
systemctl is-failed libris-backup.servicedans votre supervision, ou ajoutez un fichier complémentaire (drop-in)OnFailure=qui appelle votre unité de notification habituelle.
Réglages
| Variable | Défaut | Signification |
|---|---|---|
LIBRIS_BACKUP_DESTINATION | aucun (obligatoire) | Dossier qui reçoit un dossier libris-<UTC timestamp>/ par sauvegarde, par exemple /mnt/libris-backup/libris. |
LIBRIS_BACKUP_MOUNTPOINT | vide | Si elle est définie, la sauvegarde échoue quand ce chemin n’est pas un système de fichiers monté. |
LIBRIS_BACKUP_RETENTION_DAYS | 14 | Les sauvegardes plus anciennes que ce nombre de jours sont supprimées après chaque sauvegarde réussie. |
LIBRIS_BACKUP_PROJECT | valeur renseignée par l’installateur ; sinon $LIBRIS_PRODUCTION_BASE/project, puis volume libris ou epub-translator détecté | Projet Compose de l’installation (le renommer (en anglais) écrit ce fichier). |
LIBRIS_BACKUP_BOOKS_VOLUME | <project>_books | Volume des livres à archiver. |
LIBRIS_BACKUP_FREEZE | true | false n’interrompt plus l’API ni le worker (déconseillé : tout changement de fichier pendant l’exécution fait échouer la sauvegarde). |
LIBRIS_BACKUP_INCLUDE_ENV | false | true copie .env dans chaque sauvegarde sous le nom config.env. Uniquement si la destination peut contenir tous les secrets de l’installation. |
LIBRIS_BACKUP_SECRET_ENV | chemin renseigné par l’installateur du registre ; sinon $LIBRIS_PRODUCTION_BASE/.env, puis l’ancien /opt/epub-translator/.env | Chemin du .env de l’installation, copié quand LIBRIS_BACKUP_INCLUDE_ENV=true. Vérifiez ce chemin avant d’activer la copie des secrets. |
LIBRIS_PRODUCTION_BASE | /opt/libris-production | Emplacement où le script de déploiement de production (en anglais) enregistre la version déployée, inscrite dans backup.info. Sans conséquence s’il est absent. |
Quand .env n’est pas inclus, sauvegardez-le vous-même en lieu sûr : il change rarement.
Contenu d’une sauvegarde
| Fichier | Contenu |
|---|---|
database.dump | pg_dump -Fc de toute la base de données, cohérent, pris pendant que l’API et le worker sont gelés |
books.tar.gz | le volume des livres complet |
books.sha256 | SHA-256 de chaque fichier de books.tar.gz ; libris-restore y compare le volume restauré |
config.env | une copie de .env, seulement avec LIBRIS_BACKUP_INCLUDE_ENV=true |
backup.info | date, projet Compose, volume, image de la base de données et version de Libris déployée |
SHA256SUMS | sommes de contrôle des fichiers ci-dessus |
Le dump et l’archive sont pris à des instants différents, et l’API et le worker ajoutent, remplacent et suppriment
des fichiers (EPUB, sources, couvertures, exports) après avoir validé leurs lignes. Le script exécute donc
docker pause sur les conteneurs api et worker avant le dump et les reprend dès l’archive écrite (aussi en cas
d’échec) : les requêtes attendent, rien n’est refusé ni perdu, et aucun fichier ne change entre les deux phases. Il
liste le volume (chemin, taille, date de modification) avant le dump et après l’archive ; si un fichier a été
ajouté, supprimé ou remplacé entre-temps, la sauvegarde échoue avec files of … changed while the backup ran,
ne garde rien et n’affiche jamais « written and verified ». Les deux fichiers sont ensuite entièrement relus, et le
hash de chaque fichier archivé est écrit dans books.sha256 ; l’archive doit contenir exactement les fichiers du
volume.
Limites : le gel couvre les deux conteneurs du projet Compose, pas une commande librisctl ni un autre conteneur
qui écrirait dans le volume (le contrôle du volume les détecte, et il suffit de relancer) ; le contrôle compare la
taille et la date de modification, pas le contenu, donc un fichier réécrit avec la même taille et la même date
passe inaperçu ; avec LIBRIS_BACKUP_FREEZE=false, une sauvegarde sur une installation active échoue dès qu’un
fichier change pendant l’exécution. Les conteneurs gelés gardent leurs connexions à la base et leurs contrôles de
santé s’arrêtent : une pause longue peut les faire apparaître comme défaillants jusqu’à leur reprise. Une
sauvegarde avant mise à jour doit toujours arrêter les services d’abord. La sauvegarde est écrite dans un dossier caché .libris-….partial et
renommée seulement à la fin : une exécution interrompue ne ressemble donc jamais à une sauvegarde. Les anciennes
sauvegardes ne sont supprimées qu’après une sauvegarde réussie : une exécution en échec ne supprime jamais les
précédentes. Tout échec fait échouer l’unité systemd.
Tester une restauration chaque mois
libris-restore restaure une sauvegarde dans un projet Compose distinct et jetable, et vérifie qu’elle fonctionne. Il
ne touche jamais à votre installation et ne démarre jamais le worker, qui reprendrait les travaux sauvegardés et
appellerait vos providers de modèles.
cd /opt/libris
project="$(sed -n 's/^LIBRIS_PROJECT=//p' .env | head -n 1)"
export LIBRIS_PRODUCTION_PROJECT="${project:-libris}"
export LIBRIS_RESTORE_COMPOSE_FILE="$PWD/docker-compose.yml"
export LIBRIS_RESTORE_ENV_FILE="$PWD/.env"
export LIBRIS_RESTORE_IMAGE="$(sed -n 's/^LIBRIS_IMAGE=//p' .env | head -n 1)"
backup/libris-restore --dry-run /mnt/libris-backup/libris/libris-<timestamp>
backup/libris-restore /mnt/libris-backup/libris/libris-<timestamp>
--dry-runvérifie les sommes de contrôle et l’archive, et affiche chaque commande Docker sans l’exécuter.- L’exécution réelle crée le projet
libris-restore-testavec ses propres volumes, publie l’API sur un port aléatoire de la boucle locale, restaure la base de données et les livres, exécute les migrations et l’API, puis vérifiealembic checket/healthet affiche le nombre d’utilisateurs, de livres, de passages, de fichiers de livres et de fichiers sources. - Le projet et ses volumes sont supprimés à la fin. Avec
--keep, ils restent en place pour inspection : le script affiche la commande Compose du projet de test (avec ses--fileet--env-file) ; ajoutez-yport api 8088pour trouver le port, connectez-vous, puis exécutez-la avecdown --volumespour supprimer le projet.
Comparez les nombres avec ceux de votre installation et notez la date du test.
Pour une installation du registre, le script se trouve dans backup/. Les variables ci-dessus
indiquent le vrai projet Compose (libris par défaut), le fichier de configuration et l’image épinglée.
Pour une installation pilotée par le script de production, les valeurs par défaut restent celles du
script de déploiement (en anglais).
| Variable | Défaut | Signification |
|---|---|---|
LIBRIS_RESTORE_PROJECT | libris-restore-test | Nom du projet jetable. Le nom du projet de production est refusé. |
LIBRIS_RESTORE_COMPOSE_FILE | $LIBRIS_PRODUCTION_BASE/docker-compose.yml | Fichier Compose à utiliser. |
LIBRIS_RESTORE_ENV_FILE | le config.env de la sauvegarde, sinon LIBRIS_PRODUCTION_SECRET_ENV, sinon $LIBRIS_PRODUCTION_BASE/.env ou l’ancien /opt/epub-translator/.env | Configuration à utiliser. |
LIBRIS_RESTORE_IMAGE | l’image enregistrée par le dernier déploiement de production | Image de l’application avec laquelle restaurer. Utilisez la version qui a fait la sauvegarde, ou une plus récente. |
LIBRIS_PRODUCTION_PROJECT | epub-translator | Le projet auquel le script refuse de toucher. |
Restaurer une installation
Faites-le après une perte de données, ou pour revenir à l’état antérieur à une mise à jour ratée. Utilisez le même
.env (au moins la même SECRET_KEY) et une version de l’application au moins aussi récente que celle qui a fait la
sauvegarde.
-
Mettez en pause les livres en cours dans l’interface si Libris tourne encore.
-
Vérifiez la sauvegarde :
backup=/mnt/libris-backup/libris/libris-<timestamp> (cd "$backup" && sha256sum --check SHA256SUMS) -
Confirmez qu’il est acceptable de perdre les modifications de la base de données faites depuis cette sauvegarde. Sur une installation gérée par le récepteur de production, utilisez la CLI d’exploitation actuelle :
librisctl restore "$backup/database.dump" --confirm --no-startElle valide l’archive avant d’arrêter les services, fait un dump de secours privé, remplace la base de données de l’application et laisse les services arrêtés. Le dump de secours n’est pas supprimé automatiquement. Avant un retour arrière, gardez
--no-start: sinon, l’image actuelle réapplique ses migrations.Sans cette CLI, utilisez une base de données neuve, et non
pg_restore --cleanpar-dessus un schéma plus récent.--cleanne supprime que les objets listés dans l’ancienne archive ; les tables et clés étrangères ajoutées depuis (par exemplereview_links) peuvent la bloquer ou subsister. Depuis le dossier Libris exact, vérifiez le projet Compose et la base de données visés, puis n’exécutez chaque étape que si la précédente a réussi :docker compose exec -T database pg_restore --list < "$backup/database.dump" > /dev/null docker compose stop api worker mkdir -p backups && chmod 700 backups rescue=$(mktemp backups/pre-restore-XXXXXXXX.dump) chmod 600 "$rescue" docker compose exec -T database sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > "$rescue" test -s "$rescue" docker compose exec -T database sh -c 'case "$POSTGRES_DB" in ""|postgres|template0|template1) exit 64;; esac; dropdb -U "$POSTGRES_USER" -- "$POSTGRES_DB" && createdb -U "$POSTGRES_USER" --owner "$POSTGRES_USER" --template template0 -- "$POSTGRES_DB"' docker compose exec -T database sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --no-owner --exit-on-error' < "$backup/database.dump"Cela remplace la base de données dédiée à l’application, y compris les objets absents du dump. Les autres connexions doivent être fermées ; la commande ne les déconnecte pas de force. La base recréée utilise la locale et l’encodage par défaut du cluster, ainsi que le propriétaire PostgreSQL de l’installation. Si la base de données a une locale personnalisée, des extensions ou des objets appartenant à d’autres applications, faites d’abord adapter la procédure par son exploitant. Une restauration échouée laisse les services arrêtés ; conservez les deux dumps.
-
Restaurez aussi les livres s’ils ont été perdus ou endommagés. Cela remplace tout le contenu du volume :
docker compose run --rm --no-deps -T api sh -c 'find /data -mindepth 1 -delete && tar -C /data -xzf -' < "$backup/books.tar.gz" -
Redémarrez Libris et vérifiez-le :
docker compose up -d --no-build --wait docker compose exec -T api alembic checkConnectez-vous ensuite, ouvrez l’aperçu d’un livre, testez la connexion d’un provider et exportez un EPUB.
Si .env a lui aussi été perdu, restaurez-le d’abord à partir de config.env si vos sauvegardes l’incluent. Sinon,
créez-en un nouveau avec python3 scripts/setup.py (le mot de passe de la base de données doit alors être celui du
volume restauré) et saisissez à nouveau chaque clé de provider.
Pour reconstruire une installation du registre sauvegardée avec Libris 0.24.0 ou ultérieure sur une
nouvelle machine, placez le .env sauvegardé avant tout démarrage. Cette séquence exige que l’image
de la sauvegarde contienne l’installateur --no-start (introduit en 0.24.0). Pour une sauvegarde plus
ancienne, suivez la procédure de sa version ; n’exécutez pas cette séquence avec son ancien installateur.
LIBRIS_IMAGE doit contenir le digest sha256 complet de l’image du registre Libris. L’installateur
lit cette image, préserve le .env et en extrait les scripts de sauvegarde. Exécutez :
Ouvrez une session root et exécutez-y toute la séquence ; l’accès à /opt/libris et aux
archives de sauvegarde est réservé à root :
sudo -i
mkdir -p -m 750 /opt/libris
install -m 0600 /chemin/vers/config.env /opt/libris/.env
curl --fail --location --silent --show-error https://libris-translate.com/install.sh | bash -s -- --no-start
cd /opt/libris
docker compose up -d --wait database
backup=/mnt/libris-backup/libris/libris-YYYYMMDDTHHMMSSZ
(cd "$backup" && sha256sum --check SHA256SUMS)
docker compose exec -T database sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --no-owner --exit-on-error' < "$backup/database.dump"
docker compose run --rm --no-deps -T api tar -C /data -xzf - < "$backup/books.tar.gz"
docker compose --profile codex up -d --no-build --wait
exit
--no-start (ou LIBRIS_NO_START=1) tire les images sans lancer api, worker ni migrate ;
seule la commande explicite ci-dessus démarre la base avant la restauration. Le .env sauvegardé doit
contenir les images épinglées et les secrets d’origine. Si vous utilisez un autre dossier, définissez
LIBRIS_HOME pour l’installateur et exécutez les commandes Compose depuis ce dossier.
Remplacez YYYYMMDDTHHMMSSZ par l’horodatage UTC du dossier de sauvegarde.
Ne remplacez jamais une base de données dont vous voulez garder les données actuelles sans une sauvegarde de secours vérifiée.
Revenir en arrière après une mise à jour ratée
Les migrations de la base de données ne vont que vers l’avant. Pour revenir à la version précédente après une mise à jour qui a modifié le schéma de la base de données, il vous faut la base de données telle qu’elle était avant la mise à jour.
Installation cliente faite avec le bootstrap du registre :
-
Arrêtez l’application :
docker compose stop api worker. -
Restaurez la sauvegarde de la base de données faite avant la mise à jour (étape 3 ci-dessus). Le volume des livres n’a normalement pas besoin d’être restauré.
-
Démarrez la version précédente depuis le registre (la commande conserve
/opt/libris/.envet les volumes restaurés) :curl --fail --location --silent --show-error https://libris-translate.com/install.sh \ | sudo env LIBRIS_TAG=<version-précédente> bashLe bootstrap extrait le fichier Compose correspondant depuis cette image précise. Ne le relancez pas sans
LIBRIS_TAGavant de vouloir délibérément revenir à la version stable courante. -
Vérifiez
/health, connectez-vous et reprenez les livres.
Installation gérée par le script de déploiement de production : chaque déploiement fait un dump de la base de
données juste avant la migration, dans /opt/libris-production/backups/pre-<timestamp>-<commit>.<random>.dump (les
cinq derniers sont conservés), et garde les images qu’il a remplacées.
- Si la version fautive n’a pas modifié le schéma, exécutez
libris-production-deploy --rollback(oulibrisctl rollback --confirm) : il redémarre les images précédentes. Il refuse quand le schéma diffère, sans rien modifier. - Sinon, restaurez le dump fait juste avant le déploiement fautif (
librisctl restore <dump> --confirm --no-start, ou l’étape 3 ci-dessus avec les options Compose indiquées dans operations (en anglais)), laissez les livres de côté, puis exécutezlibris-production-deploy --rollback.
Les dumps d’avant déploiement restent sur le même disque que l’installation : ils protègent une mise à jour, pas la machine. Gardez aussi la sauvegarde nocturne.