SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-28

Como hospedar o open-kritt com Docker em um VPS

Veja como rodar o open-kritt em um VPS com Docker Compose, fixar uma release, acessar a UI na porta 5173 por túnel SSH e definir o orçamento do provedor.

Por que hospedar o open-kritt num VPS em vez de no seu portátil

Hospede o open-kritt num servidor que possa destruir e reconstruir. A ferramenta executa os seus agentes de análise como root dentro de contentores de tarefas descartáveis, fornece a cada um uma cópia gravável do seu código e acesso direto à Internet, e monta o socket Docker do host no seu serviço de engine. Esta é uma troca razoável num sistema dedicado à tarefa. É uma má escolha na máquina que guarda as suas chaves SSH.

Quatro propriedades da configuração predefinida fundamentam essa recomendação. As quatro vêm do próprio README e do ficheiro compose do projeto.

Os agentes foram concebidos para ter amplos privilégios. O README indica que os agentes com ferramentas são executados como root dentro de contentores de tarefas descartáveis, com cópias graváveis dos repositórios e acesso direto à Internet. Assim, podem instalar ferramentas, compilar alvos, executar testes e criar provas de conceito. Uma análise não é um linter que apenas lê ficheiros. É execução arbitrária de código que você solicitou. Esse acesso à Internet pode ter consequências nos dois sentidos: qualquer conteúdo que um agente obtenha ao investigar um alvo é texto não confiável que entra no seu prompt. É a mesma exposição que você aceita quando entrega a um agente a sua própria pesquisa na Web.

O engine tem acesso ao socket Docker. docker-compose.yml monta o socket Docker do host no serviço de engine, porque o engine cria e inicia um contentor de análise por tarefa. Qualquer processo que consiga aceder a esse socket pode iniciar um contentor que monte o sistema de ficheiros do host. Portanto, o engine tem efetivamente acesso root ao host onde é executado.

Não existe um ecrã de início de sessão. O backend é distribuído sem autenticação da aplicação. Ter acesso à porta significa ter acesso aos seus resultados e aos créditos do seu fornecedor.

O código analisado muitas vezes não é seu. Apontar os agentes para um repositório de terceiros significa executar a compilação desse repositório na sua máquina, como root e com acesso à rede.

Se leu por que os agentes de programação devem ficar numa VM descartável, este é o mesmo modelo de ameaça, mas mais forte. Dê ao open-kritt um VPS sem mais nada instalado e administre esse VPS através de uma conta de utilizador separada com privilégios mínimos, em vez de usar root.

O que o open-kritt faz

open-kritt (o repositório é Kritt-ai/open-kritt e está licenciado sob AGPL-3.0) divide a pesquisa de vulnerabilidades em tarefas pequenas, executa essas tarefas em paralelo com agentes de IA e, em seguida, elimina duplicados e classifica os resultados. Você define um fluxo de trabalho como uma cadeia de prompts focados, e cada etapa recebe contexto estruturado das etapas anteriores. O alvo da verificação é um repositório git remoto ou local. O mecanismo de análise é o Codex ou o Claude Code. Quando surge um candidato, scripts pós-execução opcionais podem tentar validá-lo ou criar uma prova de conceito. Projetar essa cadeia é uma tarefa normal de trabalho com agentes, não de segurança. Portanto, se prompts, ferramentas e passagem de contexto ainda forem conceitos novos, aprender como os agentes são montados contribuirá mais para os seus resultados do que qualquer definição deste guia.

No final, você obtém uma lista classificada de candidatos. Trate-a como uma fila de triagem, não como um relatório.

O que precisa antes de começar

  • Uma VPS com Ubuntu 24.04, Debian 12 ou Rocky Linux 9. A documentação de instalação lista essas distribuições como testadas, em x86_64 e ARM64.
  • Docker Engine com o plugin Compose.
  • Node.js 20 ou mais recente no host, porque a CLI ./kritt é executada no host e não dentro de um contentor.
  • Um fornecedor de modelos: uma conta Codex ou OPENAI_API_KEY, CODEX_API_KEY, ANTHROPIC_API_KEY ou OPENROUTER_API_KEY.
  • GITHUB_TOKEN apenas se pretender analisar repositórios privados. O .env.example fornecido afirma isso claramente: um token do GitHub, por si só, não permite executar análises.

