SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-13

Come eseguire open-kritt su un VPS in sicurezza

Configura open-kritt con Docker Compose, blocca una release, usa il tunnel SSH verso la UI sulla porta 5173 e imposta il budget del provider prima della scansione.

Perché eseguire open-kritt su un VPS e non sul laptop

Esegui open-kritt su un server che puoi eliminare e ricreare. Lo strumento esegue i propri agenti di analisi come root all'interno di container di job temporanei, assegna a ciascuno una copia scrivibile del codice e l'accesso diretto a Internet, quindi monta il socket Docker dell'host nel servizio engine. Questo compromesso è ragionevole su una macchina dedicata al job. È una scelta rischiosa sulla macchina che contiene le tue chiavi SSH.

Quattro caratteristiche della configurazione predefinita motivano questa raccomandazione, e tutte e quattro provengono dal README e dal file compose del progetto.

Gli agenti devono avere ampi privilegi. Il README specifica che gli agenti con strumenti eseguono i propri processi come root all'interno di container di job temporanei, con copie scrivibili dei repository e accesso diretto a Internet. In questo modo possono installare strumenti, compilare i target, eseguire test e creare proof of concept. Una scansione non è un linter che legge i file. È esecuzione arbitraria di codice richiesta da te. L'accesso a Internet comporta rischi in entrambe le direzioni: qualsiasi contenuto scaricato da un agente durante l'analisi di un target è testo non attendibile che entra nel suo prompt. È la stessa esposizione che accetti quando affidi a un agente le proprie ricerche sul Web.

L'engine contiene il socket Docker. docker-compose.yml monta il socket Docker dell'host nel servizio engine, perché l'engine crea e avvia un container di scansione per ogni job. Qualsiasi processo che può raggiungere quel socket può avviare un container con il filesystem dell'host montato. Di fatto, quindi, l'engine dispone dei privilegi di root sull'host su cui viene eseguito.

Non esiste una schermata di accesso. Il backend viene distribuito senza autenticazione applicativa. Chiunque possa accedere alla porta può accedere ai risultati delle scansioni e al credito del tuo provider.

Il codice analizzato spesso non è tuo. Indicare agli agenti un repository di terze parti significa eseguire la build di quel repository sulla tua macchina, come root e con accesso alla rete.

Se hai letto perché gli agenti di coding devono essere eseguiti in una VM temporanea, questo è lo stesso modello di minaccia, ma più severo. Dedica a open-kritt un VPS su cui non eseguire altro e gestisci quel VPS tramite un account utente separato con privilegi minimi, invece di usare root.

Cosa fa effettivamente open-kritt

open-kritt (il repository è Kritt-ai/open-kritt ed è distribuito con licenza AGPL-3.0) suddivide la ricerca di vulnerabilità in attività più piccole, esegue queste attività in parallelo tramite agenti AI, quindi elimina i duplicati e assegna una priorità ai risultati. Si definisce un workflow come una catena di prompt mirati. Ogni passaggio riceve il contesto strutturato prodotto dai passaggi precedenti. La destinazione della scansione è un repository git remoto o locale. Il motore di analisi è Codex o Claude Code. Quando viene individuato un candidato, gli script post-scansione opzionali possono tentare di convalidarlo o creare una proof of concept.

Il risultato finale è un elenco ordinato di candidati. Usalo come coda di triage, non come report.

Prerequisiti

  • Una VPS con Ubuntu 24.04, Debian 12 o Rocky Linux 9. La documentazione di installazione indica queste distribuzioni come quelle testate, su x86_64 e ARM64.
  • Docker Engine con il plugin Compose.
  • Node.js 20 o versioni successive sull'host, perché la CLI ./kritt viene eseguita sull'host e non all'interno di un container.
  • Un provider di modelli: un accesso Codex oppure OPENAI_API_KEY, CODEX_API_KEY, ANTHROPIC_API_KEY o OPENROUTER_API_KEY.
  • GITHUB_TOKEN solo se prevedi di analizzare repository privati. Il file .env.example incluso lo specifica chiaramente: un token GitHub da solo non è sufficiente per eseguire le scansioni.

