Auto-héberger open-kritt sur un VPS avec Docker
Installez open-kritt avec Docker Compose, épinglez une release, accédez à l’UI sur le port 5173 via un tunnel SSH et définissez votre budget provider.
Pourquoi auto-héberger open-kritt sur un VPS plutôt que sur votre ordinateur portable
Auto-hébergez open-kritt sur un serveur que vous pouvez détruire et recréer. L’outil exécute ses agents d’analyse en tant que root dans des conteneurs de jobs jetables, fournit à chacun une copie inscriptible de votre code et un accès direct à Internet, et monte le socket Docker de l’hôte dans son service engine. Ce compromis est raisonnable sur une machine dédiée à cette tâche. Il est risqué sur la machine qui contient vos clés SSH.
Quatre propriétés de la configuration par défaut justifient cette recommandation. Elles proviennent toutes du README et du fichier compose du projet.
Les agents sont conçus pour être puissants. Le README indique que les agents dotés d’outils s’exécutent en tant que root dans des conteneurs de jobs jetables, avec des copies inscriptibles des dépôts et un accès direct à Internet. Ils peuvent donc installer des outils, compiler des cibles, exécuter des tests et créer des proofs of concept. Un scan n’est pas un linter qui lit des fichiers. C’est une exécution de code arbitraire que vous avez demandée. Cet accès à Internet fonctionne dans les deux sens : tout ce qu’un agent récupère en analysant une cible est du texte non fiable qui arrive dans son prompt. Vous êtes exposé de la même manière lorsque vous donnez à un agent son propre accès à la recherche web.
L’engine détient le socket Docker. docker-compose.yml monte le socket Docker de l’hôte dans le service engine, car l’engine construit et lance un conteneur de scan pour chaque job. Tout processus qui peut accéder à ce socket peut démarrer un conteneur montant le système de fichiers de l’hôte. L’engine dispose donc en pratique des privilèges root sur l’hôte qui l’exécute.
Il n’y a pas d’écran de connexion. Le backend est livré sans authentification applicative. L’accès au port donne accès à vos résultats et au crédit de votre fournisseur.
Le code analysé ne vous appartient souvent pas. Pointer les agents vers un dépôt tiers revient à exécuter le build de ce dépôt sur votre machine, en tant que root et avec un accès réseau.
Si vous avez lu pourquoi les agents de programmation doivent s’exécuter dans une VM jetable, il s’agit du même modèle de menace, mais plus puissant. Fournissez à open-kritt un VPS qui n’héberge rien d’autre, puis administrez ce VPS depuis un compte utilisateur distinct doté des privilèges minimaux plutôt que depuis root.
Ce que fait réellement open-kritt
open-kritt (le dépôt est Kritt-ai/open-kritt et est distribué sous licence AGPL-3.0) décompose la recherche de vulnérabilités en petites tâches, exécute ces tâches en parallèle avec plusieurs agents d’IA, puis déduplique et classe les résultats. Vous définissez un workflow sous la forme d’une chaîne de prompts ciblés. Chaque étape reçoit le contexte structuré produit par les étapes précédentes. La cible de l’analyse est un dépôt Git distant ou local. Le moteur d’analyse est Codex ou Claude Code. Lorsqu’un candidat est détecté, des post-scripts facultatifs peuvent tenter de le valider ou de créer une preuve de concept.
Vous obtenez à la fin une liste classée de candidats. Considérez-la comme une file de triage, et non comme un rapport.
Ce qu’il vous faut avant de commencer
- Un VPS sous Ubuntu 24.04, Debian 12 ou Rocky Linux 9. La documentation d’installation indique que ces distributions ont été testées sur x86_64 et ARM64.
- Docker Engine avec le plugin Compose.
- Node.js 20 ou version ultérieure sur l’hôte, car la CLI
./kritts’exécute sur l’hôte et non dans un conteneur. - Un fournisseur de modèles : un compte Codex, ou
OPENAI_API_KEY,CODEX_API_KEY,ANTHROPIC_API_KEYouOPENROUTER_API_KEY. GITHUB_TOKENuniquement si vous prévoyez d’analyser des dépôts privés. Le.env.examplefourni l’indique clairement : un token GitHub seul ne permet pas d’exécuter des analyses.
Installer d’abord Docker et Node 20
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USERDéconnectez-vous, puis reconnectez-vous pour appliquer l’appartenance au nouveau groupe. Vérifiez ensuite que le plugin Compose est présent.
docker compose versionUne chaîne de version indique que Compose est installé comme plugin. docker: 'compose' is not a docker command indique que vous utilisez à la place l’ancien binaire autonome docker-compose, et open-kritt appelle docker compose. L’appartenance au groupe docker donne des privilèges équivalents à ceux de root sur l’hôte. Ajoutez-y uniquement le compte qui exécute open-kritt. Pour consulter la procédure complète, voir exécuter Docker sur un VPS.
Ubuntu 24.04 fournit Node 18 dans son propre dépôt, et la CLI s’arrête avec toute version antérieure à 20. Utilisez NodeSource.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -vnode -v doit afficher v20. ou une version ultérieure. Sur Rocky Linux 9, l’équivalent est sudo dnf module enable nodejs:20 -y, suivi de sudo dnf install -y nodejs.
Cloner open-kritt et figer une release marquée
git clone https://github.com/Kritt-ai/open-kritt
cd open-kritt
git fetch --tags
git tag --list
git checkout v1.3.0main évolue avec vous. Un tag, non. En août 2026, le tag le plus récent est v1.3.0, publié le 4 août 2026, et git tag --list affiche les tags disponibles le jour du clonage. Le checkout d’un tag place le dépôt en état detached HEAD, ce qui convient ici : vous utilisez ce clone comme un déploiement figé, et non comme une branche sur laquelle vous effectuez des commits. Pour mettre à niveau le déploiement ultérieurement, lisez les notes de release, puis exécutez git fetch --tags, faites le checkout du nouveau tag et exécutez à nouveau ./kritt start, car start reconstruit les images.
N’exécutez pas ./kritt avec sudo. La documentation est explicite à ce sujet. La CLI gère les répertoires d’identifiants propres au projet sous .data/. Une exécution avec root laisse donc ces répertoires appartenir à root, et l’exécution normale suivante ne peut plus y écrire.
Configurer l’accès aux modèles avec ./kritt setup
./kritt setupLa commande crée .env à partir de .env.example s’il n’existe pas, affiche l’état de chaque identifiant d’authentification et permet de les définir ou de les supprimer. Elle n’affiche jamais leurs valeurs dans le terminal. .env et le fichier d’identifiants du moteur sont tous deux créés avec le mode 0600.
Si vous préférez le faire manuellement :
cp .env.example .env
chmod 600 .env
mkdir -p .data/codex
chmod 700 .data/codexModifiez ensuite la clé du fournisseur dans .env et conservez le mode 0600 du fichier. Dans les deux cas, un identifiant d’authentification fonctionnel du fournisseur se trouve désormais sur ce serveur. C’est une raison supplémentaire de ne rien héberger d’autre sur cette machine. Créez une clé dédiée uniquement à ce projet, afin que sa révocation ultérieure ne désactive rien d’important pour vous. Éviter de laisser les secrets à la portée des agents d’IA présente cette pratique plus largement.
Définissez un plafond de dépenses chez le fournisseur avant le premier scan
open-kritt est conçu pour distribuer les tâches, et cette distribution détermine vos dépenses. Les valeurs par défaut de .env.example dans la version v1.3.0 sont prudentes : ENGINE_WORKER_COUNT=2, décrit dans le fichier comme une valeur par défaut prudente pour une petite machine dotée de 2 vCPU, et ENGINE_MAX_CONCURRENT_SCANS=1. Au-dessus figurent ENGINE_WORKERS_PER_ACCOUNT=15, le nombre maximal d’appels simultanés au modèle root autorisés sur un même compte fournisseur, et ENGINE_CODEX_MAX_SUBAGENTS_PER_SESSION=5, car une session Codex peut exécuter jusqu’à cinq agents enfants. Si vous augmentez le nombre de workers sur un VPS plus puissant, le nombre d’appels au modèle en cours augmente également.
Rien dans le dépôt ne plafonne vos dépenses. .env.example ne contient aucun paramètre de budget. Les seules conditions d’arrêt propres au moteur sont ces limites de workers et ENGINE_HARNESS_TIMEOUT_SECONDS, qui vaut par défaut 7200 secondes par exécution du harness. Le plafond doit donc être défini chez le fournisseur. Ouvrez la console de votre fournisseur et définissez une limite mensuelle stricte avant le premier scan, pas après. Contrôler le coût d’un agent IA sur un VPS présente les paramètres propres à chaque fournisseur.
Il existe également un mécanisme de freinage local. La définition de ENGINE_WORKER_COUNT=0 suspend la récupération de nouveaux jobs, et vous pouvez modifier les mêmes valeurs de workers dans l’écran Settings une fois la stack démarrée.
Ce guide n’indique aucun prix par scan, car le coût dépend de la taille du dépôt, du workflow que vous créez et du modèle utilisé. Exécutez un scan sur un petit dépôt, puis consultez la page d’utilisation de votre fournisseur avant de lancer un scan sur un dépôt volumineux.
Démarrer la stack et vérifier son état
./kritt startCette commande vérifie .env et au moins un identifiant, puis exécute docker compose up --build. Le premier build est lent, car il construit les images du frontend, du backend, de l’engine, de la vue executor et de la base de données. Il s’exécute aussi au premier plan. La fermeture de la session SSH arrête donc la stack. Lancez-la dans tmux, ou démarrez-la en mode détaché une fois le premier build terminé. Aucune de ces méthodes ne redémarre automatiquement la stack après un reboot. Si vous voulez qu’elle redémarre après celui du serveur, le modèle d’unité systemd présenté dans maintenir un agent auto-hébergé actif après les reboots s’applique directement.
docker compose up -d --build
docker compose psdocker compose ps doit lister open-kritt-frontend, open-kritt-backend, open-kritt-engine, open-kritt-executor-view et open-kritt-db. Vérifiez ensuite que le backend répond sur le serveur lui-même.
curl -s http://127.0.0.1:3002/api/healthUne réponse JSON signifie que le backend est actif. Failed to connect to 127.0.0.1 port 3002: Connection refused signifie que ce n’est pas le cas, et docker compose logs backend indiquera pourquoi. Arrêtez tous les composants avec docker compose down depuis le répertoire du repository.
Une autre possibilité, facultative : docker compose exec backend npm run seed charge des données de démonstration. C’est un moyen simple de consulter l’interface avant de lancer un vrai scan payant.
Accéder à l’interface sur le port 5173 via un tunnel SSH
Chaque service du fichier compose est lié à 127.0.0.1 par défaut : le frontend sur 5173, le backend sur 3002, la vue de l’exécuteur sur 8090 et Postgres sur 5432. Ne modifiez pas ces bindings. Transférez le port via SSH depuis votre propre machine.
ssh -N -L 5173:127.0.0.1:5173 you@your-server-ipOuvrez http://localhost:5173 dans votre navigateur local pendant l’exécution de cette commande. -N signifie que la connexion assure le forwarding sans ouvrir de shell. Ajoutez un second -L 8090:127.0.0.1:8090 à la même commande pour accéder également à la vue de l’exécuteur.
Vous pourriez être tenté de définir FRONTEND_BIND_ADDRESS=0.0.0.0 et de vous passer du tunnel. Ne le faites pas. Le backend n’a pas d’écran de connexion. Toute personne qui accède à cette page peut lancer des scans et consommer le crédit de votre fournisseur. Un autre problème se pose : un port de conteneur publié est traité avant l’application de la stratégie par défaut d’ufw. Une règle ufw deny 5173 semble donc correcte, mais elle ne bloque rien. Les ports Docker qui contournent ufw présente la chaîne de règles à l’origine de ce comportement.
Dimensionnement du VPS
ENGINE_MIN_FREE_STORAGE_GB vaut 20 par défaut. Le moteur refuse de démarrer un nouveau conteneur de scan par tâche lorsque l’espace de stockage disponible passe en dessous de cette valeur. Les images construites, le cache des checkouts, les données Postgres et les espaces de travail des tâches résident tous sur le même disque. Un VPS de 20 GB ne démarre donc jamais de scan. Considérez 40 GB comme le minimum et prévoyez davantage si vous analysez de gros dépôts.
Le dimensionnement de la mémoire repose sur un calcul simple. ENGINE_MEMORY_RESERVE_GB=2 réserve de la mémoire pour le moteur, la base de données, l’API et les surcharges de courte durée. Chaque runner de scan dispose d’une réservation et d’une limite stricte définies par ENGINE_SCAN_RUNNER_MEMORY_MB=1536. Deux workers nécessitent donc environ 5 GB avant même le lancement des autres services. Le moteur n’autorise que les runners qui tiennent dans le budget restant. Sur une petite machine, les scans sont ainsi mis en file d’attente au lieu d’échouer. C’est un comportement bien préférable à un arrêt par l’out-of-memory killer.
Deux paramètres de purge valent true par défaut : ENGINE_AUTO_PRUNE_DOCKER_BUILD_CACHE et ENGINE_AUTO_PRUNE_UNUSED_DOCKER_IMAGES. Une fois la tâche terminée, le moteur supprime le cache de build inutilisé, les images inutilisées et les conteneurs de scan arrêtés. Les images référencées par un conteneur en cours d’exécution, les bind mounts, les données de la base de données, les credentials et les volumes sont conservés. C’est une raison supplémentaire de ne pas partager l’hôte : un pruner que vous n’avez pas configuré s’exécute sur ce Docker daemon.
Les paramètres du moteur que la plupart des utilisateurs finissent par modifier
ENGINE_WORKER_COUNT: nombre total de worker slots partagés entre les étapes de scan et le post-traitement. Définissez-le à 0 pour suspendre la prise en charge des nouvelles tâches.ENGINE_MAX_CONCURRENT_SCANS: nombre de scans admis simultanément. Les scans en attente patientent jusqu’à ce que le pool actif soit vide.ENGINE_MAX_WORKERS_PER_SCAN: à 0, les slots agrégés sont répartis équitablement entre les scans.ENGINE_HARNESS_TIMEOUT_SECONDS: 7200 par défaut. Il s’agit de la durée maximale d’une tâche unique qui s’emballe.ENGINE_MIN_FREE_STORAGE_GB: seuil minimal de stockage.ENGINE_IGNORE_LOW_STORAGE=truedésactive cette protection, et le fichier avertit que le disque de l’hôte peut alors être rempli.ENGINE_SCAN_RUNNER_MEMORY_MB: limite stricte de mémoire par runner. 0 supprime cette limite.
Analyser un dépôt local sans l’exposer
LOCAL_REPOS_PATH est défini par défaut sur ./local_repos et monté par liaison dans les conteneurs backend et engine à /local_repos. Un dépôt que vous placez dans ce dossier sur l’hôte apparaît donc immédiatement dans les conteneurs. Utilisez un clone propre, pas votre arborescence de travail. Le conteneur du job dispose d’une copie inscriptible, de root à l’intérieur du conteneur et d’un accès Internet sortant. Tout ce qui se trouve dans cette copie peut donc être modifié ou envoyé hors du serveur. Supprimez les fichiers .env et les clés privées avant de copier un projet.
Ce que vous obtenez et ce que vous n’obtenez pas
Vous obtenez des résultats candidats classés. Vous n’obtenez pas des vulnérabilités vérifiées. Le classement et la déduplication déterminent l’ordre de votre file de triage. Ils ne prouvent pas qu’une entrée est réelle. Les post-scripts peuvent tenter une validation et construire une preuve de concept. C’est le signal le plus fort fourni par l’outil. Toutefois, l’échec d’un post-script ne prouve pas que le résultat est faux. Une personne doit quand même examiner chaque candidat.
Ce guide ne prétend pas indiquer combien de bugs réels open-kritt détecte, car nous ne l’avons pas mesuré. Toute personne qui cite un taux de détection pour votre codebase ne l’a pas exécuté sur votre codebase. Commencez par scanner un repository que vous connaissez déjà bien. Les résultats que vous pouvez évaluer vous-même constituent la calibration la moins coûteuse.
L’autorisation est encore plus importante ici qu’avec la plupart des outils auto-hébergés. Les agents compilent et exécutent du code, et accèdent au réseau. Une étape de preuve de concept peut donc toucher des systèmes en production. Dirigez l’outil vers du code dont vous êtes propriétaire ou que vous êtes mandaté pour tester. Définissez par écrit le périmètre de la cible avant toute exécution. Si vous configurez ANTHROPIC_API_KEY et utilisez le moteur Claude Code, les pratiques de sandboxing présentées dans exécuter Claude Code en toute sécurité sur un VPS s’appliquent également à ces agents.
FAQ
Pourquoi open-kritt a-t-il besoin de son propre VPS ?
Parce que ses agents d’analyse s’exécutent en tant que root dans des conteneurs de tâches jetables, avec des copies inscriptibles de votre code et un accès direct à Internet. Le service engine monte également le socket Docker de l’hôte afin de pouvoir lancer un conteneur par tâche. Tout processus qui accède à ce socket peut démarrer un conteneur montant le système de fichiers de l’hôte. Il faut donc considérer toute la stack comme ayant les privilèges root sur son hôte. Sur un VPS dédié, ce compromis est acceptable et la reconstruction du serveur ne vous coûte rien. Sur votre poste de travail quotidien, vos clés SSH et vos profils de navigateur se retrouvent dans la même boundary de confiance que le code analysé.
Puis-je exposer le port 5173 au lieu d’utiliser un tunnel SSH ?
Vous ne devriez pas le faire. Le backend est livré sans authentification applicative. Le port est donc la seule protection entre Internet, vos résultats d’analyse et vos crédits fournisseur. Pour cette raison, le fichier compose lie chaque service à 127.0.0.1. Exécutez plutôt ssh -N -L 5173:127.0.0.1:5173 you@your-server-ip, puis ouvrez http://localhost:5173 en local. Une règle ufw ne suffit pas, car un port Docker publié est traité avant l’application de la policy par défaut d’ufw.
Comment empêcher open-kritt de dépenser plus que prévu ?
Définissez une limite stricte dans la console de votre fournisseur de modèles avant le premier scan, car open-kritt ne possède pas de réglage de budget. Conservez les valeurs de concurrence fournies par défaut lors des premières exécutions, ENGINE_WORKER_COUNT=2 et ENGINE_MAX_CONCURRENT_SCANS=1. Gardez à l’esprit qu’un compte fournisseur autorise par défaut jusqu’à 15 appels concurrents au modèle root, tandis qu’une session Codex peut exécuter jusqu’à cinq agents enfants. ENGINE_WORKER_COUNT=0 suspend la prise en charge de nouvelles tâches. C’est l’arrêt local le plus rapide.
Quelle version dois-je récupérer ?
Un tag, jamais main. git fetch --tags suivi de git tag --list affiche les versions disponibles, et v1.3.0, publié le 4 August 2026, est le plus récent au moment de la rédaction. Épingler une version garantit qu’une reconstruction effectuée plusieurs mois plus tard utilise la même stack. Cela fait de la mise à niveau une décision prise après lecture des release notes, plutôt qu’un effet secondaire du clonage effectué un autre jour.
Un scan ne démarre jamais. Que dois-je vérifier ?
Vérifiez d’abord l’espace disque disponible, car l’engine ne lance pas de conteneur de scan par tâche lorsque l’espace libre est inférieur à ENGINE_MIN_FREE_STORAGE_GB, dont la valeur par défaut est 20 GB. Vérifiez ensuite que ENGINE_WORKER_COUNT n’est pas égal à 0, car cette valeur suspend la prise en charge de nouvelles tâches. Confirmez ensuite qu’un credential de modèle est bien configuré en exécutant ./kritt setup, car un GITHUB_TOKEN seul ne peut pas exécuter de scans. docker compose logs engine indique la raison pour laquelle la tâche a été ignorée.