Presque tout le monde utilisant Odoo a des sauvegardes. Presque personne n'a de restauration.
Ce sont deux choses différentes, et l'écart entre elles est la source des mauvais jours. Un travail de sauvegarde qui vous donnera un système fonctionnel et un qui ne vous donnera rien ont exactement le même aspect de l'extérieur : même horaire, même coche verte, même fichier atterrissant dans le même seau chaque nuit. Rien n'indique lequel vous avez.
Ce n'est pas un guide pour configurer les sauvegardes Odoo. Vous avez déjà fait cela, et il y en a déjà beaucoup. C'est l'autre moitié : comment prouver que la chose que vous avez collectée chaque nuit pendant l'année dernière va réellement revenir, un mardi normal, dans environ une heure.
Réponse courte
Vous ne pouvez pas savoir si une sauvegarde Odoo va se restaurer tant que vous ne l'avez pas restaurée. Il n'y a aucune propriété du fichier de sauvegarde, du journal de travail ou du seau de stockage qui vous le dit. Une sauvegarde qui produira un système fonctionnel et une qui ne produira rien ont un aspect identique de l'extérieur.
Pour le découvrir, restaurez-la dans une base de données isolée avec `psql -v ON_ERROR_STOP=1` (sans ce drapeau, une restauration échouée sort toujours `0`), confirmez que le `filestore/` de la sauvegarde contient chaque fichier référencé par la table restaurée `ir_attachment` , puis comparez les comptes d'enregistrements et un total financier avec la production. Exécutez-le trimestriellement et enregistrez combien de temps cela a pris. Ce nombre est votre temps de récupération réel.
La procédure complète est ci-dessous, et cela prend environ une heure la première fois.
Deux vérifications à effectuer maintenant
1. Votre sauvegarde contient-elle les fichiers, ou seulement la base de données ?
unzip -l backup.zip | grep -c 'filestore/'
Zéro signifie que vous avez une sauvegarde de la base de données, pas une sauvegarde Odoo.
Les pièces jointes, les documents téléchargés, les images de produits, les PDF générés et les pièces jointes d'e-mail ne sont pas stockés dans PostgreSQL par défaut. La base de données contient une `ir_attachment` ligne dont le `store_fname` pointe vers un chemin, et le fichier lui-même se trouve dans le répertoire filestore sur le disque. Restaurer uniquement la base de données et chaque enregistrement revient avec ses documents vidés.
Cela peut encore être un choix délibéré. Certaines équipes conservent les pièces jointes dans un stockage d'objets et les sauvegardent séparément. Cela devrait être un choix que vous avez fait, pas un que vous découvrez.
2. Les pièces jointes sont-elles déjà cassées en production ?
C'est celui qui surprend les gens. Exécutez-le contre votre base de données en direct, avant toute question de sauvegarde :
DB=odoo_prod
FS=/var/lib/odoo/filestore/$DB
psql -d "$DB" -tAc \
"SELECT store_fname FROM ir_attachment WHERE store_fname IS NOT NULL" \
| LC_ALL=C sort -u > /tmp/db_files.txt
( cd "$FS" && find . -type f -printf '%P\n' ) | LC_ALL=C sort > /tmp/fs_files.txt
echo "pièces jointes dont le fichier est manquant : $(comm -23 /tmp/db_files.txt /tmp/fs_files.txt | wc -l)"
echo "fichiers orphelins sans ligne de pièce jointe : $(comm -13 /tmp/db_files.txt /tmp/fs_files.txt | wc -l)"
Le premier nombre devrait être zéro.
Si ce n'est pas le cas, ces documents sont déjà partis, et cela fait un moment qu'ils sont partis, car Odoo ne l'annonce pas. Un fichier de filestore manquant est détecté, enregistré au niveau INFO, et revient sous forme de chaîne d'octets vide. La pièce jointe conserve son nom de fichier d'origine et sa taille enregistrée, et se télécharge comme rien.
C'est la raison pour laquelle toute la procédure ci-dessous existe : vérifier une restauration en l'ouvrant et en cliquant autour passera avec chaque pièce jointe cassée. Les enregistrements, les noms de fichiers et les tailles de fichiers ont tous l'air exactement comme ils devraient.
La barre : ce que "testé" signifie réellement
La règle générale habituelle pour les sauvegardes est 3-2-1-1-0: trois copies des données, sur deux types de supports, une hors site, une hors ligne ou immuable, et zéro erreurs sur une restauration vérifiée.
La plupart des configurations Odoo fonctionnent raisonnablement bien sur les quatre premiers chiffres et sautent complètement le dernier. Ce qui est dommage, car le zéro est le seul qui prouve que les autres valaient quelque chose. Des copies que vous ne pouvez pas restaurer ne sont que du stockage.
Il y a deux autres chiffres que vous devriez pouvoir dire à voix haute, et seule une véritable restauration vous en donnera un :
- RPO : combien de données vous perdriez. Pas "nous faisons des sauvegardes chaque nuit à 2h du matin". Si la panne survient à 16h, vous perdez quatorze heures de facturation. Est-ce acceptable ? C'est une question commerciale avec une vraie réponse, et la réponse est généralement différente du calendrier que quelqu'un a établi une fois et n'a jamais revu.
- RTO : combien de temps vous seriez hors service. C'est celui qui est deviné, et la supposition est généreuse. Un test de restauration le transforme en une mesure : téléchargement, restauration, copie de fichier, chargement de module, vérifications. Sur une grande base de données, le vrai chiffre se trouve souvent à des heures de celui que les gens supposent, et il est bien mieux d'apprendre cela aujourd'hui.
Tout ce qui suit concerne l'atteinte de ce zéro.
Comment tester une sauvegarde Odoo, étape par étape
Avant de commencer, obtenez une cible isolée : une branche de staging, un serveur de secours, ou un ordinateur portable avec Docker. Pas de production, et rien ne partage un chemin réseau avec le serveur de messagerie de production, les fournisseurs de paiement ou la synchronisation bancaire.
Étape 1 : Récupérez la sauvegarde d'où elle se trouve réellement
Téléchargez-la depuis le bucket de stockage, avec des identifiants qui ne sont pas ceux de la production, sur une machine qui n'est pas le serveur de production.
Une sauvegarde que vous ne pouvez récupérer *qu'en utilisant* le serveur de production n'est pas une sauvegarde. C'est une seconde copie sur la chose contre laquelle vous vous protégez. Cette étape est le test de cela, et c'est celle que les gens sautent parce qu'elle ressemble plus à de l'administration qu'à de l'ingénierie.
Étape 2 : Prouvez que le fichier est intact avant de l'utiliser
unzip -t backup.zip && unzip -l backup.zip | tail -3
`unzip -t` vérifie les sommes de contrôle internes de l'archive. Cela détecte les téléchargements tronqués et les téléchargements à moitié terminés, qui comptent plus qu'ils ne devraient, car un tronqué `dump.sql` se restaure silencieusement jusqu'au point où il a été coupé.
Étape 3 : Lisez le manifeste et comparez-le à la cible
Chaque dump zip Odoo contient un `manifest.json`, écrit par `dump_db_manifest` (odoo/service/db.py):
unzip -p backup.zip manifest.json | python3 -m json.tool | head -20
Il enregistre la version d'Odoo, la version majeure de PostgreSQL, et chaque module installé avec sa version. Entre eux, ils vous disent exactement ce dont ce dump a besoin avant qu'il puisse signifier quoi que ce soit.
Vérifiez trois choses :
- version par rapport à la version d'Odoo de la cible. La même version est une restauration. Une version différente est une mise à niveau, et les mises à niveau appartiennent à une répétition, pas à un incident.
- pg_version par rapport à la PostgreSQL de la cible. De l'ancien au nouveau est routine. Du nouveau à l'ancien est là où les restaurations commencent à perdre des déclarations.
- modules par rapport à ce qui est installé sur la cible, y compris les tiers, OCA et le vôtre.
À savoir : `restore_db` extrait `dump.sql` et le `filestore/` membres et rien d'autre. Le manifeste est écrit sur chaque sauvegarde et n'est lu par rien dans la base de code. Il existe pour vous.
Étape 4 : Restaurez le SQL vous-même, avec les erreurs activées
C'est l'étape qui sépare un test d'un espoir. N'utilisez pas le gestionnaire de base de données pour cela :
createdb restore_test_2026_08
time unzip -p backup.zip dump.sql \
| psql -v ON_ERROR_STOP=1 --dbname=restore_test_2026_08
echo "exit: $?"
-v ON_ERROR_STOP=1 est tout l'intérêt de cette étape. Sans ce drapeau, `psql` ignore les instructions qui échouent, continue jusqu'à la fin du fichier et sort `0`, donc une base de données partielle est signalée comme une restauration réussie. Avec, la restauration s'arrête à la première erreur et sort `3`, et vous obtenez le texte d'erreur : l'extension manquante, le rôle absent, l'écart de version.
Sortie `0` signifie maintenant ce que vous avez toujours supposé qu'elle signifiait.
`temps` vous donne le plus grand composant unique de votre RTO réel. Notez-le. Vous en aurez besoin à l'étape 8.
Étape 5 : Vérifiez que le filestore est complet avant de le copier
Maintenant que la base de données est restaurée, comparez ce qu'elle attend avec ce que la sauvegarde contient réellement :
unzip -Z1 backup.zip | sed -n 's|^filestore/||p' \
| grep -v '/$' | grep -v '^$' | LC_ALL=C sort > /tmp/zip_files.txt
psql -d restore_test_2026_08 -tAc \
"SELECT store_fname FROM ir_attachment WHERE store_fname IS NOT NULL" \
| LC_ALL=C sort -u > /tmp/db_files.txt
echo "pièces jointes sans fichier dans cette sauvegarde : $(comm -23 /tmp/db_files.txt /tmp/zip_files.txt | wc -l)"
Zéro est le passage. Tout autre nombre vous indique exactement combien de documents cette sauvegarde ne peut pas vous rendre.
Les deux `LC_ALL=C` et le `grep -v '^$'` comptent : l'ordre de tri doit correspondre des deux côtés, et `unzip -Z1` émet l'entrée de répertoire nue `filestore/` qui devient une ligne vide et empoisonne silencieusement la comparaison.
Ensuite, copiez les fichiers à leur place en tant que `filestore/restore_test_2026_08` dans le répertoire de données de la cible, et définissez la propriété afin qu'Odoo puisse les lire et les écrire.
Étape 6 : Neutralisez avant que quoi que ce soit ne l'ouvre
Les données de production restaurées arrivent avec ses serveurs de messagerie sortants, actions programmées, fournisseurs de paiement et connecteurs intacts. La neutralisation est une étape distincte, sur option. Elle ne se produit pas parce que vous avez restauré.
Exécutez-le avant qu'Odoo ne démarre, et démarrez Odoo avec des sémantiques de copie afin que la base de données restaurée obtienne sa propre identité plutôt que celle de la production. Ce que couvre la neutralisation, ce qu'elle laisse armé, et pourquoi la partie identité est importante a son propre guide *(lien vers le post de mise en scène ici lors de la publication)*. Lisez-le avant d'exécuter cette procédure sur des données réelles.
Étape 7 : Vérifiez les données par rapport aux chiffres que vous connaissez déjà
Aucun code de sortie ne peut faire cette partie.
Avant de commencer, exécutez une empreinte sur la production et enregistrez la sortie :
SELECT 'account_move' AS t, count(*), max(id), max(write_date) FROM account_move
UNION ALL SELECT 'account_move_line', count(*), max(id), max(write_date) FROM account_move_line
UNION ALL SELECT 'sale_order', count(*), max(id), max(write_date) FROM sale_order
UNION ALL SELECT 'stock_move', count(*), max(id), max(write_date) FROM stock_move
UNION ALL SELECT 'res_partner', count(*), max(id), max(write_date) FROM res_partner;
Exécutez la même requête contre la restauration et différez les deux. Les comptes de lignes détectent les données manquantes ; `max(id)` détecte une restauration qui s'est arrêtée tôt ; `max(write_date)` détecte une sauvegarde qui est plus ancienne que vous ne le pensez.
Ajoutez les tables qui comptent pour *votre* entreprise. Si vous vivez dans des commandes de fabrication ou des abonnements, mettez-les dans la liste.
Ensuite, dans l'interface :
- Un total financier que vous pouvez vérifier. Revenu de l'année en cours, ou un solde bancaire. Un nombre qui est soit juste, soit faux.
- Ouvrez trois pièces jointes de différents mois, y compris une de cette semaine, et vérifiez la taille du fichier téléchargé, pas seulement que quelque chose a été téléchargé. C'est le seul endroit où le comportement de fichier vide apparaît.
- Chargez un écran de chaque module personnalisé. Un module manquant sur la cible laisse ses tables restaurées et ses données inaccessibles, et l'interface est l'endroit où vous le voyez.
Étape 8 : Enregistrez-le, puis détruisez la base de données de test
Notez quatre choses : la date, quelle sauvegarde vous avez utilisée, le temps total écoulé et ce qui a échoué.
Le temps écoulé est votre RTO : mesuré, pas deviné. Quatre de ces enregistrements et vous avez une tendance, ce qui est le moment où cela cesse d'être une corvée et devient une preuve. C'est aussi le nombre à apporter quand quelqu'un demande si l'hébergement est adéquat, car cela répond à la question qu'il pose réellement.
Ensuite, supprimez la base de données de test et retirez la copie du filestore.
À quoi ressemble un passage
- `unzip -t` propre
- Le manifeste correspond à la cible sur la version Odoo, la version PostgreSQL et la liste des modules
- `psql -v ON_ERROR_STOP=1` sort `0`
- Aucune pièce jointe manquante dans la sauvegarde
- L'empreinte correspond à la production sur les comptes, l'id max et la date d'écriture max
- Trois pièces jointes s'ouvrent à la bonne taille de fichier
- L'écran de chaque module personnalisé se charge
- Temps écoulé enregistré
Tout ce qui est en deçà de cela est une constatation, et une constatation aujourd'hui vaut beaucoup plus que la même constatation pendant une panne.
À quelle fréquence, et qui
Trimestriel est le minimum. Exécutez-le également après toute modification de la structure du système : un changement d'hébergement, une mise à niveau de PostgreSQL, une mise à niveau de version d'Odoo, un nouveau module mis en ligne, ou un changement de l'emplacement de stockage des sauvegardes.
Une personne nommée en est responsable. Pas "l'équipe". Les tests de sauvegarde semblent être quelque chose que n'importe qui pourrait faire, c'est pourquoi cela finit généralement par n'être fait par personne. Cela prend une heure par trimestre. Mettez-le dans un calendrier avec un nom dessus.
Gardez les enregistrements ensemble, dans ce que votre entreprise utilise déjà. Quatre entrées datées avec des temps écoulés constituent une position de récupération après sinistre. Zéro entrée est un espoir, aussi bonne que soit la configuration de la sauvegarde.
Ce qu'il faut automatiser, et ce qui reste humain
Automatisez les parties objectives et ennuyeuses : une restauration qui s'arrête en cas d'erreur, un contrôle d'intégrité d'archive, une comparaison de complétude de filestore, un enregistrement de taille et de somme de contrôle pour chaque sauvegarde, et une alerte lorsqu'une sauvegarde arrive avec une taille inférieure de plus de quelques pourcents par rapport à la précédente. Rien de tout cela n'a besoin de jugement, et tout cela est scriptable.
Ce qui ne s'automatise pas, c'est l'étape 7. "Complet" est défini par des chiffres que seule votre entreprise connaît : le chiffre d'affaires du mois dernier, le nombre de factures, si le document dont votre comptable a besoin s'ouvre. Aucune plateforme ne peut vérifier cela pour vous, et toute plateforme qui dit qu'elle vérifie complètement vos restaurations utilise le mot pour signifier quelque chose de plus petit.
Donc : l'automatisation devrait rendre impossible de manquer une restauration échouée, et un humain vérifie toujours que le contenu est correct. La deuxième partie est une demi-heure un quart.
Ce que c'est réellement
Les sauvegardes ne sont pas négligées. Elles s'exécutent, elles deviennent vertes, et presque tout le monde en a. L'écart est entre une sauvegarde étant *prise* et une sauvegarde étant *restaurable*, et il reste ouvert parce que les deux états semblent identiques de l'extérieur. Une sauvegarde qui ne sera jamais restaurée ressemble exactement à celle qui le sera, jusqu'au jour où vous en avez besoin. Ce qui est le pire jour possible pour le découvrir.
C'est la différence entre Odoo en cours d'exécution et Odoo en cours d'exécution correctement, dans la forme la plus coûteuse qu'elle prenne. Rien de dramatique. Juste un fichier que personne n'a jamais ouvert, pendant un an.
Et cela vous coûte quelque chose chaque jour avant cela. Personne ne fait vraiment confiance aux sauvegardes, donc personne ne fait vraiment confiance aux changements non plus. Les mises à niveau sont repoussées, les mises à jour de modules sont repoussées, et le système dérive encore plus de tout ce que vous voudriez restaurer de toute façon.
Des restaurations qui sont testées parce qu'elles se produisent
La version fiable de cela n'est pas une meilleure liste de contrôle. C'est un chemin de restauration qui s'exécute suffisamment souvent pour avoir été prouvé, et qui échoue bruyamment quand il échoue.
Sur l'hébergement Odoo Skysize, la restauration s'exécute `psql -q -v ON_ERROR_STOP=1`, le même drapeau que l'étape 4, donc un échec au niveau de l'instruction interrompt la restauration et échoue le travail au lieu de produire une base de données partielle avec un code de sortie propre. Les lignes qui autrement interrompraient une restauration légitime (paramètres de serveur uniquement plus récents d'un `pg_dump` plus récent, DDL d'extension gérée par le fournisseur) sont délibérément supprimées, et le nombre retiré est écrit dans le journal de travail. Retiré intentionnellement et compté, plutôt que sauté et rejeté.
Les restaurations sont bleu-vert : une nouvelle base de données et un nouveau conteneur apparaissent sur un nouveau port tandis que le déploiement précédent continue de servir, et le nouveau doit démarrer et passer un contrôle de santé avant que quoi que ce soit ne soit transféré vers lui. Ce n'est qu'alors que l'ancien déploiement est abandonné. Si une étape échoue, le déploiement à moitié construit est démonté et l'ancien conteneur n'est jamais touché. Vous êtes exactement là où vous étiez, toujours en service. Et les branches de staging sont neutralisées automatiquement lorsque les données de production arrivent, ce qui rend la restauration dans le staging pour *vérifier* une sauvegarde un après-midi ordinaire plutôt qu'un risque.
Ce que rien de tout cela ne fait, et nous préférerions le dire : cela ne vérifie pas que vos totaux de factures sont corrects. Notre contrôle de santé prouve que le déploiement restauré démarre et répond. Il ne peut pas prouver que les factures de jeudi dernier y sont. L'étape 7 reste la vôtre, sur n'importe quelle plateforme.
Construit par d'anciens ingénieurs d'Odoo, certifié ISO 27001. Parlez à un expert en hébergement Odoo sur ce à quoi ressemble réellement votre récupération.
Si vous préférez l'exécuter sur votre propre machine, dans votre propre pays, Skysize BYOS met la même plateforme sur votre serveur. Connectez votre serveur.