Installa prima Docker e Node 20

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER

Disconnettiti e accedi di nuovo per applicare l'appartenenza al nuovo gruppo, quindi verifica che il plugin Compose sia presente.

docker compose version

Una stringa di versione indica che Compose è installato come plugin. docker: 'compose' is not a docker command indica invece che è presente il vecchio binario autonomo docker-compose, mentre open-kritt richiama docker compose. L'appartenenza al gruppo docker equivale all'accesso root sull'host, quindi aggiungi a questo gruppo soltanto l'account che esegue open-kritt. Per la procedura completa, consulta eseguire Docker su un VPS.

Ubuntu 24.04 distribuisce Node 18 nel proprio repository, mentre la CLI termina l'esecuzione con versioni inferiori a 20. Usa NodeSource.

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -v

node -v deve stampare v20. o una versione successiva. Su Rocky Linux 9 l'equivalente è sudo dnf module enable nodejs:20 -y seguito da sudo dnf install -y nodejs.

Clonare open-kritt e bloccare una release contrassegnata

git clone https://github.com/Kritt-ai/open-kritt
cd open-kritt
git fetch --tags
git tag --list
git checkout v1.3.0

main viene aggiornato insieme al ramo. Un tag non viene aggiornato. Ad agosto 2026, il tag più recente è v1.3.0, pubblicato il 4 agosto 2026, mentre git tag --list mostra ciò che esiste nel giorno in cui si esegue il clone. Il checkout di un tag lascia il repository nello stato detached HEAD, che in questo caso è corretto: questo clone viene usato come deployment bloccato su una versione, non come un ramo sul quale eseguire commit. Per aggiornare in seguito, leggere le note di rilascio, quindi eseguire git fetch --tags, passare al nuovo tag ed eseguire di nuovo ./kritt start, perché start ricrea le immagini.

Non eseguire ./kritt con sudo. La documentazione lo specifica esplicitamente. La CLI gestisce le directory delle credenziali locali del progetto in .data/. Eseguendola come root, queste directory diventano di proprietà di root e la successiva esecuzione con un account normale non può scrivervi.

Configura l'accesso ai modelli con ./kritt setup

./kritt setup

Il comando crea .env da .env.example se non esiste, visualizza lo stato di ogni credenziale e consente di impostarle o rimuoverle. Non stampa mai i valori nel terminale. Sia .env sia il file delle credenziali del motore vengono scritti con modalità 0600.

Se preferisci eseguire la configurazione manualmente:

cp .env.example .env
chmod 600 .env
mkdir -p .data/codex
chmod 700 .data/codex

Inserisci quindi la chiave del provider in .env e lascia il file con modalità 0600. In entrambi i casi, sul server è ora presente una credenziale funzionante del provider. Questo è un motivo in più per non ospitare altro su quel server. Crea una chiave dedicata esclusivamente a questo progetto, in modo che la sua revoca non interrompa nulla di importante. Tenere i secret fuori dalla portata degli agenti AI descrive questa buona pratica in modo più ampio.

Impostare un limite di spesa presso il provider prima della prima scansione

open-kritt è progettato per distribuire il carico in parallelo, ed è proprio questa distribuzione a determinare i costi. I valori predefiniti in .env.example nella versione v1.3.0 sono prudenti: ENGINE_WORKER_COUNT=2, descritto nel file come valore predefinito prudente per una macchina con 2 vCPU, e ENGINE_MAX_CONCURRENT_SCANS=1. Al di sopra di questi valori si trovano ENGINE_WORKERS_PER_ACCOUNT=15, il numero massimo di chiamate simultanee al modello root consentite su un singolo account del provider, e ENGINE_CODEX_MAX_SUBAGENTS_PER_SESSION=5, perché una sessione Codex può eseguire fino a cinque agenti figli. Se aumenti il numero di worker su un VPS più grande, aumenta di conseguenza anche il numero di chiamate al modello in corso.