Instale primeiro o Docker e o Node 20

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

Termine a sessão e inicie-a novamente para aplicar a nova associação ao grupo. Em seguida, confirme que o plugin Compose está disponível.

docker compose version

Uma cadeia de versão indica que o Compose está instalado como plugin. docker: 'compose' is not a docker command indica que, em vez disso, tem o binário autónomo docker-compose antigo, e open-kritt chama docker compose. A associação ao grupo docker equivale a root no host. Por isso, adicione-lhe apenas a conta que executa o open-kritt. Para consultar a versão mais detalhada desta configuração, veja executar o Docker numa VPS.

O Ubuntu 24.04 disponibiliza o Node 18 no seu próprio repositório, mas a CLI termina com qualquer versão inferior à 20. Use o NodeSource.

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

node -v deve apresentar v20. ou superior. No Rocky Linux 9, o equivalente é sudo dnf module enable nodejs:20 -y seguido de sudo dnf install -y nodejs.

Clone open-kritt e fixe uma versão marcada

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

main move-se consigo. Uma tag não. Em agosto de 2026, a tag mais recente é v1.3.0, publicada em 4 de agosto de 2026, e git tag --list mostra o que existe no dia em que faz o clone. Fazer checkout de uma tag deixa o repositório no estado detached HEAD, o que é correto neste caso: este clone é tratado como uma implementação com versão fixa, não como uma branch na qual vai fazer commits. Para atualizar mais tarde, leia as notas da versão, execute git fetch --tags, faça checkout da nova tag e execute ./kritt start novamente, porque start recompila as imagens.

Não execute ./kritt com sudo. A documentação é explícita sobre este ponto. A CLI gere diretórios de credenciais específicos do projeto em .data/. Por isso, uma execução como root deixa esses diretórios pertencentes a root e a execução normal seguinte não consegue escrever neles.

Configure o acesso ao modelo com ./kritt setup

./kritt setup

O comando cria .env a partir de .env.example quando este não existe, apresenta o estado de cada credencial e permite defini-las ou removê-las. Nunca apresenta os valores no terminal. Tanto .env como o ficheiro de credenciais do motor são escritos com o modo 0600.

Se preferir fazer isto manualmente:

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

Em seguida, edite a chave do fornecedor em .env e mantenha o ficheiro com o modo 0600. Em qualquer dos casos, passa a existir uma credencial funcional do fornecedor nesse servidor. Este é mais um motivo para o servidor não alojar mais nada. Crie uma chave exclusiva para este projeto, para que a sua revogação posterior não interrompa nada importante. Manter os segredos fora do alcance dos agentes de IA aborda esta prática de forma mais ampla.

Defina um limite de gastos do provedor antes da primeira análise

O open-kritt foi concebido para distribuir tarefas, e é essa distribuição que gera custos. Os valores predefinidos em .env.example na v1.3.0 são conservadores: ENGINE_WORKER_COUNT=2, descrito no ficheiro como um valor predefinido conservador para uma máquina pequena com 2 vCPU, e ENGINE_MAX_CONCURRENT_SCANS=1. Acima destes valores estão ENGINE_WORKERS_PER_ACCOUNT=15, o número máximo de chamadas simultâneas ao modelo raiz permitidas numa conta de provedor, e ENGINE_CODEX_MAX_SUBAGENTS_PER_SESSION=5, porque uma sessão do Codex pode executar até cinco agentes filhos. Se aumentar o número de workers numa VPS maior, o número de chamadas ao modelo em curso também aumenta.

Nada no repositório limita o que pode gastar. Não existe uma definição de orçamento em .env.example. As próprias condições de paragem do motor são esses limites dos workers e ENGINE_HARNESS_TIMEOUT_SECONDS, que por predefinição corresponde a 7200 segundos por execução do harness. Neste contexto, o harness é o ciclo que continua a chamar o modelo com ferramentas e contexto até algo terminar a execução. Por isso, esse timeout é um limite de tempo real para o programa que envolve o modelo, e não um limite para o que o modelo gasta no seu interior. Assim, o teto tem de ser definido no fornecedor. Abra a consola do seu fornecedor e defina um limite mensal rígido antes da primeira análise, não depois. Como controlar os custos de um agente de IA num VPS explica as definições de cada fornecedor.

