HeroCtl vs Kamal: quando você precisa de mais de um servidor
Kamal é brilhante pra um VPS rodando Rails. Quando o segundo cliente sério pede redundância, a arquitetura precisa mudar. Onde Kamal para e o HeroCtl começa.
Em 2023 o 37signals publicou números que não combinavam com o discurso da indústria. A empresa saiu da nuvem pública pra hospedar os próprios produtos em servidores dedicados, projetou economia anual de aproximadamente três milhões de dólares e abriu o ferramental que usou pra fazer essa migração. Esse ferramental ganhou nome — Kamal — e virou referência rápida pra um tipo de time que estava cansado da complexidade de orquestradores planetários.
DHH, sócio do 37signals, popularizou a tese ao redor da ferramenta com uma frase curta: "you don't need orchestration". O argumento é elegante, factual e — pra a maioria dos times que ele descreve — verdadeiro. Deploy de aplicação Rails havia virado um mestrado em sistemas distribuídos sem que ninguém tivesse pedido isso. O Kamal é a resposta legítima a uma frustração legítima, e ocupa um nicho próprio dentro do segmento de Heroku auto-hospedado em 2026.
Este post não é sobre derrubar essa tese. É sobre o momento exato em que ela deixa de descrever a sua realidade. Em algum ponto entre o primeiro e o décimo cliente sério, a frase muda de "você não precisa de orquestração" pra "você passou a precisar e não percebeu ainda". O sintoma costuma ser um e-mail às três da manhã.
A filosofia Kamal, como ela merece ser descrita
Antes de qualquer crítica, vale registrar o que o Kamal acerta — porque ele acerta muito.
Você tem uma aplicação dentro de um Dockerfile. Tem uma lista de servidores onde quer que ela rode. O Kamal pega essa lista, conecta em cada servidor por SSH, baixa a imagem nova, troca o contêiner velho pelo novo e atualiza o roteador interno. Não há plano de controle persistente. Não há agente residente em cada servidor com processo próprio. Não há banco de dados de estado fora do conjunto de servidores que você já tinha.
A configuração mora num único arquivo deploy.yml com talvez quarenta linhas. Você roda um comando, e o Kamal faz o trabalho em paralelo nos hosts. Quando ele termina, ele some — não há serviço escutando porta 8080 esperando comandos futuros. É deploy como uma transação SSH com checkpoints.
Essa minimização do estado externo é a virtude central. Pra times de uma a três pessoas que rodam uma aplicação monolítica num único servidor, é difícil bater. O Coolify e os outros painéis modernos pedem um banco de dados próprio, um agente próprio, uma interface web própria. O Kamal pede dois ingredientes: SSH e Docker. Você já tinha os dois.
Estimamos que setenta e cinco por cento dos times de aplicação web no Brasil em 2026 nunca precisam de mais do que isso. Se você é um deles, fecha esse post e instala Kamal. Sério.
Quando "você não precisa de orquestração" é verdade
Alguns marcadores são honestos. Se a sua operação cabe nesta lista, o Kamal vence qualquer comparação que se possa fazer com ele:
- Um servidor único com folga de recursos
- Aplicação monolítica, sem dependências internas em rede privada entre serviços
- Tráfego previsível, sem picos que exijam escalonamento horizontal de emergência
- Janela de deploy ocasional, com até trinta segundos de degradação aceitável
- Cliente final que não cobra contrato formal de disponibilidade
- Uma a três pessoas tomando conta da infra, em meio expediente
Pra esse perfil, qualquer ferramenta com plano de controle persistente é overhead injustificado. O Kamal é, literalmente, um arquivo de configuração mais um binário cliente. Não há nada pra manter no servidor além do Docker que você ia instalar de qualquer jeito.
A elegância dessa abordagem é tal que muitos times com perfil ligeiramente maior que o descrito acima continuam felizes — e estão certos. Migrar pra um orquestrador antes que a dor apareça é gold-plating de infraestrutura. A pergunta correta não é "tenho cluster?", é "qual dor não consigo mais ignorar?".
Quando "você não precisa de orquestração" começa a doer
A dor não chega de uma vez. Chega em quatro etapas, geralmente nessa ordem.
Primeira etapa: o cliente exige SLA
Em algum momento entra um contrato de prestação de serviço com cláusula de disponibilidade. Os números mais comuns são 99% (3,65 dias de indisponibilidade permitida por ano), 99,9% (8,7 horas) e 99,95% (4,4 horas). O cliente quer ver o número no contrato.
Aqui o Kamal num único servidor já não cabe. Não porque o Kamal seja ruim — é porque um servidor único nunca dá 99,9% sem manobra externa. Manutenção do provedor de nuvem, falha de disco, atualização de kernel: cada um desses eventos consome integralmente o seu orçamento anual de indisponibilidade. Em 2026 nenhum provedor sério garante 99,9% de uptime para uma instância individual.
A resposta natural é "vou colocar dois servidores". E é aqui que o Kamal começa a precisar de andaimes externos.
Segunda etapa: dois servidores e a ilusão do cluster
O Kamal aceita sem reclamar uma lista com dois IPs no deploy.yml. Mas o que ele faz com essa lista não é orquestração — é repetição. Os dois servidores são destinos paralelos de deploy, não membros de um cluster.
Concretamente: se um dos dois cair, o Kamal não realoca o tráfego. O Kamal não tem opinião sobre tráfego entre deploys. Você precisa montar, por fora dele:
- Um balanceador de carga (do provedor de nuvem ou auto-hospedado)
- Verificação de saúde periódica que retire o servidor inativo do balanço
- Resolução de DNS configurada em cima do balanceador, não dos servidores diretos
- Algum mecanismo de notificação quando algo sai do ar
São quatro produtos novos que você passa a operar. Cada um tem o seu próprio painel, a sua própria conta, a sua própria fatura, o seu próprio modo de quebrar às três da manhã. O ferramental que era um arquivo de configuração virou um diagrama.
Terceira etapa: rolling deploy real fica frágil
Com dois servidores, o Kamal oferece deploy em sequência: primeiro um, depois o outro. Bonito na descrição. O problema mora no caso de erro.
Imagine que o deploy no primeiro servidor sobe a versão nova com sucesso, o segundo trava no meio. O Kamal não tem visão consolidada do estado dos dois servidores depois do erro. Você fica com uma versão nova rodando num lado, versão velha rodando no outro, e nenhum sistema centralizado pra reconciliar a divergência. A reconciliação vira intervenção manual: você abre os dois servidores, decide qual versão fica, faz rollback ou avança no que falhou.
Pra um time de três pessoas, intervir manualmente uma vez por trimestre é tolerável. Pra um time que entrega quatro deploys por semana em três aplicações distintas, a divergência manual vira o trabalho principal de uma das três pessoas. Foi exatamente esse o gatilho que motivou orquestradores nascerem nos anos 2010.
Quarta etapa: criptografia e roteamento entre serviços
Cedo ou tarde a aplicação cresce e ganha um segundo serviço — talvez um worker de fila, talvez um serviço separado de processamento de imagens, talvez uma API auxiliar consumida pelo frontend principal. Esses serviços precisam conversar entre si, idealmente com tráfego cifrado e controle de quem pode chamar quem.
O Kamal não tem opinião sobre isso. É o seu trabalho montar — geralmente com proxy externo, certificados emitidos manualmente, regras de firewall escritas a mão. Em um servidor era trivial (todo mundo é localhost). Em três servidores rodando seis serviços, vira um projeto à parte de uma semana.
O roteador embutido no Kamal (o kamal-proxy) resolve a parte de tráfego HTTP de entrada com elegância — terminação TLS, troca atômica entre versões, cabeçalhos sob controle. Mas o tráfego entre serviços, em rede privada, é problema seu.
O salto necessário
Olhando os quatro pontos acima em conjunto, fica claro que pra cobri-los você precisa, na prática, de:
- Um plano de controle replicado entre múltiplos servidores — pra que a queda de um deles não derrube a capacidade de fazer deploy
- Eleição automática do servidor que coordena, sem intervenção humana
- Balanceamento e verificação de saúde integrados, sem depender de balanceador externo do provedor
- Estado consolidado dos serviços, com reconciliação automática quando algo diverge
- Roteador integrado com certificados automáticos
- Criptografia entre serviços embutida, sem montar mais um produto
A tentação de muito time, ao chegar nessa lista, é cair no orquestrador planetário e acabar com o assunto. Daí instala o colosso, escreve trezentas linhas de manifesto pra subir o que estava em quarenta linhas no Kamal, contrata um especialista de salário sênior só pra manter aquilo respirando, e descobre que trocou o problema certo por um problema maior.
A resposta razoável é uma ferramenta que oferece os seis itens acima sem pedir um time dedicado. É exatamente onde o HeroCtl mora.
HeroCtl como Kamal com cluster real
A simplicidade conceitual é a mesma. Você descreve o serviço num arquivo de configuração curto — em torno de cinquenta linhas pra uma aplicação completa com regras de roteamento, segredos e certificado automático. Submete o serviço pelo cliente de linha de comando ou pelo painel web embutido. O cluster decide onde rodar.
A diferença está debaixo do capô. Em vez de SSH transacional, o HeroCtl mantém um plano de controle replicado entre três servidores. Esses três conversam o tempo todo pra manter uma visão consolidada de tudo que está rodando, em qual servidor, em qual versão, com qual saúde. Quando o servidor que coordena cai, em torno de sete segundos um dos outros dois assume — sem intervenção humana, sem alerta de pager pra ninguém. Os contêineres da aplicação que rodavam no servidor caído são realocados nos sobreviventes.
A operação diária parece exatamente com o Kamal: você muda a versão da imagem, submete, o cluster orquestra a substituição. A diferença aparece nos casos ruins. Se o deploy parcial falhar no meio, a reconciliação é automática — o estado desejado está gravado no plano de controle, e os agentes em cada servidor convergem pra ele sem você abrir terminal. Se um servidor cair durante o deploy, os outros assumem o trabalho dele. Se a porta que ia ser usada estiver presa por um contêiner zumbi, o cluster espera ou redireciona — não falha o deploy.
E o ferramental embutido cobre os outros itens da lista: roteador com certificados Let's Encrypt automáticos, criptografia entre serviços sem montar nada por fora, painel web pra ver o que está rodando, métricas e logs centralizados sem stack externa.
A instalação é o mesmo gesto que o Kamal pede: servidor Linux com Docker, um comando único de setup. Não há requisito novo de infraestrutura. Não há banco de dados externo. Não há serviço gerenciado de nuvem. O cluster mora nos servidores que você já tem.
Lado a lado, sem floreio
| Critério | Kamal | HeroCtl |
|---|---|---|
| Filosofia | Deploy SSH minimalista, sem estado externo | Cluster com plano de controle replicado |
| Faixa ideal de servidores | 1 (excelente), 2-3 (com andaimes externos) | 3 a 500 |
| Alta disponibilidade real | Não nativa — requer balanceador externo | Embutida; eleição automática em ~7s |
| Painel web | Não | Embutido |
| Certificados automáticos | Sim, via roteador embutido | Sim, via roteador embutido |
| Criptografia entre serviços | Não nativa | Embutida |
| Métricas persistentes | Não nativa | Job interno |
| Logs centralizados | Não nativa — recolha por fora | Escritor único embutido |
| Reconciliação automática após falha parcial | Não — requer intervenção manual | Sim |
| Modelo comercial | Aberto, sem produto pago associado | Plano gratuito permanente + Business/Enterprise pagos |
A coluna do Kamal não é punição — é honestidade. O produto foi desenhado pra um caso de uso específico e o cumpre com elegância. Quando o seu caso de uso passa do que ele cobre, a resposta correta é trocar de ferramenta, não obrigar o Kamal a virar o que ele nunca quis ser.
Continue no Kamal se...
A virtude de uma ferramenta especializada é admitir onde ela vence. Quatro perfis em que recomendamos Kamal sem hesitação, mesmo que o HeroCtl exista.
Você roda um servidor, sem pressão de SLA formal. O custo conceitual de um cluster — entender quórum, plano de controle replicado, eleição — é injustificado pra um servidor único. O Kamal te dá noventa e nove por cento do que importa com cinco por cento do conceito.
Você é um time de uma a três pessoas com forte cultura Rails e nenhum tempo disponível pra aprender ferramental novo. O Kamal é, na prática, uma extensão natural do bin/rails. Adotá-lo custa uma tarde. Adotar qualquer outra coisa custa uma semana — e essa semana, no seu contexto, vale mais do que a melhoria de operação que viria depois.
As suas aplicações são internas ou de staging, onde cinco minutos de indisponibilidade mensal não causam dano real. A operação do Kamal é tão direta que ele continua a melhor escolha mesmo pra times grandes que têm um conjunto de aplicações secundárias com tolerância alta a falha.
Você é o DHH. Com respeito sincero. A tese de que orquestração é overkill foi defendida por alguém que opera produtos públicos com milhões de usuários e prova diariamente que dá pra fazer sem cluster, com apenas servidores dedicados bem configurados. Se você está num time em que essa filosofia é parte da identidade, o Kamal não é só ferramenta — é declaração. Não há razão técnica pra abandoná-lo.
Migração de Kamal pra HeroCtl quando faz sentido
Pra quem chegou no momento em que a dor descrita acima virou rotina, a migração é mais leve do que parece, porque a maior parte do trabalho que o Kamal já fazia continua válido.
O Dockerfile que o Kamal usa pra empacotar a aplicação serve sem mudança nenhuma. O HeroCtl consome a mesma imagem que o Kamal empurra pro registro. Não há requisito de adaptar ENTRYPOINT, variáveis de ambiente esperadas, portas expostas — o contrato do contêiner é preservado.
Variáveis de ambiente migram com as mesmas chaves. O HeroCtl tem um sistema de segredos próprio, mas o nome das variáveis que a aplicação consome continua o mesmo. Você importa o conteúdo do .env que estava no deploy.yml direto pro vault interno do cluster, e a aplicação não percebe a troca.
Volumes nomeados se mantêm, porque Docker é Docker. Se você tinha um volume chamado app_storage no Kamal pra persistir uploads, no HeroCtl ele continua se chamando app_storage e mora no mesmo lugar do servidor. A diferença é que o cluster sabe onde ele está e respeita essa fixação ao decidir onde rodar a aplicação.
O deploy.yml não converte um pra um, mas o mapeamento conceitual é quase mecânico:
- O bloco
serversdo Kamal vira a noção de cluster com N nós no HeroCtl. Você não lista IPs no arquivo de aplicação — o cluster já se conhece. - O bloco
proxydo Kamal vira a configuração de roteamento integrado. Em vez de descrever o proxy explicitamente, você descreve o nome de domínio e as regras; o roteador embutido aplica. - O bloco
accessories(Postgres, Redis e similares ao lado da aplicação) vira jobs auxiliares no mesmo cluster, gerenciados como qualquer outro serviço. - O bloco
envvira o sistema de segredos do HeroCtl, com as mesmas chaves.
Estimativa honesta: uma a três horas pra uma aplicação de complexidade média, contando tempo de leitura de documentação, conversão do arquivo, primeiro deploy de validação. Aplicações com muitos accessories ou regras incomuns de roteamento podem chegar a meio dia. Acima disso, escreve pra gente — temos um conversor experimental que cobre os casos comuns.
Perguntas que a gente recebe
O HeroCtl tem o equivalente do kamal accessories?
Sim. No HeroCtl você descreve Postgres, Redis ou qualquer outro serviço auxiliar como um job comum, gerenciado pelo mesmo cluster que roda a aplicação principal. A diferença prática é que esses serviços auxiliares ganham o mesmo tratamento que a aplicação: alta disponibilidade quando faz sentido, reconciliação automática, certificados se forem expostos publicamente, métricas e logs no painel central. Você não opera um conjunto separado de "coisas ao lado".
E se eu uso Kamal pra um app pequeno e HeroCtl pra outro maior, posso? Pode. Os dois mundos coexistem sem conflito. Inclusive recomendamos esse modelo durante a migração: você mantém o que funciona no Kamal exatamente como está, e usa o HeroCtl pras aplicações onde o cluster real importa. O único cuidado é não rodar o Kamal e o HeroCtl no mesmo servidor — eles disputam espaço no Docker e nas portas, e a confusão não compensa o ganho operacional. Servidores diferentes, mundos diferentes.
O HeroCtl roda em qualquer VPS Linux como o Kamal? Sim. A premissa é a mesma: servidor Linux com Docker. Provedor de nuvem grande, provedor menor, servidor dedicado, máquina virtual no escritório — onde o Kamal funciona, o HeroCtl funciona. Não há requisito de rede privada gerenciada, não há requisito de balanceador externo do provedor, não há requisito de sistema de arquivos especial. A condição mínima é três servidores que se enxerguem na rede e tenham Docker instalado.
Quanto consome a mais que o Kamal? O plano de controle ocupa entre 200 e 400 MB por servidor. Em três servidores de configuração modesta, isso é menos de cinco por cento da memória total disponível. Comparado ao Kamal — que consome zero porque não tem processo residente — é mais. Comparado ao colosso, cuja versão gerenciada começa em torno de 700 MB por nó-mestre antes de qualquer aplicação subir, é metade. A pergunta correta não é "quanto a mais", é "quanto isso me dá em troca". Pra o nosso cluster público de demonstração, que roda quatro servidores, dezesseis contêineres e cinco sites com cinco vCPUs e dez gigabytes totais, a resposta é: alta disponibilidade real, sem precisar dobrar o hardware.
E o kamal-proxy, que é roteador integrado por baixo?
O HeroCtl tem o próprio roteador integrado, com troca atômica entre versões, terminação TLS automática via Let's Encrypt e roteamento por nome de domínio. O conceito é o mesmo do kamal-proxy. A diferença é que o roteador do HeroCtl conhece o estado do cluster — ele sabe quando um servidor inteiro caiu, quando um contêiner está em rolling, quando uma versão nova ainda não passou na verificação de saúde. Roteador isolado faz roteamento; roteador integrado ao plano de controle faz roteamento informado.
Preciso aprender uma linguagem nova pra usar HeroCtl?
Não. O arquivo de configuração é texto simples, parecido com o deploy.yml do Kamal em estrutura e tamanho. Os comandos de linha de comando seguem o padrão verbo-substantivo que qualquer pessoa que rodou Docker conhece. O painel web cobre noventa por cento das operações sem você precisar abrir terminal. Não há linguagem de templating, não há sistema de pacotes paralelo, não há manifesto cerimonial. A regra interna é a mesma do Kamal: a configuração tem que caber numa tela.
Quando o HeroCtl não é a resposta certa? Quando você opera um servidor único sem pressão de SLA, o Kamal é melhor — e dissemos isso acima. Quando você opera centenas de milhares de máquinas em escala planetária, o colosso é melhor — e dissemos isso noutro post. Quando o seu compliance officer precisa apontar pra um certificado existente com nome de produto na lista, hoje a resposta é o colosso ou um orquestrador comercial maduro. Nessas três condições, o HeroCtl não compete bem e a gente não tenta forçar. Pra a faixa entre três e quinhentos servidores, com pressão real de disponibilidade e tempo escasso pra montar stack, é onde a ferramenta foi desenhada pra brilhar.
Fechamento
A pergunta certa não é Kamal ou HeroCtl. É: o seu segundo cliente sério já apareceu? Se ainda não, fica no Kamal e seja feliz — qualquer coisa diferente disso é distração. Se já apareceu, e a noite mal dormida com o servidor caído já aconteceu pelo menos uma vez, a resposta começa a inclinar.
O caminho de teste é um comando único:
curl -sSL get.heroctl.com/install.sh | sh
Roda em três servidores, sobe a aplicação, mata um deles à força, vê o cluster realocar. Se a sensação de alívio for proporcional à dor que você teve no último incidente, está conversado. Se não for, volta pro Kamal sem culpa — significa que o seu momento ainda não chegou, e respeitar isso é tão importante quanto adotar a ferramenta certa quando o momento chega.
A história mais longa do porquê construímos isso, e a leitura honesta dos três caminhos que existiam antes, está em Por que criamos o HeroCtl.