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 :
- Le rapport de l'exécution, dans l'interface. L'étape qui a échoué est nommée, avec son message.
- 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.
- 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 :
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 :
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é :
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 :
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 :
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 :
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 :
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 :
Sur une installation binaire, l'utilisateur du runner doit être dans le groupe
docker :
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 ?
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 :
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
unpackmanque, et le dump est encore dans l'archive ; - le nom n'est pas celui que vous croyez — essayez un motif,
input: "*.sql"; - le
fetcha 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.