Também existe um mecanismo de travagem local. Definir ENGINE_WORKER_COUNT=0 pausa a recolha de novos trabalhos, e os mesmos valores de workers podem ser alterados no ecrã Settings depois de a stack estar em execução.

Este guia não indica um preço por análise, porque o custo depende do tamanho do repositório, do workflow que criar e do modelo utilizado. Execute uma análise num repositório pequeno e, em seguida, consulte a página de utilização do provedor antes de analisar algo grande.

Inicie a stack e confirme que está saudável

./kritt start

Isto verifica .env e, pelo menos, uma credencial, e depois executa docker compose up --build. A primeira compilação é demorada porque cria as imagens do frontend, backend, engine, executor view e base de dados. Também é executada em primeiro plano, por isso fechar a sessão SSH para a stack. Inicie-a dentro de tmux ou execute-a em segundo plano depois de a primeira compilação terminar. Nenhuma destas opções sobrevive sozinha a um reboot. Se quiser que a stack volte a arrancar depois de o servidor reiniciar, o padrão de unidade systemd em manter um agente self-hosted em execução após reboots aplica-se diretamente.

docker compose up -d --build
docker compose ps

docker compose ps deve listar open-kritt-frontend, open-kritt-backend, open-kritt-engine, open-kritt-executor-view e open-kritt-db. Depois, confirme que o backend responde no próprio servidor.

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

Uma resposta JSON significa que o backend está ativo. Failed to connect to 127.0.0.1 port 3002: Connection refused significa que não está, e docker compose logs backend indicará o motivo. Pare tudo com docker compose down a partir do diretório do repositório.

Uma opção adicional: docker compose exec backend npm run seed carrega dados de demonstração. É uma forma simples de consultar a interface antes de gastar qualquer valor numa análise real.

Aceder à interface na porta 5173 através de um túnel SSH

Cada serviço no ficheiro compose está associado a 127.0.0.1 por predefinição: o frontend na porta 5173, o backend na porta 3002, a vista do executor na porta 8090 e o Postgres na porta 5432. Não altere essas associações. Encaminhe a porta através de SSH a partir da sua própria máquina.

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

Abra http://localhost:5173 no navegador local enquanto esse comando estiver em execução. -N significa que a ligação transporta o encaminhamento e não abre uma shell. Adicione um segundo -L 8090:127.0.0.1:8090 ao mesmo comando quando também quiser a vista do executor.

A tentação é definir FRONTEND_BIND_ADDRESS=0.0.0.0 e ignorar o túnel. Não faça isso. O backend não tem um ecrã de início de sessão. Qualquer pessoa que aceda a essa página pode iniciar análises e gastar o crédito do seu fornecedor. Em comparação, o Vaultwarden foi concebido para ser exposto à Internet, e protegê-lo continua a depender do token de administrador e do ficheiro de backup, que são mecanismos que o open-kritt não disponibiliza. Existe ainda uma segunda armadilha: uma porta de contentor publicada é processada antes de a política predefinida do ufw ser aplicada. Por isso, uma regra ufw deny 5173 parece correta, mas não bloqueia nada. Portas Docker que contornam o ufw mostra a cadeia de regras que provoca esse comportamento.

Dimensionamento do VPS

ENGINE_MIN_FREE_STORAGE_GB assume 20, e o motor recusa iniciar um novo contentor de análise por tarefa quando o armazenamento livre fica abaixo desse valor. As imagens criadas, a cache do checkout, os dados do Postgres e os espaços de trabalho das tarefas ficam todos no mesmo disco, por isso uma VPS de 20 GB nunca inicia uma análise. Considere 40 GB como o mínimo e atribua mais espaço se analisar repositórios grandes. Evite recuperar espaço no servidor instalando ao lado um serviço que consuma muito armazenamento, porque os requisitos mínimos medidos de RAM e disco nesta comparação entre PhotoPrism e Immich mostram a rapidez com que uma biblioteca multimédia consumiria a margem de armazenamento necessária para uma análise. O mesmo se aplica aos extras decorativos que parecem não ocupar espaço junto de um analisador: uma interface Web que reformula uma biblioteca Jellyfin como uma loja de aluguer dos anos 90 continua a exigir um servidor multimédia completo e os respetivos transcodes no disco subjacente, por isso coloque-a noutro servidor.

