Aller au contenu

Dépannage

Les erreurs ci-dessous ont toutes été rencontrées pour de vrai. Pour chacune : le message exact, ce qu'il veut dire, et quoi faire.

Où lire l'erreur

Trois endroits, dans cet ordre :

  1. Le rapport de l'exécution, dans l'interface. L'étape qui a échoué est nommée, avec son message.
  2. Le message de la sonde, dans le même rapport. Les sondes sont écrites pour dire quoi corriger, pas seulement que quelque chose ne va pas.
  3. Les journaux du runner, chez vous. docker logs restoreproof-runner.

ldap_add: Undefined attribute type (17)

Ce que ça veut dire

Votre annuaire utilise un schéma personnalisé — des attributs ou des classes d'objets que vous avez ajoutés — et ce schéma n'est pas dans la sauvegarde. Le serveur du bac à sable démarre vierge : il ne connaît pas ces attributs, et refuse la première entrée qui en porte un.

Ce n'est pas un défaut du produit. C'est une vraie découverte : votre dump d'annuaire ne peut pas être rechargé sur un serveur neuf, et c'est exactement ce que vous êtes venu vérifier.

Ce que fait le runner aujourd'hui

Avant d'écrire la première entrée, il compare les attributs et classes utilisés par le dump au sous-schéma que l'annuaire du bac à sable déclare. S'il en manque, l'étape échoue avec la liste complète :

the dump uses attribute types [monattribut, monautreattribut] and object classes [maclasse] that the target directory does not define. They come from a custom schema that is not part of the backup…

C'est le message que vous devriez voir. Le Undefined attribute type (17) brut, une erreur à la fois, apparaît quand ce contrôle n'a pas pu s'exécuter — un serveur qui ne répond pas à une requête sur son root DSE. Dans ce cas, chaque exécution ne vous apprend qu'un attribut manquant, et il en faut autant que de schémas absents.

Quoi faire

Extrayez le schéma de votre serveur de production, ajoutez-le à ce que vous sauvegardez, et rechargez-le dans le bac à sable avant l'étape restore_ldap.

Sur OpenLDAP, l'export du schéma :

ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config -LLL > schema.ldif

Dans le plan, une étape exec_in_sandbox entre start_sandbox et restore_ldap :

{
  "type": "exec_in_sandbox",
  "name": "charger le schéma",
  "config": {
    "cmd": ["ldapadd", "-Y", "EXTERNAL", "-H", "ldapi:///", "-f", "/workspace/schema.ldif"]
  }
}

Le chemin doit être exact

cmd est exécuté sans shell : /workspace/*/schema.ldif ne sera pas développé. Voir l'archive imbriquée ci-dessous.


Une archive imbriquée

Le symptôme

Votre sauvegarde s'appelle backup.tar.gz et se décompresse en :

20260830T212418Z/
  data.ldif
  schema.ldif

Vous avez écrit input: "data.ldif" et le plan trouve le fichier. Puis vous ajoutez un exec_in_sandbox avec /workspace/*/schema.ldif — et il échoue avec un « fichier introuvable » qui nomme littéralement le chemin avec l'étoile dedans.

Ce qui se passe

Les deux étapes ne résolvent pas les chemins de la même façon, et c'est délibéré.

Les champs input (unpack, restore_postgres, restore_mysql, restore_mongo, restore_ldap) descendent dans l'arborescence. Si data.ldif n'est pas à la racine, le runner parcourt les sous-répertoires et compare le nom de chaque fichier. Les jokers sont acceptés. Si plusieurs fichiers correspondent, le plus gros gagne. C'est ce qui rend input: "data.ldif" correct même dans un répertoire horodaté dont le nom change à chaque sauvegarde.

Le champ cmd de exec_in_sandbox, lui, est exécuté directement dans le conteneur, sans shell. Il n'y a ni développement de joker, ni substitution de variable, ni redirection. Le * est passé tel quel au programme, qui n'en fait rien.

Quoi faire

Trois possibilités, de la meilleure à la moins bonne.

1. Aplatir l'archive. Si vous maîtrisez la sauvegarde, construisez-la sans le répertoire horodaté :

tar czf backup.tar.gz -C 20260830T212418Z .

C'est la seule qui rend le plan stable dans le temps.

2. Appeler un shell explicitement, quand vous ne maîtrisez pas l'archive :

{"cmd": ["sh", "-c", "ldapadd -Y EXTERNAL -H ldapi:/// -f /workspace/*/schema.ldif"]}

