[{"data":1,"prerenderedAt":192},["ShallowReactive",2],{"seo-verification":3,"blog-desplegar-con-kamal-es":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-desplegar-con-kamal-es",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":136,"ctaBody":137,"ctaButton":138,"ctaUrl":139,"relatedPosts":140},40,"desplegar-con-kamal",{"fr":12,"en":13,"ar":14,"es":10},"deployer-avec-kamal","deploy-your-applications-with-kamal-on-a-vps","انشر-تطبيقاتك-باستخدام-kamal-على-خادم-vps","Desplegar aplicaciones web con Kamal en un VPS","Guía completa de Kamal v2: instalación, configuración deploy.yml, kamal-proxy, secretos, despliegues multi-servidor, CI\u002FCD con GitHub Actions y resolución de errores.",11,0,false,"2026-05-11T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},3,"Despliegue","deploiement","bg-success\u002F10 text-success",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-avec-kamal-poster.svg","Kamal (antes conocido como MRSK), desarrollado por 37signals, despliega aplicaciones en contenedores en uno o varios servidores VPS desde tu máquina local, sin necesidad de un orquestador pesado. Desde la versión 2, publicada en septiembre de 2024 (incluida por defecto en Rails 8, publicado en noviembre de 2024), reemplaza Traefik por su propio proxy dedicado (kamal-proxy) y centraliza la gestión de secretos en `.kamal\u002Fsecrets`. El comando `kamal deploy` coordina la construcción de la imagen Docker, el envío al registro y el cambio de tráfico sin interrupciones en una sola pasada.",[34,38,50,53,56,84,87,90,93,96,99,102,133],{"type":35,"title":36,"body":37},"h2","¿Por qué elegir Kamal en lugar de Kubernetes para desplegar aplicaciones web en un VPS?","Kubernetes resuelve problemas de coordinación a gran escala — descubrimiento de servicios, escalado horizontal automático, espacios de nombres para múltiples equipos — que simplemente no existen en un VPS único o en un cluster pequeño. Su plano de control consume entre 2 y 4 GB de RAM antes de lanzar una sola aplicación. Kamal apunta a un espacio diferente: toma tu Dockerfile, construye la imagen, la envía al registro, la ejecuta en tus servidores vía SSH y cambia el tráfico sin interrupciones gracias a kamal-proxy. Toda la configuración reside en un único archivo `config\u002Fdeploy.yml` versionado junto al código. Sin plano de control que mantener, sin certificados de API que renovar, sin YAML distribuido en diez tipos de recursos. Conservas la simplicidad operativa de un VPS — acceso SSH directo, `docker ps` legible, logs en un archivo — y obtienes un flujo de despliegue profesional con rollback instantáneo, health checks y HTTPS automático.",{"type":39,"title":40,"items":41},"ul","Lo que te aporta Kamal v2",[42,43,44,45,46,47,48,49],"**Despliegues sin interrupciones** — kamal-proxy espera a que los health checks pasen en el nuevo contenedor antes de redirigir el tráfico, y drena las peticiones en vuelo en el antiguo","**Un único comando** — `kamal deploy` encadena build, envío al registro, despliegue SSH y verificación sin pasos manuales","**HTTPS automático con Let's Encrypt** — kamal-proxy gestiona la renovación de certificados TLS; no se necesita configurar Certbot por separado","**Rollback instantáneo** — `kamal rollback [VERSION]` redirige el proxy a una imagen ya presente en el servidor en segundos","**Gestión estructurada de secretos** — `.kamal\u002Fsecrets` admite lectura desde 1Password, Bitwarden o variables de entorno sin almacenar valores en texto plano en el repositorio","**Multi-servidor y multi-rol nativos** — servidores web, workers Sidekiq, accesorios Postgres o Redis descritos en un solo archivo, desplegados en paralelo","**Múltiples apps en un solo VPS** — desde Kamal 2, varias aplicaciones comparten un kamal-proxy sin conflictos de configuración","**Compatible con cualquier stack** — Rails, Django, Node.js, Go, PHP: Kamal solo requiere un Dockerfile y un registro de contenedores",{"type":35,"title":51,"body":52},"Requisitos previos antes de desplegar con Kamal","En el lado del VPS, Kamal exige Ubuntu 22.04 o 24.04 (o cualquier distribución Linux con Docker 20.10+), acceso SSH por clave (sin contraseña) y al menos 2 vCPU y 2 GB de RAM para una aplicación web estándar con su base de datos. Kamal puede instalar Docker él mismo durante el primer `kamal setup`, pero la cuenta SSH debe tener derechos sudo. Los puertos 80 y 443 abiertos en entrada y un registro DNS A apuntando a la IP del VPS son indispensables antes de activar el SSL. En tu máquina local, dos opciones: instalar la gema Ruby (`gem install kamal`, requiere Ruby 3.1+) o usar la imagen Docker oficial. La versión actual es la 2.12.0 (junio de 2026). Prepara también un registro de contenedores — Docker Hub, GitHub Container Registry o un registro privado — junto con sus credenciales.",{"type":35,"title":54,"body":55},"Kamal v1 vs Kamal v2: qué ha cambiado","Kamal 2, publicado en septiembre de 2024 (incluido por defecto en Rails 8, publicado en noviembre de 2024), reemplaza Traefik por kamal-proxy, un proxy inverso desarrollado internamente por 37signals. El cambio es estructural: Traefik es declarativo (le envías una configuración y converge), mientras que Kamal es imperativo. La versión 1 tenía que consultar la API de Traefik repetidamente para saber si el despliegue había tenido éxito — fuente de condiciones de carrera. Con kamal-proxy, los comandos son directos y sincrónicos. En cuanto a la configuración, el bloque `traefik:` desaparece de `deploy.yml` y es reemplazado por `proxy:` con las claves `host`, `ssl` y `app_port`. Los secretos migran de `.env` a `.kamal\u002Fsecrets`, un archivo shell evaluado que puede llamar a herramientas externas como `op read` o `bw get`. El comando `kamal upgrade` detecta una configuración v1 y propone un plan de migración automatizado. Kamal 2 también introduce el despliegue de varias aplicaciones en un mismo proxy, el modo mantenimiento (`kamal app pause`) y soporte experimental para despliegues canary.",{"type":57,"title":58,"steps":59},"steps","Instalación y primer despliegue con Kamal v2",[60,63,66,69,72,75,78,81],{"title":61,"body":62},"Instalar Kamal en tu máquina local","Ejecuta `gem install kamal` (requiere Ruby 3.1+) o usa el alias Docker si prefieres evitar Ruby. Verifica la instalación con `kamal version` — la versión actual es 2.12.0.",{"title":64,"body":65},"Inicializar la configuración en tu proyecto","En el directorio raíz del proyecto ejecuta `kamal init`. Kamal genera `config\u002Fdeploy.yml` y `.kamal\u002Fsecrets`. Rellena en `deploy.yml`: nombre del servicio (`service: miapp`), imagen (`image: tuusuario\u002Fmiapp`), lista de servidores y registro.",{"title":67,"body":68},"Configurar los secretos y variables de entorno","Añade `.kamal\u002Fsecrets` a tu `.gitignore`. En ese archivo declara los secretos como variables shell: `KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD` o leyéndolos desde 1Password. En `config\u002Fdeploy.yml` referéncialos bajo `env.secret:` para valores cifrados y `env.clear:` para variables no sensibles.",{"title":70,"body":71},"Configurar el proxy y el SSL","En `config\u002Fdeploy.yml` añade la sección proxy: `proxy: host: app.your-domain.com ssl: true app_port: 3000`. kamal-proxy obtendrá automáticamente un certificado Let's Encrypt vía ACME HTTP-01. Asegúrate de que el registro DNS ya apunte a la IP del VPS antes de este paso.",{"title":73,"body":74},"Aprovisionar el servidor (solo una vez)","Ejecuta `kamal setup`. Kamal se conecta por SSH, instala Docker si está ausente, autentica el registro, inicia kamal-proxy y despliega la primera versión de la aplicación. Este es el único paso de arranque inicial.",{"title":76,"body":77},"Desplegar las actualizaciones siguientes","En cada iteración ejecuta `kamal deploy`. Kamal construye la imagen, la envía al registro, inicia un nuevo contenedor junto al antiguo, espera que el health check pase, redirige kamal-proxy al nuevo contenedor, drena las conexiones existentes y detiene el antiguo.",{"title":79,"body":80},"Verificar el estado y consultar los logs","Tras el despliegue: `kamal app details` muestra la versión en ejecución en cada servidor, `kamal app logs -f` sigue los logs en tiempo real, `kamal app exec 'bin\u002Frails console'` abre una consola dentro del contenedor en producción.",{"title":82,"body":83},"Gestionar los accesorios (base de datos, caché)","Declara Postgres bajo la clave `accessories:` en `deploy.yml` con imagen, puerto y volúmenes. `kamal accessory boot db` inicia el servicio en el servidor correcto. Los accesorios no pasan por kamal-proxy: se conectan directamente mediante variables de entorno.",{"type":35,"title":85,"body":86},"Configuración multi-servidor y despliegues paralelos","Kamal despliega hacia todos los servidores de un rol en paralelo por defecto. Para un cluster de servidores web, lista sus IPs bajo `servers: web:`. Para un despliegue progresivo (rolling), añade `boot: limit: 2 wait: 10` — Kamal desplegará en 2 servidores a la vez con 10 segundos entre grupos. Los roles permiten diferenciar los servidores: bajo `servers:` declara `web:` (servidores HTTP) y `workers:` con un comando específico como `bundle exec sidekiq`. Cada rol puede tener sus propios servidores, secretos y variables. Un único kamal-proxy funciona en el servidor `primary` (el primero de la lista web); los demás servidores solo ejecutan el contenedor de la aplicación.",{"type":35,"title":88,"body":89},"Variables de entorno y secretos — buenas prácticas","La separación entre variables claras y secretos es explícita en Kamal 2. En `deploy.yml`, las variables no sensibles van bajo `env: clear:` (aparecen en los logs e inspección de contenedor), y los secretos bajo `env: secret:` — su valor se lee desde `.kamal\u002Fsecrets` en el momento del despliegue y se inyecta en el contenedor sin pasar en texto plano por un comando shell visible. Cada rol debe listar explícitamente los secretos que usa. El comando `kamal secrets print` muestra los valores resueltos para verificar que la lectura desde un gestor de contraseñas funciona correctamente antes de desplegar.",{"type":91,"body":92},"tip","Si un despliegue introduce una regresión, no esperes al próximo ciclo de build: ejecuta `kamal rollback [VERSION]` para reapuntar kamal-proxy instantáneamente a una imagen ya presente en el VPS. Lista las versiones disponibles con `kamal app images`. El rollback no reconstruye nada — reapunta el proxy en segundos. Además, `kamal app exec 'comando'` permite ejecutar migraciones o abrir una consola en el contenedor activo sin abrir manualmente una sesión SSH.",{"type":35,"title":94,"body":95},"HTTPS automático con kamal-proxy y Let's Encrypt","Kamal-proxy gestiona el ciclo de vida TLS completo: escucha en el puerto 80, responde a los desafíos ACME HTTP-01 de Let's Encrypt, obtiene el certificado, lo almacena en un volumen Docker en el servidor y lo renueva automáticamente antes de su caducidad. El único requisito previo es que el nombre de host declarado en `proxy: host:` resuelva a la IP del VPS en el momento del primer despliegue — el desafío ACME es síncrono y bloquea el arranque si el DNS no se ha propagado. En servidores con múltiples apps cada una con su propio dominio, kamal-proxy gestiona un certificado separado por dominio vía SNI.",{"type":35,"title":97,"body":98},"Resolución de errores — problemas frecuentes al desplegar con Kamal","**SSH connection timeout**: verifica que la IP del servidor sea accesible (`ssh -i tu_clave root@203.0.113.10`) y que el cortafuegos permita el puerto 22. El agente SSH debe estar activo. **Target failed to become healthy**: el health check por defecto consulta `GET \u002Fup` — si tu aplicación no responde en esa ruta, declara `proxy: healthcheck: path: \u002Fhealth` en `deploy.yml`. Verifica también que `app_port:` coincida con el puerto real del contenedor. **Error de autenticación en el registro**: ejecuta `kamal registry login` y reintenta. En CI, verifica que la variable `KAMAL_REGISTRY_PASSWORD` esté exportada antes de `kamal deploy`. **Conflicto de puertos en el servidor**: si un proceso externo ocupa el puerto 80 o 443, kamal-proxy no puede iniciarse; identifícalo con `ss -tlnp | grep -E '80|443'`. **kamal setup falla al instalar Docker**: la cuenta SSH debe tener derechos sudo, o instala Docker manualmente y relanza `kamal setup`.",{"type":35,"title":100,"body":101},"Integrar Kamal en un pipeline CI\u002FCD con GitHub Actions","Un flujo de trabajo típico de GitHub Actions para Kamal 2 tiene dos trabajos: un trabajo de pruebas (ejecutado en cada push) y un trabajo de despliegue condicional (activado al hacer push a `main` o al publicar una release). En el trabajo de despliegue: instala Ruby y la gema Kamal, luego ejecuta `kamal deploy` con los secretos inyectados desde GitHub Secrets. Elementos clave del archivo `.github\u002Fworkflows\u002Fdeploy.yml`: el trabajo de despliegue depende del de pruebas (`needs: test`), configura las variables de entorno necesarias, instala Kamal con una versión fijada (`gem install kamal -v 2.12.0`) y ejecuta `kamal deploy`. El agente SSH se configura vía `webfactory\u002Fssh-agent@v0.9.0` con la clave privada almacenada en GitHub Secrets. La variable `KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}` inyecta la contraseña del registro de contenedores desde GitHub Secrets.",{"type":103,"title":104,"rows":105,"headers":130},"comparison","Kamal v1 vs Kamal v2 — resumen de diferencias",[106,110,114,118,122,126],[107,108,109],"Proxy","Traefik (declarativo, polling de API)","kamal-proxy (imperativo, comandos directos)",[111,112,113],"Secretos",".env en la raíz del proyecto",".kamal\u002Fsecrets (shell evaluado, gestores de contraseñas)",[115,116,117],"SSL","Gestionado por Traefik vía ACME","Gestionado por kamal-proxy (Let's Encrypt integrado)",[119,120,121],"Múltiples apps","No soportado de forma nativa","Nativo: varias apps por servidor, un solo proxy",[123,124,125],"Actualización","—","`kamal upgrade` detecta y migra la config v1",[127,128,129],"Config del proxy en deploy.yml","Bloque `traefik:`","Bloque `proxy:` con `host`, `ssl`, `app_port`",[5,131,132],"Kamal v1","Kamal v2",{"type":35,"title":134,"body":135},"Kamal en un VPS de ServOrbit — del comando al dominio en órbita","Un VPS Cloud de ServOrbit con Ubuntu 24.04 cumple todos los requisitos de Kamal desde el primer momento: acceso SSH por clave, red de 1 Gbit\u002Fs e IP dedicada. El flujo de trabajo habitual: crea un registro DNS A apuntando `app.your-domain.com` a la IP del VPS, luego ejecuta `kamal setup` desde tu máquina local — Kamal instala Docker, inicia kamal-proxy, obtiene el certificado Let's Encrypt y despliega tu aplicación en una sola pasada. A partir de entonces, cada `kamal deploy` desde tu terminal o pipeline CI aplica la actualización sin interrupciones. Para alojar varios proyectos en el mismo VPS, cada uno con su propio dominio y certificado, añade una aplicación en un segundo `deploy.yml` apuntando al mismo servidor — kamal-proxy enruta por hostname sin reconfiguración. La facturación es la del VPS, sin coste adicional asociado al despliegue.","Controle sus despliegues Kamal en un VPS Cloud ServOrbit","Aprovisione un VPS Cloud con la plantilla Despliegue y acceso SSH por clave: Kamal instala Docker en él y despliega su aplicación en zero-downtime desde el primer comando.","Ver los VPS Cloud","\u002Fvps-cloud",[141,161,175],{"id":142,"slug":143,"slugs":144,"title":148,"excerpt":149,"readTime":150,"views":151,"isPinned":19,"publishedAt":152,"updatedAt":153,"category":154,"categories":155,"featuredImage":29,"bgImage":30,"posterImage":157,"relatedSolution":158},33,"desplegar-aplicaciones-con-caprover-en-un-vps",{"fr":145,"en":146,"ar":147,"es":143},"deployer-avec-caprover","deploy-your-applications-with-caprover-on-a-vps","انشر-تطبيقاتك-باستخدام-caprover-على-خادم-vps","Desplegar sus aplicaciones con CapRover en un VPS","Guía completa de CapRover: instalación, captain-definition, CI\u002FCD con GitHub Actions, clúster multinodo, copias de seguridad y resolución de problemas.",10,1,"2026-05-18T00:00:00+00:00","2026-09-09T21:41:06+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[156],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-caprover-poster.svg",{"categorySlug":159,"appSlug":160},"despliegue-de-aplicaciones-devops","caprover",{"id":162,"slug":163,"slugs":164,"title":168,"excerpt":169,"readTime":23,"views":18,"isPinned":19,"publishedAt":170,"updatedAt":21,"category":171,"categories":172,"featuredImage":29,"bgImage":30,"posterImage":174,"relatedSolution":29},34,"desplegar-aplicaciones-con-dokku-en-un-vps",{"fr":165,"en":166,"ar":167,"es":163},"deployer-avec-dokku","deploy-your-applications-with-dokku-on-a-vps","انشر-تطبيقاتك-باستخدام-dokku-على-خادم-vps","Desplegar sus aplicaciones con Dokku en un VPS","Despliegue sus apps con Dokku, el PaaS más pequeño del mercado: git push, buildpacks de Heroku y SSL automático en un VPS ligero.","2026-05-17T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[173],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-dokku-poster.svg",{"id":176,"slug":177,"slugs":178,"title":182,"excerpt":183,"readTime":184,"views":18,"isPinned":19,"publishedAt":185,"updatedAt":21,"category":186,"categories":187,"featuredImage":29,"bgImage":30,"posterImage":189,"relatedSolution":190},35,"desplegar-aplicaciones-con-portainer-en-un-vps",{"fr":179,"en":180,"ar":181,"es":177},"deployer-avec-portainer","deploy-your-applications-with-portainer-on-a-vps","انشر-تطبيقاتك-باستخدام-portainer-على-خادم-vps","Desplegar sus aplicaciones con Portainer en un VPS","Pilote Docker visualmente con Portainer en su VPS: contenedores, stacks, volúmenes y redes gestionados desde una interfaz web clara.",4,"2026-05-16T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[188],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-portainer-poster.svg",{"categorySlug":159,"appSlug":191},"portainer",1789665015660]