A memória segue uma aritmética simples. ENGINE_MEMORY_RESERVE_GB=2 reserva memória para o motor, a base de dados, a API e a sobrecarga temporária, e cada executor de análise tem uma reserva e um limite rígido de ENGINE_SCAN_RUNNER_MEMORY_MB=1536. Dois workers precisam, portanto, de cerca de 5 GB antes de qualquer outro processo arrancar. O motor só inicia os executores que cabem no orçamento restante. Num servidor pequeno, as análises ficam em fila em vez de falharem. Esta é uma situação muito melhor do que a intervenção do out-of-memory killer. A mesma aritmética define o mínimo para qualquer ferramenta que atribua um contentor próprio a cada unidade de trabalho. É por isso que o contentor e o browser do OpenBot para cada colega de trabalho de IA atinge o limite de RAM muito antes de atingir o limite de CPU.

Duas definições de limpeza têm o valor true por predefinição: ENGINE_AUTO_PRUNE_DOCKER_BUILD_CACHE e ENGINE_AUTO_PRUNE_UNUSED_DOCKER_IMAGES. Depois de uma tarefa terminar, o motor remove a cache de compilação não utilizada, as imagens não utilizadas e os contentores de análise parados. As imagens referenciadas por um contentor em execução, os bind mounts, os dados da base de dados, as credenciais e os volumes são preservados. É mais uma razão para não partilhar o host: um processo de limpeza que não configurou está a atuar nesse daemon do Docker.

As definições do motor que a maioria das pessoas acaba por alterar
  • ENGINE_WORKER_COUNT: total de slots de workers partilhados pelas etapas de análise e pós-processamento. Defina-o como 0 para pausar a recolha de novas tarefas.
  • ENGINE_MAX_CONCURRENT_SCANS: número de análises admitidas em simultâneo. As análises em fila aguardam até o conjunto ativo ficar vazio.
  • ENGINE_MAX_WORKERS_PER_SCAN: 0 distribui uniformemente os slots agregados pelas análises.
  • ENGINE_HARNESS_TIMEOUT_SECONDS: 7200 por predefinição. Este é o tempo máximo durante o qual uma única tarefa bloqueada pode continuar em execução.
  • ENGINE_MIN_FREE_STORAGE_GB: limite mínimo de armazenamento. ENGINE_IGNORE_LOW_STORAGE=true desativa a proteção, e o ficheiro avisa que isso pode encher o disco do host.
  • ENGINE_SCAN_RUNNER_MEMORY_MB: limite rígido de memória por executor. 0 remove o limite.

Verificar um repositório local sem o expor

Por predefinição, LOCAL_REPOS_PATH é definido como ./local_repos e montado com bind nos contentores de backend e do motor em /local_repos. Assim, um repositório que coloque nessa pasta no host fica imediatamente disponível dentro dos contentores. Use um clone novo, não a sua árvore de trabalho. O contentor da tarefa tem uma cópia com permissões de escrita, acesso root dentro do próprio contentor e acesso à Internet de saída. Portanto, qualquer conteúdo existente nessa cópia pode ser alterado ou enviado para fora do servidor. Remova os ficheiros .env e as chaves privadas antes de copiar um projeto para lá.

O que recebe e o que não recebe

Você recebe potenciais descobertas ordenadas por classificação. Não recebe vulnerabilidades verificadas. A ordenação e a eliminação de duplicados definem a ordem da sua fila de triagem. Não provam que uma entrada é real. Os scripts posteriores podem tentar validar a descoberta e criar uma prova de conceito. Esse é o sinal mais forte oferecido pela ferramenta. No entanto, um script posterior que falha não é evidência de que a descoberta seja falsa. Uma pessoa continua a analisar cada potencial descoberta. Essa diferença entre um potencial achado e uma prova explica por que vale a pena aproveitar pedir a um agente provas que possa executar novamente: uma descoberta que pode reproduzir quando quiser vale mais do que uma descoberta ordenada que tem de aceitar sem verificar.