Cela suppose que l'image du bac à sable contient un shell — c'est presque toujours le cas, mais pas toujours.

3. Écrire le chemin en dur, si le nom du répertoire ne change pas.


Le canari échoue et vous ne lui avez rien demandé

Le message

This probe was asked to prove nothing, so it proves nothing. Walking the restored tree found 1 842 file(s) in 96 directories, 412 998 231 bytes in total, but no check was configured…

Ce que ça veut dire

Ce n'est pas une panne. C'est l'étape de réglage.

La sonde filesystem-canary a bien parcouru vos données restaurées. Elle refuse seulement de rendre un PASS alors qu'on ne lui a rien demandé de vérifier : compter des fichiers ne prouve pas qu'une sauvegarde est restaurable, et un PASS qui n'a rien vérifié est une preuve qui ment.

Cette sonde passait autrefois sur un unique fichier vide, et l'exécution était signée comme une preuve. Plus maintenant.

Quoi faire

Le message vous rend les trois chiffres de votre arborescence. Reportez-les :

Ce que vous avez lu Où le mettre
1 842 file(s) RESTOREPROOF_CANARY_MIN_FILES — prenez un peu en dessous, par exemple 1700.
412 998 231 bytes RESTOREPROOF_CANARY_MIN_TOTAL_SIZE — par exemple 400000000.

Ces deux seuils attrapent la sauvegarde qui rétrécit silencieusement de plusieurs milliers de fichiers à une poignée.

Ajoutez au moins un fichier nommé, parce qu'un volume global ne dit rien de ce qu'il contient :

Variable Ce qu'elle ajoute
RESTOREPROOF_CANARY_PATH Un ou plusieurs chemins qui doivent exister.
RESTOREPROOF_CANARY_FILES Les mêmes, plus ce qu'ils doivent contenir, peser ou valoir en SHA-256.
RESTOREPROOF_CANARY_PATTERN Un motif qu'au moins un fichier doit satisfaire.

Un fichier vide au bon nom se restaure aussi bien que le vrai. Seul RESTOREPROOF_CANARY_FILES, en écriture JSON, permet d'exiger un contenu :

[{"path": "config/database.yml", "contains": "production", "min_size": 200}]

L'image d'une sonde ne se télécharge pas

Le message

failed to pull image ghcr.io/kolapsis/restoreproof/probe-postgres:latest

Ce que ça veut dire

Le runner n'a pas pu récupérer le conteneur de la sonde. Les images sont sur ghcr.io, elles sont publiques, et le runner les tire à la demande.

Quoi faire

Vérifiez que le runner peut sortir vers ghcr.io. Depuis la machine du runner :

docker pull ghcr.io/kolapsis/restoreproof/probe-postgres:latest

Si cette commande échoue, c'est un problème de réseau ou de proxy, pas de RestoreProof.

Si votre réseau est fermé, utilisez votre propre miroir. Le runner construit le nom de l'image comme <préfixe><type>:<étiquette> ; ces deux morceaux se règlent :

RESTOREPROOF_PROBE_IMAGE_PREFIX=registry.interne/mirroir/probe-
RESTOREPROOF_PROBE_IMAGE_TAG=v0.1.0

Miroitez alors les dix images : probe-archive-integrity, probe-filesystem-canary, probe-certificate, probe-postgres, probe-mysql, probe-mongodb, probe-sqlite, probe-pocketbase, probe-ldap, probe-http.

Vérifiez que Docker répond pour l'utilisateur du runner :

docker info

Sur une installation binaire, l'utilisateur du runner doit être dans le groupe docker :

sudo usermod -aG docker restoreproof

Il faut se reconnecter, puis redémarrer le runner, pour que le changement de groupe prenne effet. Dans l'installation Docker, le conteneur tourne en root et la question ne se pose pas.


Le runner n'apparaît pas « en ligne »

Comment l'état est décidé

Le runner ouvre un canal vers le Control Plane et le garde ouvert. Il y envoie un battement de cœur toutes les 30 secondes. Un runner silencieux pendant 90 secondes — trois battements manqués — passe à offline. Un canal fermé le dit immédiatement.

Quoi vérifier, dans l'ordre

1. Le runner tourne-t-il ?

docker logs restoreproof-runner

Cherchez control channel established. Sans cette ligne, il n'est pas connecté, et un runner sans canal ne reçoit jamais de travail.

2. L'adresse est-elle la bonne ?