Nel repository non esiste alcun limite alla spesa. In .env.example non è presente alcuna impostazione per il budget. Le condizioni di arresto proprie del motore sono i limiti dei worker e ENGINE_HARNESS_TIMEOUT_SECONDS, che imposta per impostazione predefinita 7200 secondi per ogni esecuzione dell'harness. Il limite massimo deve quindi essere configurato presso il provider. Apri la console del provider e imposta un limite mensile rigido prima della prima scansione, non dopo. Controllare i costi di un agente AI su un VPS descrive le impostazioni disponibili per ciascun provider.

È disponibile anche un freno locale. L'impostazione ENGINE_WORKER_COUNT=0 sospende il prelievo di nuovi job, e gli stessi valori dei worker possono essere modificati nella schermata Settings dopo l'avvio dello stack.

Questa guida non indica un prezzo per scansione, perché il costo dipende dalle dimensioni del repository, dal workflow che crei e dal modello utilizzato. Esegui una scansione su un singolo repository di piccole dimensioni, quindi consulta la pagina dei consumi del provider prima di usarla su repository più grandi.

Avviare lo stack e verificarne lo stato

./kritt start

Questo controlla .env e almeno una credenziale, quindi esegue docker compose up --build. La prima build è lenta perché crea le immagini del frontend, del backend, dell'engine, della vista dell'executor e del database. Inoltre, l'esecuzione avviene in primo piano: se si chiude la sessione SSH, lo stack viene arrestato. Avviarlo all'interno di tmux oppure eseguirlo in modalità detached dopo il completamento della prima build. Nessuna delle due modalità riavvia automaticamente lo stack dopo un reboot. Se si vuole riattivare lo stack dopo il riavvio del server, il modello di unità systemd descritto in mantenere in esecuzione un agent self-hosted dopo i reboot si applica direttamente.

docker compose up -d --build
docker compose ps

docker compose ps dovrebbe elencare open-kritt-frontend, open-kritt-backend, open-kritt-engine, open-kritt-executor-view e open-kritt-db. Verificare quindi che il backend risponda dal server stesso.

curl -s http://127.0.0.1:3002/api/health

Una risposta JSON indica che il backend è attivo. Failed to connect to 127.0.0.1 port 3002: Connection refused indica che non lo è, mentre docker compose logs backend mostra il motivo. Arrestare tutto con docker compose down dalla directory del repository.

Un'ultima opzione: docker compose exec backend npm run seed carica dati dimostrativi. È un modo semplice per esaminare l'interfaccia prima di sostenere costi per una scansione reale.

Accedere all’interfaccia sulla porta 5173 tramite un tunnel SSH

Ogni servizio nel file compose si associa a 127.0.0.1 per impostazione predefinita: il frontend sulla porta 5173, il backend sulla porta 3002, la vista dell’executor sulla porta 8090 e Postgres sulla porta 5432. Lascia invariati questi binding e inoltra la porta tramite SSH dal tuo computer.

ssh -N -L 5173:127.0.0.1:5173 you@your-server-ip

Mentre il comando è in esecuzione, apri http://localhost:5173 nel browser locale. -N indica che la connessione trasporta l’inoltro e non apre una shell. Quando vuoi rendere disponibile anche la vista dell’executor, aggiungi un secondo -L 8090:127.0.0.1:8090 allo stesso comando.

La soluzione più immediata sembra impostare FRONTEND_BIND_ADDRESS=0.0.0.0 e saltare il tunnel. Non farlo. Il backend non dispone di una schermata di accesso, quindi chiunque raggiunga quella pagina può avviare scansioni e consumare il credito del provider. Esiste anche un secondo problema: una porta del container pubblicata viene gestita prima che si applichi la policy predefinita di ufw, quindi una regola ufw deny 5173 può sembrare corretta ma non blocca nulla. Porte Docker che bypassano ufw illustra la catena di regole che causa questo comportamento.

Dimensionamento del VPS