Este guia não afirma quantos bugs reais o open-kritt encontra, porque não fizemos essa medição. Quem citar uma taxa de deteção para a sua base de código não executou a ferramenta contra a sua base de código. Comece por analisar um repositório que já conheça bem: as descobertas que consegue avaliar sozinho são a forma mais barata de calibrar a ferramenta.

A autorização é mais importante aqui do que na maioria das ferramentas self-hosted. Os agentes compilam e executam código e acedem à rede, pelo que uma etapa de prova de conceito pode interagir com sistemas ativos. Aponte a ferramenta para código que lhe pertença ou que esteja contratado para testar e registe o âmbito do alvo antes de executar qualquer tarefa. Se configurar ANTHROPIC_API_KEY e usar o motor Claude Code, os procedimentos de sandboxing descritos em executar o Claude Code com segurança numa VPS também se aplicam a estes agentes.

FAQ

Por que o open-kritt precisa do seu próprio VPS?

Porque os agentes de análise executam como root dentro de contentores de tarefas descartáveis, com cópias graváveis do seu código e acesso direto à Internet. Além disso, o serviço do motor monta o socket do Docker do host para poder iniciar um contentor por tarefa. Qualquer processo que alcance esse socket pode iniciar um contentor que monte o sistema de ficheiros do host. Por isso, toda a stack deve ser tratada como root no respetivo host. Num VPS dedicado, esta é uma troca aceitável, e reconstruir o servidor não tem custos relevantes. Na sua estação de trabalho diária, as chaves SSH e os perfis do navegador ficam no mesmo limite de confiança que o código analisado.

Posso expor a porta 5173 em vez de usar um túnel SSH?

Não deve fazê-lo. O backend é fornecido sem autenticação ao nível da aplicação. Assim, a porta é a única barreira entre a Internet e os resultados das análises e os créditos do fornecedor. Por esse motivo, o ficheiro compose associa todos os serviços a 127.0.0.1. Execute ssh -N -L 5173:127.0.0.1:5173 you@your-server-ip e aceda localmente a http://localhost:5173. Uma regra do ufw não substitui esta medida, porque uma porta Docker publicada é processada antes de se aplicar a política predefinida do ufw.

Como impeço o open-kritt de gastar mais do que planeei?

Defina um limite rígido na consola do seu fornecedor de modelos antes da primeira análise, porque o open-kritt não tem uma definição própria de orçamento. Mantenha os valores predefinidos de concorrência fornecidos nas primeiras execuções, ENGINE_WORKER_COUNT=2 e ENGINE_MAX_CONCURRENT_SCANS=1. Tenha também em conta que uma conta de fornecedor permite, por predefinição, até 15 chamadas concorrentes ao modelo root, enquanto uma sessão Codex pode executar até cinco agentes subordinados. ENGINE_WORKER_COUNT=0 interrompe a recolha de novas tarefas e é a forma local mais rápida de parar o processamento.

Que versão devo obter?

Uma tag, nunca main. git fetch --tags seguido de git tag --list mostra o que está disponível. v1.3.0, publicado em 4 August 2026, é a versão mais recente no momento da redação. Fixar uma versão garante que uma reconstrução feita meses depois produz a mesma stack. Também transforma a atualização numa decisão tomada depois de ler as notas de versão, em vez de ser um efeito secundário de clonar o repositório num dia diferente.

Uma análise nunca começa. O que devo verificar?

Verifique primeiro o espaço livre em disco, porque o motor não inicia um contentor de análise por tarefa quando o armazenamento livre é inferior a ENGINE_MIN_FREE_STORAGE_GB, cujo valor predefinido é 20 GB. Depois, confirme que ENGINE_WORKER_COUNT não é 0, porque esse valor interrompe a recolha de novas tarefas. Em seguida, confirme que uma credencial de modelo está realmente configurada executando ./kritt setup, porque um GITHUB_TOKEN isolado não consegue executar análises. docker compose logs engine indica o motivo pelo qual a tarefa foi ignorada.