Le canal du runner est en gRPC, sur son propre port. Ce n'est pas l'URL de l'API ni celle de l'application :

RESTOREPROOF_URL=https://grpc.restoreproof.io:443

Une valeur en localhost dans un déploiement réel ne joindra rien.

3. La clé d'API est-elle la bonne ?

Elle commence par rp_. Elle est propre à une organisation. Une clé refusée produit Unauthenticated dans les journaux du runner — un message différent de celui d'un serveur injoignable, qui produit une erreur de connexion suivie d'un délai de reconnexion qui s'allonge.

Si vous avez régénéré la clé dans l'interface, l'ancienne ne vaut plus rien : remettez la nouvelle dans la configuration du runner et redémarrez-le.

4. Le réseau sortant est-il ouvert ?

Le runner n'a besoin d'aucun port entrant. Il lui faut seulement pouvoir sortir en HTTPS/gRPC vers le Control Plane, et vers ghcr.io pour les images.

5. La vérification TLS.

RESTOREPROOF_TLS_SKIP=true ne doit jamais être utilisé en production. Si c'est la seule façon de faire fonctionner le runner, c'est votre chaîne de certificats qu'il faut corriger, pas cette variable.


Autres messages fréquents

no sandbox container running - start_sandbox step must precede restore step

Une étape restore_* est placée avant tout start_sandbox. exec_in_sandbox rend le même message, en se nommant à la fin. Ces deux familles d'étapes travaillent dans le dernier conteneur démarré ; sans conteneur, elles n'ont rien à faire. Remettez les étapes dans l'ordre.

nothing matching "dump.sql" in the workspace, at its root or below

Le fichier n'est nulle part dans l'espace de travail, ni à la racine ni dans les sous-répertoires. Les causes habituelles :

  • l'étape unpack manque, et le dump est encore dans l'archive ;
  • le nom n'est pas celui que vous croyez — essayez un motif, input: "*.sql" ;
  • le fetch a bien récupéré autre chose que ce que vous pensiez.

cannot auto-detect archive format from filename

L'étape unpack déduit le format de l'extension, et le nom de votre fichier ne finit par aucune de celles qu'elle connaît (.tar, .tar.gz, .tgz, .tar.bz2, .tbz2, .tar.xz, .txz, .gz, .zip). Donnez le format explicitement dans l'étape.

No archive found to validate: nothing here proves the backup is readable

La sonde archive-integrity n'a trouvé aucune archive. C'est presque toujours parce que le plan contient une étape unpack : l'archive a été décompressée et a disparu. Cette sonde ne sert que dans un plan qui ne décompresse pas. Si vous décompressez, la vérification du contenu revient à filesystem-canary.

backup is 97h12m0s old, older than the 26h allowed by max_age

Le fichier se restaure très bien. Il est seulement vieux : la tâche qui écrit la sauvegarde s'est arrêtée sans que personne ne le remarque. C'est la seule chose qu'un test de restauration ne peut pas déduire des données elles-mêmes, et c'est pour cela que max_age existe.

Le message donne la date d'écriture à la source.

the directory server truncated the search results before returning every entry

La sonde ldap compte les entrées page par page, 500 à la fois, précisément pour dépasser la limite par défaut de slapd. Ce message signifie que le serveur a quand même coupé la réponse.

Ce n'est pas un annuaire incomplet : c'est une limite du serveur du bac à sable, sans rapport avec votre sauvegarde. Relevez la sizelimit du serveur dans la configuration du bac à sable.

An assertion is configured but no table or query provides a value to check

Vous avez donné un seuil, mais rien à compter. Renseignez la table ou la requête de la sonde concernée — par exemple RESTOREPROOF_PG_TABLE ou RESTOREPROOF_PG_QUERY.

La sonde échoue plutôt que de passer : une assertion qui ne peut pas être évaluée n'est pas une assertion satisfaite.

402 Payment Required

Ce n'est pas une erreur technique. Vous avez atteint une limite de votre offre : nombre de plans, nombre de runners, ou nombre d'exécutions sur le mois. La réponse dit laquelle.


Ce qu'il faut rassembler avant de nous écrire

  • L'identifiant de l'exécution qui a échoué.
  • Le message exact de l'étape ou de la sonde.
  • Les journaux du runner autour de l'horodatage.
  • Le plan, sans les valeurs de secrets — les références secret:// sont utiles, ce qu'elles désignent ne l'est pas.

support@kolapsis.com