ENGINE_MIN_FREE_STORAGE_GB è impostato su 20 per impostazione predefinita e il motore rifiuta di avviare un nuovo container di scansione per job quando lo spazio di archiviazione libero scende al di sotto di questo valore. Le immagini compilate, la cache dei checkout, i dati PostgreSQL e gli workspace dei job si trovano tutti sullo stesso disco. Per questo motivo, un VPS da 20 GB non avvia mai una scansione. Considera 40 GB come valore minimo e assegna più spazio se esegui scansioni di repository di grandi dimensioni.

La memoria segue un calcolo semplice. ENGINE_MEMORY_RESERVE_GB=2 riserva memoria per il motore, il database, l'API e l'overhead temporaneo. Ogni runner di scansione ha inoltre una prenotazione e un limite rigido pari a ENGINE_SCAN_RUNNER_MEMORY_MB=1536. Due worker richiedono quindi circa 5 GB prima dell'avvio degli altri componenti. Il motore avvia solo i runner che rientrano nella memoria rimanente. Su un sistema di piccole dimensioni, le scansioni vengono quindi accodate invece di fallire. Questo comportamento è molto preferibile all'intervento dell'out-of-memory killer.

Due impostazioni di prune sono impostate su true per impostazione predefinita: ENGINE_AUTO_PRUNE_DOCKER_BUILD_CACHE e ENGINE_AUTO_PRUNE_UNUSED_DOCKER_IMAGES. Al termine di un task, il motore rimuove la build cache inutilizzata, le immagini inutilizzate e i container di scansione arrestati. Le immagini utilizzate da un container in esecuzione, i bind mount, i dati del database, le credenziali e i volumi vengono conservati. È un ulteriore motivo per non condividere l'host: un pruner che non hai configurato viene eseguito sul relativo Docker daemon.

Le impostazioni del motore che la maggior parte degli utenti finisce per modificare
  • ENGINE_WORKER_COUNT: numero totale di slot worker condivisi tra i passaggi di scansione e il post-processing. Impostalo su 0 per sospendere la presa in carico di nuovi job.
  • ENGINE_MAX_CONCURRENT_SCANS: numero di scansioni ammesse contemporaneamente. Le scansioni in coda attendono finché il pool attivo non è vuoto.
  • ENGINE_MAX_WORKERS_PER_SCAN: con valore 0, gli slot aggregati vengono distribuiti in modo uniforme tra le scansioni.
  • ENGINE_HARNESS_TIMEOUT_SECONDS: 7200 per impostazione predefinita. È la durata massima di un singolo job fuori controllo.
  • ENGINE_MIN_FREE_STORAGE_GB: soglia minima di spazio di archiviazione. ENGINE_IGNORE_LOW_STORAGE=true disabilita la protezione e il file avvisa che il disco dell'host può riempirsi.
  • ENGINE_SCAN_RUNNER_MEMORY_MB: limite rigido di memoria per runner. 0 rimuove il limite.

Scansione di un repository locale senza esporlo

LOCAL_REPOS_PATH ha come impostazione predefinita ./local_repos ed è montato con bind nei container backend ed engine in /local_repos. Un repository copiato in quella directory sull'host diventa quindi immediatamente visibile nei container. Usa un clone appena creato, non il tuo working tree. Il container del job riceve una copia scrivibile, dispone dell'utente root al proprio interno e ha accesso a Internet in uscita. Qualsiasi elemento presente in quella copia può quindi essere modificato o inviato all'esterno del server. Rimuovi i file .env e le chiavi private prima di copiare un progetto nella directory.

Cosa si ottiene e cosa no

Si ottiene un elenco ordinato di risultati potenziali. Non si ottengono vulnerabilità verificate. L'ordinamento e la deduplicazione determinano l'ordine della coda di triage. Non dimostrano che un risultato sia reale. Gli script post-scansione possono tentare la validazione e creare una proof of concept. Questo è il segnale più forte fornito dallo strumento. Tuttavia, il fallimento di uno script post-scansione non dimostra che il risultato sia falso. Una persona deve comunque esaminare ogni risultato potenziale.

