Ce qu'il vous faut¶
Rien d'exotique, et surtout pas un environnement de développement. Un serveur Linux avec Docker ou un cluster Kubernetes, un accès en lecture à vos sauvegardes, et une connexion sortante.
Une machine avec Docker, ou un cluster Kubernetes¶
Le runner tourne lui-même dans un conteneur, et démarre un conteneur par sonde et par bac à sable : il lui faut donc, d'une façon ou d'une autre, un démon Docker accessible. Deux voies de déploiement sont proposées par l'assistant ; le binaire seul reste annoncé « à venir ».
Quelle que soit la voie choisie, prévoyez un espace de travail capable d'accueillir l'archive téléchargée et son contenu décompressé, en même temps : c'est là que la sauvegarde est téléchargée, décompressée et restaurée, et c'est ce que les conteneurs de sondes montent. Chaque exécution nettoie derrière elle — conteneurs, volumes du bac à sable, espace de travail.
Avec Docker¶
Une machine Linux avec Docker Engine 25.0 ou plus récent. Le runner négocie la version de l'API avec le démon au démarrage : vous n'avez rien à régler.
Il lui faut l'accès au socket Docker :
C'est le même modèle que GitLab Runner : le conteneur tourne en root pour atteindre ce socket. Traitez la machine du runner comme une machine de confiance — quiconque atteint ce socket atteint le démon Docker de l'hôte.
Le volume de travail est obligatoire :
Sans lui, le runner refuse de démarrer avec un message explicite : depuis un conteneur, un chemin qui n'est pas sur un volume monté n'existe pas pour les conteneurs qu'il lance.
Avec Kubernetes¶
Un cluster Kubernetes 1.29 ou plus récent, Helm 3.8+, et une classe de stockage par défaut pour les deux volumes que le chart demande (espace de travail et données Docker).
Le pod du runner embarque son propre démon Docker, dans un conteneur à part
(un side-car Docker-in-Docker) : le runner fonctionne donc quel que soit
le moteur de conteneurs de vos nœuds. Ce side-car tourne en mode
privilégié — votre cluster doit l'autoriser, et le chart ne l'accorde pas
tout seul : --set dind.privileged=true est obligatoire, sans quoi
l'installation s'arrête avec un message qui le rappelle. C'est un « side-car
natif », une garantie Kubernetes apparue en 1.29 : le démon Docker est démarré
et attend d'être prêt avant que le runner ne le soit à son tour, pour ne pas
dépendre de l'ordre de démarrage des deux conteneurs.
Le volume d'espace de travail est une revendication de stockage en
lecture-écriture par un seul pod (ReadWriteOnce) : une mise à jour du
chart remplace donc le pod plutôt que de faire cohabiter l'ancien et le
nouveau — comptez quelques secondes sans runner en ligne à chaque
helm upgrade.
Le chart est publié en artefact OCI, versionné par chaque publication de RestoreProof :
kubectl create namespace restoreproof
kubectl create secret generic restoreproof-runner-credentials \
--namespace restoreproof \
--from-literal=api-key='<votre clé API>'
helm install restoreproof-runner \
oci://ghcr.io/kolapsis/restoreproof/charts/restoreproof-runner \
--version 0.5.0 \
--namespace restoreproof \
--set controlPlane.url=<adresse du canal gRPC> \
--set runner.name=<nom du runner> \
--set dind.privileged=true \
--set secrets.apiKeySecretName=restoreproof-runner-credentials
L'assistant de déploiement (Parc de runners → Ajouter un runner) écrit cette commande pour vous : clé API, nom, adresse, labels et montages de volumes déjà remplis — voir le parcours complet.
Le chart pose aussi une NetworkPolicy : le runner n'accepte aucun trafic entrant, et ne sort que vers le DNS et les ports TCP 443 et 80. Si votre canal gRPC ou une de vos sources écoute ailleurs — un 9090, un stockage S3 sur 9000 — ouvrez-le :
helm upgrade restoreproof-runner \
oci://ghcr.io/kolapsis/restoreproof/charts/restoreproof-runner \
--version 0.5.0 \
--namespace restoreproof --reuse-values \
--set 'networkPolicy.egressRules[0].ports[0].protocol=TCP' \
--set 'networkPolicy.egressRules[0].ports[0].port=9090'
Vous pouvez la désactiver avec --set networkPolicy.enabled=false. Sur un
cluster dont le greffon réseau n'applique pas les NetworkPolicy, l'objet est
posé mais ne filtre rien.
Si vous mettez à jour un runner installé avec une version antérieure du chart,
votre helm upgrade doit ajouter --set dind.privileged=true : c'est la seule
option devenue obligatoire.
L'accès en lecture à vos sauvegardes¶
Selon l'endroit où elles vivent :
- S3, MinIO, Wasabi — les identifiants sont fournis au runner (variables
d'environnement, fichier dans son dossier de secrets, table de secrets
statiques de sa configuration, ou rôle IAM de l'instance pour AWS). La source
déclarée dans RestoreProof n'enregistre que la référence —
env://S3_SECRET_KEY,file://minio.key,static://minio-access-key— ou rien du tout si vous laissez le runner utiliser sa chaîne d'identification par défaut. La valeur n'est jamais enregistrée. Où poser cette valeur selon votre plateforme de déploiement : Fournir les secrets au runner. Google Cloud Storage et Azure Blob Storage : à venir. -
Disque local ou NFS — montez le répertoire dans le conteneur du runner, en lecture seule. L'assistant de déploiement écrit le montage pour vous, à partir du chemin que vous déclarez à l'étape Configuration : côté runner, le répertoire est monté sous
/mnt/, suivi du dernier segment du chemin déclaré. Un/chemin/hote/backupsdevient donc :Sur Kubernetes, le même chemin déclaré ajoute le volume et son montage à la commande
helm install. Le plan désignera ensuite/mnt/backups, le chemin vu par le runner. L'assistant ajoute aussi ce dossier à la liste des dossiers que le runner a le droit de lire (voir plus bas). Pour un partage NFS, assurez-vous qu'il est monté avant le démarrage du runner. - HTTP/HTTPS — une URL directe vers le fichier. Pour une URL authentifiée, posez la référence sur la source, soussecret_refs.authorization(une des trois formesenv://,file://,static://) : le runner en fait l'en-têteAuthorization. Le champheadersde l'étapefetchdu plan reste disponible, en configuration brute (onglet JSON (expert)), pour un autre en-tête ou pour écraser celui de la source ; ses valeurs acceptent une référencesecret://, par exemple"Authorization": "secret://env://JETON_SAUVEGARDES".
La lecture seule suffit. Le runner ne réécrit jamais dans vos sauvegardes.
Ce que le runner a le droit d'atteindre¶
Le runner ne télécharge que depuis les hôtes que vous lui avez listés, et ne lit que les dossiers locaux que vous lui avez listés. Tout le reste est refusé, même quand un plan le demande : le plan vient de RestoreProof, et le runner ne le laisse pas décider à votre place de ce qu'il peut joindre chez vous. Les deux listes sont vides par défaut, et une liste vide refuse tout.
L'assistant de déploiement remplit ces listes à partir de vos sources, à l'étape Configuration. Il affiche chaque entrée avec la source ou le volume qui l'a fait ajouter, et vous pouvez les modifier avant de copier la commande. Les listes figurent seulement dans cette commande : rien n'est envoyé à RestoreProof.
| Variable | Clé de config.yaml |
Ce qu'elle autorise |
|---|---|---|
RESTOREPROOF_FETCH_HOSTS |
fetch.allowed_hosts |
Les hôtes depuis lesquels le runner télécharge, pour les sources HTTP et S3. |
RESTOREPROOF_LOCAL_ROOTS |
fetch.local_roots |
Les dossiers dans lesquels une source locale doit se trouver, tels que le runner les voit. |
RESTOREPROOF_PROBE_IMAGES |
probes.allowed_images |
Les images de sondes personnalisées, en plus des images officielles (voir Sondes). |
Chaque variable prend une liste séparée par des virgules. Quand elle est
posée, elle remplace la liste du fichier de configuration. Sur Kubernetes, le
chart pose ces variables à partir des valeurs fetch.allowedHosts,
fetch.localRoots et allowedProbeImages.
Une entrée de RESTOREPROOF_FETCH_HOSTS peut prendre cinq formes : un nom
d'hôte (s3.fr-par.scw.cloud), un hôte suivi d'un port (minio.interne:9000),
tous les sous-domaines d'un domaine (*.wasabisys.com, qui n'autorise pas
wasabisys.com lui-même), une adresse IP, ou un bloc CIDR (10.0.0.0/8). Un
nom d'hôte ou une adresse IP sans port n'autorise que le port par défaut de
l'adresse, 443 en https et 80 en http : un MinIO sur le port 9000 s'écrit
donc minio.interne:9000 ou 10.0.0.5:9000, et l'assistant écrit le port pour
vous quand l'adresse de la source en porte un. Un bloc CIDR autorise tous les
ports. Une adresse IP ou un bloc CIDR autorise aussi tout nom d'hôte qui s'y
résout. Pour
une source S3 sans point d'accès, c'est-à-dire chez AWS, l'hôte à autoriser est
<bucket>.s3.<région>.amazonaws.com.
Certaines adresses restent hors d'atteinte même si vous les listez : les
adresses locales au lien (169.254.0.0/16 et fe80::/10), qui comprennent
l'adresse de métadonnées des clouds 169.254.169.254, ainsi que fd00:ec2::254 et
100.100.100.200. L'adresse de la machine elle-même (127.0.0.1, ::1) n'est
autorisée que si une entrée nomme localhost ou cette adresse. Le runner
vérifie l'adresse qu'il joint réellement, après la résolution DNS et à chaque
redirection : un nom autorisé qui se résout vers une adresse interdite est
refusé lui aussi.
Les entrées de RESTOREPROOF_LOCAL_ROOTS sont des chemins absolus. Le runner
refuse de démarrer si l'une d'elles contient son propre dossier de travail, son
dossier de secrets, son fichier de configuration ou /proc, ou se trouve à
l'intérieur de l'un d'eux.
Quand une étape est refusée faute d'entrée, son message, sur la page de l'exécution, nomme la variable et l'entrée exacte à ajouter.
Une connexion sortante¶
Le runner appelle, il n'est jamais appelé. Aucun port à ouvrir en entrée, aucune redirection, aucune IP fixe à nous communiquer.
Ce qu'il doit pouvoir joindre :
- Le canal du control plane, en gRPC sur TLS. C'est l'adresse
https://…que l'assistant de déploiement écrit dans votre commande. Il y maintient une connexion longue durée : le réseau doit laisser vivre une connexion inactive plusieurs minutes (le runner envoie un keepalive toutes les 20 secondes, ce qui suffit à la plupart des NAT et proxys). - Le registre des images de sondes,
ghcr.io, d'où viennent les imagesghcr.io/kolapsis/restoreproof/probe-*. Le préfixe et le tag sont configurables si vous préférez un miroir interne. - Le registre des images de bacs à sable — celles que vos plans nomment
(
mysql:8.0,postgres:16, une image applicative…), donc en général le Docker Hub ou votre registre privé. - Vos sources HTTP et S3, aux adresses que vous avez listées dans
RESTOREPROOF_FETCH_HOSTS.
Si vous préchargez toutes ces images sur la machine, seul le canal du control plane reste indispensable.
Un compte, et rien d'autre¶
La création de compte crée l'organisation et son premier utilisateur, sans paiement ni carte bancaire. De quoi faire le parcours complet et obtenir une vraie preuve signée avant de payer quoi que ce soit. Les limites de départ — nombre de runners, de plans, d'exécutions par mois et durée de consultation des rapports — sont affichées dans l'application.
Rien ne bloque tant que vous n'avez pas confirmé votre adresse e-mail : la confirmation sert aux notifications par e-mail, pas à l'accès. Le détail est dans Compte et équipe. Pour être prévenu ailleurs que par e-mail (Slack, Teams, Discord, Telegram, Matrix, webhook), voir Notifications.
Ce que le runner ne fait pas¶
- Il n'envoie jamais de données de sauvegarde au control plane. Il envoie des verdicts, des mesures et des journaux assainis.
- Il ne transmet aucun de vos secrets. Un plan et une source ne contiennent
que des références (
env://,file://,static://), résolues sur la machine du runner. Toute valeur qu'il a résolue pendant une exécution est remplacée par[REDACTED]dans ce qu'il envoie. - Il ne renvoie pas la sortie des commandes qu'il exécute. Quand une commande échoue, RestoreProof reçoit son nom, son code de sortie et une seule ligne de 200 octets au plus. La sortie complète reste dans les journaux du runner, chez vous.
- Il ne joint aucun hôte et ne lit aucun dossier que vous ne lui avez pas listés.
- Il ne touche pas à votre production : la restauration a lieu dans un bac à sable jetable, détruit à la fin de l'exécution.
- Il n'accepte aucune connexion entrante.
Deux réglages à connaître avant de vous lancer¶
Ces deux points concernent la clé de signature et le TLS, pas les identifiants d'accès à vos sauvegardes : ceux-là se règlent comme décrit dans Fournir les secrets au runner.
-
La clé de signature — c'est la clé Ed25519 qui signe vos rapports. Vous n'avez rien à fournir : au premier démarrage, le runner la crée dans son volume de travail (
/var/lib/restoreproof) et affiche son empreinte dans ses journaux. Elle reste la même tant que ce volume est conservé, y compris lors d'une mise à jour. Gardez donc toujours le volume indiqué dans la commande d'installation.Si ce volume est perdu, le runner crée une nouvelle clé au démarrage suivant. RestoreProof la met en attente et le runner ne reçoit plus de travail tant qu'un administrateur ne l'a pas approuvée sur la page du runner. Avant d'approuver, vérifiez que l'empreinte affichée sur cette page est bien celle que le runner a écrite dans ses journaux. Si l'empreinte ne correspond pas, ou si vous pensez que la clé d'API du runner a pu fuiter, n'approuvez pas : régénérez la clé d'API, reconfigurez le runner, puis approuvez la clé qu'il présente une fois l'empreinte vérifiée. Une fois la clé approuvée, le runner reprend seul dans les cinq minutes, sans redémarrage.
Si un administrateur refuse la nouvelle clé, le runner reste en pause tant qu'il présente cette clé. Pour le remettre en service, remettez en place le volume qui contient la clé d'origine (le fichier
signing.key), ou réinstallez-le comme un nouveau runner.Les runners installés avant cette version présentent une nouvelle clé une seule fois, juste après leur mise à jour : il faut l'approuver une fois pour chacun d'eux. -
RESTOREPROOF_TLS_SKIP(sur Kubernetes :controlPlane.tlsSkip) — à laisser àfalse. Ne le passez àtrueque face à un control plane en certificat auto-signé, dans un environnement de test.
Une fois tout cela en place, suivez le parcours complet.