HeroCtl vs Kamal: cuando necesitas más de un servidor
Kamal es brillante para un VPS ejecutando Rails. Cuando el segundo cliente serio pide redundancia, la arquitectura necesita cambiar. Donde Kamal para y HeroCtl empieza.
En 2023 37signals publicó números que no combinaban con el discurso de la industria. La empresa salió de la nube pública para hospedar los propios productos en servidores dedicados, proyectó economía anual de aproximadamente tres millones de dólares y abrió el ferramental que usó para hacer esa migración. Ese ferramental ganó nombre — Kamal — y se volvió referencia rápida para un tipo de equipo que estaba cansado de la complejidad de orquestadores planetarios.
DHH, socio de 37signals, popularizó la tesis alrededor de la herramienta con una frase corta: "you don't need orchestration". El argumento es elegante, factual y — para la mayoría de los equipos que él describe — verdadero. Deploy de aplicación Rails se había vuelto un máster en sistemas distribuidos sin que nadie hubiera pedido eso. Kamal es la respuesta legítima a una frustración legítima, y ocupa un nicho propio dentro del segmento de Heroku auto-hospedado en 2026.
Este post no es sobre derrumbar esa tesis. Es sobre el momento exacto en el que deja de describir tu realidad. En algún punto entre el primer y el décimo cliente serio, la frase cambia de "no necesitas orquestación" a "pasaste a necesitar y aún no te diste cuenta". El síntoma suele ser un email a las tres de la mañana.
La filosofía Kamal, como merece ser descrita
Antes de cualquier crítica, vale la pena registrar lo que Kamal acierta — porque acierta mucho.
Tienes una aplicación dentro de un Dockerfile. Tienes una lista de servidores donde quieres que corra. Kamal toma esa lista, conecta a cada servidor por SSH, baja la imagen nueva, cambia el contenedor viejo por el nuevo y actualiza el router interno. No hay plano de control persistente. No hay agente residente en cada servidor con proceso propio. No hay base de datos de estado fuera del conjunto de servidores que ya tenías.
La configuración vive en un único archivo deploy.yml con tal vez cuarenta líneas. Corres un comando, y Kamal hace el trabajo en paralelo en los hosts. Cuando termina, desaparece — no hay servicio escuchando puerto 8080 esperando comandos futuros. Es deploy como una transacción SSH con checkpoints.
Esa minimización del estado externo es la virtud central. Para equipos de una a tres personas que ejecutan una aplicación monolítica en un único servidor, es difícil ganar. Coolify y los otros paneles modernos piden una base de datos propia, un agente propio, una interfaz web propia. Kamal pide dos ingredientes: SSH y Docker. Ya tenías los dos.
Estimamos que setenta y cinco por ciento de los equipos de aplicación web nunca necesitan más que eso. Si eres uno de ellos, cierra este post e instala Kamal. En serio.
Cuándo "no necesitas orquestación" es verdad
Algunos marcadores son honestos. Si tu operación cabe en esta lista, Kamal vence cualquier comparación que se pueda hacer con él:
- Un servidor único con holgura de recursos
- Aplicación monolítica, sin dependencias internas en red privada entre servicios
- Tráfico previsible, sin picos que exijan escalado horizontal de emergencia
- Ventana de deploy ocasional, con hasta treinta segundos de degradación aceptable
- Cliente final que no cobra contrato formal de disponibilidad
- Una a tres personas cuidando de la infra, en medio expediente
Para ese perfil, cualquier herramienta con plano de control persistente es overhead injustificado. Kamal es, literalmente, un archivo de configuración más un binario cliente. No hay nada para mantener en el servidor además de Docker que ibas a instalar de cualquier manera.
La elegancia de ese enfoque es tal que muchos equipos con perfil ligeramente mayor que el descrito arriba siguen felices — y están en lo correcto. Migrar a un orquestador antes de que el dolor aparezca es gold-plating de infraestructura. La pregunta correcta no es "¿tengo cluster?", es "¿qué dolor ya no logro ignorar?".
Cuándo "no necesitas orquestación" empieza a doler
El dolor no llega de una vez. Llega en cuatro etapas, generalmente en ese orden.
Primera etapa: el cliente exige SLA
En algún momento entra un contrato de prestación de servicio con cláusula de disponibilidad. Los números más comunes son 99% (3,65 días de indisponibilidad permitida al año), 99,9% (8,7 horas) y 99,95% (4,4 horas). El cliente quiere ver el número en el contrato.
Aquí Kamal en un único servidor ya no cabe. No porque Kamal sea malo — es porque un servidor único nunca da 99,9% sin maniobra externa. Mantenimiento del proveedor de nube, fallo de disco, actualización de kernel: cada uno de esos eventos consume integralmente tu presupuesto anual de indisponibilidad. En 2026 ningún proveedor serio garantiza 99,9% de uptime para una instancia individual.
La respuesta natural es "voy a poner dos servidores". Y es aquí donde Kamal empieza a necesitar andamios externos.
Segunda etapa: dos servidores y la ilusión del cluster
Kamal acepta sin reclamar una lista con dos IPs en el deploy.yml. Pero lo que hace con esa lista no es orquestación — es repetición. Los dos servidores son destinos paralelos de deploy, no miembros de un cluster.
Concretamente: si uno de los dos se cae, Kamal no realoca el tráfico. Kamal no tiene opinión sobre tráfico entre deploys. Necesitas montar, por fuera de él:
- Un balanceador de carga (del proveedor de nube o auto-hospedado)
- Verificación de salud periódica que retire el servidor inactivo del balance
- Resolución de DNS configurada encima del balanceador, no de los servidores directos
- Algún mecanismo de notificación cuando algo sale del aire
Son cuatro productos nuevos que pasas a operar. Cada uno tiene su propio panel, su propia cuenta, su propia factura, su propio modo de romper a las tres de la mañana. El ferramental que era un archivo de configuración se volvió un diagrama.
Tercera etapa: rolling update real se vuelve frágil
Con dos servidores, Kamal ofrece deploy en secuencia: primero uno, después el otro. Bonito en la descripción. El problema vive en el caso de error.
Imagina que el deploy en el primer servidor sube la versión nueva con éxito, el segundo traba en el medio. Kamal no tiene visión consolidada del estado de los dos servidores después del error. Te quedas con una versión nueva corriendo en un lado, versión vieja corriendo en el otro, y ningún sistema centralizado para reconciliar la divergencia. La reconciliación se vuelve intervención manual: abres los dos servidores, decides qué versión queda, haces rollback o avanzas en lo que falló.
Para un equipo de tres personas, intervenir manualmente una vez por trimestre es tolerable. Para un equipo que entrega cuatro deploys por semana en tres aplicaciones distintas, la divergencia manual se vuelve el trabajo principal de una de las tres personas. Fue exactamente ese el gatillo que motivó a los orquestadores a nacer en los años 2010.
Cuarta etapa: criptografía y enrutamiento entre servicios
Tarde o temprano la aplicación crece y gana un segundo servicio — tal vez un worker de cola, tal vez un servicio separado de procesamiento de imágenes, tal vez una API auxiliar consumida por el frontend principal. Esos servicios necesitan conversar entre sí, idealmente con tráfico cifrado y control de quién puede llamar a quién.
Kamal no tiene opinión sobre eso. Es tu trabajo montar — generalmente con proxy externo, certificados emitidos manualmente, reglas de firewall escritas a mano. En un servidor era trivial (todo el mundo es localhost). En tres servidores ejecutando seis servicios, se vuelve un proyecto aparte de una semana.
El router embebido en Kamal (el kamal-proxy) resuelve la parte de tráfico HTTP de entrada con elegancia — terminación TLS, cambio atómico entre versiones, headers bajo control. Pero el tráfico entre servicios, en red privada, es problema tuyo.
El salto necesario
Mirando los cuatro puntos arriba en conjunto, queda claro que para cubrirlos necesitas, en la práctica, de:
- Un plano de control replicado entre múltiples servidores — para que la caída de uno de ellos no tire la capacidad de hacer deploy
- Elección automática del servidor que coordina, sin intervención humana
- Balanceo y verificación de salud integrados, sin depender de balanceador externo del proveedor
- Estado consolidado de los servicios, con reconciliación automática cuando algo diverge
- Router integrado con certificados automáticos
- Criptografía entre servicios embebida, sin montar un producto más
La tentación de mucho equipo, al llegar a esa lista, es caer en el orquestador planetario y acabar con el asunto. De ahí instala el coloso, escribe trescientas líneas de manifiesto para subir lo que estaba en cuarenta líneas en Kamal, contrata un especialista de salario senior solo para mantener aquello respirando, y descubre que cambió el problema correcto por un problema mayor.
La respuesta razonable es una herramienta que ofrece los seis ítems arriba sin pedir un equipo dedicado. Es exactamente donde HeroCtl vive.
HeroCtl como Kamal con cluster real
La simplicidad conceptual es la misma. Describes el servicio en un archivo de configuración corto — alrededor de cincuenta líneas para una aplicación completa con reglas de enrutamiento, secretos y certificado automático. Sometes el servicio por el cliente de línea de comando o por el panel web embebido. El cluster decide dónde ejecutar.
La diferencia está debajo del capó. En lugar de SSH transaccional, HeroCtl mantiene un plano de control replicado entre tres servidores. Esos tres conversan todo el tiempo para mantener una visión consolidada de todo lo que está corriendo, en qué servidor, en qué versión, con qué salud. Cuando el servidor que coordina se cae, en alrededor de siete segundos uno de los otros dos asume — sin intervención humana, sin alerta de pager para nadie. Los contenedores de la aplicación que corrían en el servidor caído son realocados en los sobrevivientes.
La operación diaria parece exactamente con Kamal: cambias la versión de la imagen, sometes, el cluster orquesta la sustitución. La diferencia aparece en los casos malos. Si el deploy parcial falla en el medio, la reconciliación es automática — el estado deseado está grabado en el plano de control, y los agentes en cada servidor convergen hacia él sin que abras terminal. Si un servidor se cae durante el deploy, los otros asumen el trabajo de él. Si el puerto que iba a ser usado está preso por un contenedor zombi, el cluster espera o redirige — no falla el deploy.
Y el ferramental embebido cubre los otros ítems de la lista: router con certificados Let's Encrypt automáticos, criptografía entre servicios sin montar nada por fuera, panel web para ver lo que está corriendo, métricas y logs centralizados sin stack externa.
La instalación es el mismo gesto que Kamal pide: servidor Linux con Docker, un comando único de setup. No hay requisito nuevo de infraestructura. No hay base de datos externa. No hay servicio gestionado de nube. El cluster vive en los servidores que ya tienes.
Lado a lado, sin floritura
| Criterio | Kamal | HeroCtl |
|---|---|---|
| Filosofía | Deploy SSH minimalista, sin estado externo | Cluster con plano de control replicado |
| Franja ideal de servidores | 1 (excelente), 2-3 (con andamios externos) | 3 a 500 |
| Alta disponibilidad real | No nativa — requiere balanceador externo | Embebida; elección automática en ~7s |
| Panel web | No | Embebido |
| Certificados automáticos | Sí, vía router embebido | Sí, vía router embebido |
| Criptografía entre servicios | No nativa | Embebida |
| Métricas persistentes | No nativa | Job interno |
| Logs centralizados | No nativa — recoja por fuera | Escritor único embebido |
| Reconciliación automática tras fallo parcial | No — requiere intervención manual | Sí |
| Modelo comercial | Abierto, sin producto pago asociado | Plan gratuito permanente + Business/Enterprise pagados |
La columna de Kamal no es castigo — es honestidad. El producto fue diseñado para un caso de uso específico y lo cumple con elegancia. Cuando tu caso de uso pasa de lo que cubre, la respuesta correcta es cambiar de herramienta, no obligar a Kamal a volverse lo que nunca quiso ser.
Continúa en Kamal si...
La virtud de una herramienta especializada es admitir dónde gana. Cuatro perfiles en los que recomendamos Kamal sin titubear, aunque HeroCtl exista.
Ejecutas un servidor, sin presión de SLA formal. El coste conceptual de un cluster — entender quórum, plano de control replicado, elección — es injustificado para un servidor único. Kamal te da noventa y nueve por ciento de lo que importa con cinco por ciento del concepto.
Eres un equipo de una a tres personas con fuerte cultura Rails y ningún tiempo disponible para aprender ferramental nuevo. Kamal es, en la práctica, una extensión natural de bin/rails. Adoptarlo cuesta una tarde. Adoptar cualquier otra cosa cuesta una semana — y esa semana, en tu contexto, vale más que la mejora de operación que vendría después.
Tus aplicaciones son internas o de staging, donde cinco minutos de indisponibilidad mensual no causan daño real. La operación de Kamal es tan directa que sigue siendo la mejor elección incluso para equipos grandes que tienen un conjunto de aplicaciones secundarias con tolerancia alta a fallo.
Eres DHH. Con respeto sincero. La tesis de que orquestación es overkill fue defendida por alguien que opera productos públicos con millones de usuarios y prueba diariamente que se puede hacer sin cluster, con apenas servidores dedicados bien configurados. Si estás en un equipo en el que esa filosofía es parte de la identidad, Kamal no es solo herramienta — es declaración. No hay razón técnica para abandonarlo.
Migración de Kamal a HeroCtl cuando tiene sentido
Para quien llegó al momento en el que el dolor descrito arriba se volvió rutina, la migración es más ligera de lo que parece, porque la mayor parte del trabajo que Kamal ya hacía sigue siendo válido.
El Dockerfile que Kamal usa para empaquetar la aplicación sirve sin cambio alguno. HeroCtl consume la misma imagen que Kamal empuja al registry. No hay requisito de adaptar ENTRYPOINT, variables de entorno esperadas, puertos expuestos — el contrato del contenedor es preservado.
Variables de entorno migran con las mismas claves. HeroCtl tiene un sistema de secretos propio, pero el nombre de las variables que la aplicación consume sigue siendo el mismo. Importas el contenido del .env que estaba en el deploy.yml directo al vault interno del cluster, y la aplicación no nota el cambio.
Volúmenes nombrados se mantienen, porque Docker es Docker. Si tenías un volumen llamado app_storage en Kamal para persistir uploads, en HeroCtl sigue llamándose app_storage y vive en el mismo lugar del servidor. La diferencia es que el cluster sabe dónde está y respeta esa fijación al decidir dónde ejecutar la aplicación.
El deploy.yml no convierte uno a uno, pero el mapeo conceptual es casi mecánico:
- El bloque
serversde Kamal se vuelve la noción de cluster con N nodos en HeroCtl. No listas IPs en el archivo de aplicación — el cluster ya se conoce. - El bloque
proxyde Kamal se vuelve la configuración de enrutamiento integrado. En lugar de describir el proxy explícitamente, describes el nombre de dominio y las reglas; el router embebido aplica. - El bloque
accessories(Postgres, Redis y similares al lado de la aplicación) se vuelve jobs auxiliares en el mismo cluster, gestionados como cualquier otro servicio. - El bloque
envse vuelve el sistema de secretos de HeroCtl, con las mismas claves.
Estimación honesta: una a tres horas para una aplicación de complejidad media, contando tiempo de lectura de documentación, conversión del archivo, primer deploy de validación. Aplicaciones con muchos accessories o reglas inusuales de enrutamiento pueden llegar a medio día. Por encima de eso, escríbenos — tenemos un conversor experimental que cubre los casos comunes.
Preguntas que recibimos
¿HeroCtl tiene el equivalente de kamal accessories?
Sí. En HeroCtl describes Postgres, Redis o cualquier otro servicio auxiliar como un job común, gestionado por el mismo cluster que ejecuta la aplicación principal. La diferencia práctica es que esos servicios auxiliares ganan el mismo tratamiento que la aplicación: alta disponibilidad cuando tiene sentido, reconciliación automática, certificados si son expuestos públicamente, métricas y logs en el panel central. No operas un conjunto separado de "cosas al lado".
¿Y si uso Kamal para una app pequeña y HeroCtl para otra mayor, puedo? Puedes. Los dos mundos coexisten sin conflicto. Inclusive recomendamos ese modelo durante la migración: mantienes lo que funciona en Kamal exactamente como está, y usas HeroCtl para las aplicaciones donde el cluster real importa. El único cuidado es no ejecutar Kamal y HeroCtl en el mismo servidor — disputan espacio en Docker y en los puertos, y la confusión no compensa la ganancia operacional. Servidores diferentes, mundos diferentes.
¿HeroCtl corre en cualquier VPS Linux como Kamal? Sí. La premisa es la misma: servidor Linux con Docker. Proveedor de nube grande, proveedor menor, servidor dedicado, máquina virtual en la oficina — donde Kamal funciona, HeroCtl funciona. No hay requisito de red privada gestionada, no hay requisito de balanceador externo del proveedor, no hay requisito de sistema de archivos especial. La condición mínima es tres servidores que se vean en la red y tengan Docker instalado.
¿Cuánto consume de más que Kamal? El plano de control ocupa entre 200 y 400 MB por servidor. En tres servidores de configuración modesta, eso es menos de cinco por ciento de la memoria total disponible. Comparado con Kamal — que consume cero porque no tiene proceso residente — es más. Comparado con el coloso, cuya versión gestionada empieza en alrededor de 700 MB por nodo-maestro antes de que cualquier aplicación suba, es la mitad. La pregunta correcta no es "cuánto a más", es "cuánto eso me da a cambio". Para nuestro cluster público de demostración, que ejecuta cuatro servidores, dieciséis contenedores y cinco sitios con cinco vCPUs y diez gigabytes totales, la respuesta es: alta disponibilidad real, sin necesitar duplicar el hardware.
¿Y el kamal-proxy, que es router integrado por debajo?
HeroCtl tiene el propio router integrado, con cambio atómico entre versiones, terminación TLS automática vía Let's Encrypt y enrutamiento por nombre de dominio. El concepto es el mismo del kamal-proxy. La diferencia es que el router de HeroCtl conoce el estado del cluster — sabe cuándo un servidor entero se cayó, cuándo un contenedor está en rolling, cuándo una versión nueva aún no pasó en la verificación de salud. Router aislado hace enrutamiento; router integrado al plano de control hace enrutamiento informado.
¿Necesito aprender un lenguaje nuevo para usar HeroCtl?
No. El archivo de configuración es texto simple, parecido al deploy.yml de Kamal en estructura y tamaño. Los comandos de línea de comando siguen el patrón verbo-sustantivo que cualquier persona que ejecutó Docker conoce. El panel web cubre noventa por ciento de las operaciones sin que necesites abrir terminal. No hay lenguaje de templating, no hay sistema de paquetes paralelo, no hay manifiesto ceremonial. La regla interna es la misma de Kamal: la configuración tiene que caber en una pantalla.
¿Cuándo HeroCtl no es la respuesta correcta? Cuando operas un servidor único sin presión de SLA, Kamal es mejor — y lo dijimos arriba. Cuando operas cientos de miles de máquinas en escala planetaria, el coloso es mejor — y lo dijimos en otro post. Cuando tu compliance officer necesita apuntar a un certificado existente con nombre de producto en la lista, hoy la respuesta es el coloso o un orquestador comercial maduro. En esas tres condiciones, HeroCtl no compite bien y no intentamos forzar. Para la franja entre tres y quinientos servidores, con presión real de disponibilidad y tiempo escaso para montar stack, es donde la herramienta fue diseñada para brillar.
Cierre
La pregunta correcta no es Kamal o HeroCtl. Es: ¿tu segundo cliente serio ya apareció? Si aún no, quédate en Kamal y sé feliz — cualquier cosa diferente de eso es distracción. Si ya apareció, y la noche mal dormida con el servidor caído ya sucedió al menos una vez, la respuesta empieza a inclinarse.
El camino de prueba es un comando único:
curl -sSL get.heroctl.com/install.sh | sh
Corre en tres servidores, sube la aplicación, mata uno de ellos a la fuerza, mira el cluster realocar. Si la sensación de alivio es proporcional al dolor que tuviste en el último incidente, está conversado. Si no lo es, vuelve a Kamal sin culpa — significa que tu momento aún no llegó, y respetar eso es tan importante como adoptar la herramienta correcta cuando el momento llega.
La historia más larga del por qué construimos esto, y la lectura honesta de los tres caminos que existían antes, está en Por qué creamos HeroCtl.