Questa guida non dichiara quanti bug reali open-kritt rilevi, perché non è stata eseguita alcuna misurazione. Chiunque citi un tasso di rilevamento per la vostra codebase non ha eseguito lo strumento sulla vostra codebase. Eseguite prima la scansione di un repository che conoscete già bene. I risultati che potete valutare personalmente sono il metodo di calibrazione più economico disponibile.

L'autorizzazione è ancora più importante in questo caso rispetto alla maggior parte degli strumenti self-hosted. Gli agenti compilano ed eseguono codice e accedono alla rete, quindi una fase di proof of concept può interagire con sistemi in produzione. Indicate codice di vostra proprietà o per il quale avete un incarico di test, e definite per iscritto l'ambito del target prima di eseguire qualsiasi operazione. Se configurate ANTHROPIC_API_KEY e utilizzate il motore Claude Code, le procedure di sandboxing descritte in eseguire Claude Code in sicurezza su un VPS si applicano anche a questi agenti.

FAQ

Perché open-kritt richiede un VPS dedicato?

Perché i suoi agenti di analisi vengono eseguiti come root all'interno di container di job temporanei, con copie scrivibili del codice e accesso diretto a Internet. Inoltre, il servizio engine monta il socket Docker dell'host per poter avviare un container per ogni job. Qualsiasi processo che raggiunge quel socket può avviare un container con il filesystem dell'host montato. Per questo motivo, l'intero stack deve essere considerato equivalente a root sull'host. Su un VPS dedicato è un compromesso accettabile e la ricostruzione del server non comporta costi. Sulla workstation che usi ogni giorno, invece, le chiavi SSH e i profili del browser si trovano nello stesso perimetro di attendibilità del codice sottoposto ad analisi.

Posso esporre la porta 5173 invece di usare un tunnel SSH?

No. Il backend viene distribuito senza autenticazione applicativa. La porta è quindi l'unica barriera tra Internet, i risultati delle analisi e il credito del provider. Per questo il file compose associa ogni servizio a 127.0.0.1. Esegui ssh -N -L 5173:127.0.0.1:5173 you@your-server-ip e apri localmente http://localhost:5173 nel browser. Una regola ufw non è un'alternativa equivalente, perché una porta pubblicata da Docker viene gestita prima che si applichi la policy predefinita di ufw.

Come posso impedire a open-kritt di spendere più del previsto?

Imposta un limite rigido nella console del provider del modello prima della prima analisi, perché open-kritt non dispone di una propria impostazione del budget. Mantieni i valori predefiniti di concorrenza forniti inizialmente, ENGINE_WORKER_COUNT=2 e ENGINE_MAX_CONCURRENT_SCANS=1, e ricorda che, per impostazione predefinita, un account del provider consente fino a 15 chiamate concorrenti al modello eseguite come root, mentre una sessione Codex può eseguire fino a cinque agenti secondari. ENGINE_WORKER_COUNT=0 sospende il prelievo di nuovi job ed è il modo più rapido per interrompere localmente l'esecuzione.

Quale versione devo estrarre?

Un tag, mai main. git fetch --tags seguito da git tag --list mostra ciò che è disponibile, mentre v1.3.0, pubblicato il 4 agosto 2026, è il più recente al momento della stesura. Fissare una versione garantisce che una ricostruzione eseguita mesi dopo produca lo stesso stack. Inoltre, l'aggiornamento diventa una decisione presa dopo aver letto le note di rilascio, invece di essere una conseguenza casuale della clonazione eseguita in un giorno diverso.

Un'analisi non viene mai avviata. Cosa devo controllare?

Controlla innanzitutto lo spazio libero su disco, perché engine non avvia il container di analisi dedicato al job quando lo spazio disponibile scende sotto ENGINE_MIN_FREE_STORAGE_GB, che per impostazione predefinita è di 20 GB. Verifica quindi che ENGINE_WORKER_COUNT non sia 0, perché quel valore sospende il prelievo di nuovi job. Infine, conferma che una credenziale del modello sia configurata eseguendo ./kritt setup, perché un GITHUB_TOKEN da solo non può eseguire analisi. docker compose logs engine indica il motivo per cui il job è stato ignorato.