Alojar KiroCrew en un VPS con Docker y systemd
Mantén KiroCrew activo en un VPS con Docker y systemd: conserva memoria y trabajos tras reinicios, accede por SSH y restaura copias o versiones anteriores.
Por qué alojar KiroCrew en un VPS en lugar de un portátil
Alojar KiroCrew por cuenta propia sólo resulta útil en una máquina que nunca entra en suspensión, por lo que un VPS es el lugar adecuado y un portátil no. KiroCrew guarda en disco el historial de sesiones, la memoria semántica, los trabajos programados y la cola de aprobaciones, y vuelve a cargar todos esos datos cuando se reinicia el proceso. Nada de eso sirve si el proceso no está ejecutándose a las 03:00, cuando debe ejecutarse un trabajo programado, y un portátil cerrado no lo está ejecutando.
KiroCrew es un espacio de trabajo de agentes de código abierto del equipo de Kiro, con licencia Apache 2.0, cuyas primeras versiones públicas aparecieron a principios de agosto de 2026. Un proceso, denominado gateway, posee el estado y ofrece un panel web en el puerto 5476. Puede acceder a ese gateway desde el panel, desde la CLI kirocrew o desde un canal de chat como Slack. El gateway es el único componente que aloja por cuenta propia, por lo que esta guía trata sobre mantenerlo activo, mantenerlo fuera de Internet pública y poder restaurarlo después de una actualización defectuosa.
Hay dos aspectos que debe conocer antes de empezar. KiroCrew utiliza kiro-cli, que requiere un inicio de sesión único con una cuenta de Kiro, y la inferencia de los agentes se factura a un plan de Kiro, por lo que, en agosto de 2026, no es una configuración sin conexión. El proyecto también tiene sólo unas semanas de antigüedad. Dé por hecho que en algún momento tendrá que volver a una versión anterior e instálelo de forma que pueda hacerlo. Si nunca ha ejecutado un agente en un servidor, ejecutar un agente de código en un VPS explica los conceptos básicos en los que se basa esta guía. Si la parte del agente le resulta más nueva que la del servidor, lea primero qué son realmente el bucle de un agente, sus herramientas y su memoria para que las decisiones siguientes se entiendan como opciones técnicas y no como comandos arbitrarios.
Qué necesita KiroCrew y dónde guarda su estado
Una instalación nativa necesita Python 3.10 o una versión posterior (el proyecto recomienda 3.12), Node.js 18 o una versión posterior si compila el dashboard desde el código fuente, y kiro-cli, que se instala e inicia sesión automáticamente durante el primer arranque. La instalación en contenedor no necesita nada de eso en el host. Necesita Docker. Esta es la razón principal para preferirla.
El estado se guarda en ~/.kiro/crew, y la variable de entorno KIROCREW_HOME permite trasladarlo a otra ubicación. Su contenido incluye:
config.json: configuración del gateway y credenciales de los canales de chat..env: secretos.workspace/memory/: preferencias, notas del proyecto e historial de chat.memory.dbymemory_index.db: índices semánticos y de texto completo.models/: modelo de embeddings, descargado durante el primer arranque.gateway.logysecurity_events.jsonl: registro de ejecución y registro de eventos de seguridad.
Ese directorio es la instalación. Cópielo a un VPS nuevo y habrá trasladado su agente. Por eso la sección de copias de seguridad que aparece más abajo es más importante que la sección de instalación.
Planifique el espacio en disco, no la RAM. El gateway es un proceso de Python. Lo que realmente carga el equipo es lo que ejecute el agente: una compilación o una suite de pruebas. El directorio de estado crece con el historial de chat y el modelo de embeddings se descarga durante el primer arranque. Por eso, mídalo en su propio equipo con du -sh ~/.kiro/crew después de unas semanas, en lugar de confiar en una cifra publicada durante el primer mes de un proyecto. Compárelo con un entorno de ejecución que asigna a cada worker su propio contenedor y su propio navegador, donde alojar los compañeros de IA de OpenBot convierte la RAM en una cuestión prioritaria antes que el disco.
Qué ruta de instalación de las tres debe usar
El proyecto publica tres. El instalador de una línea descarga un wheel y coloca kirocrew en su PATH:
curl -fsSL https://download.crew.kiro.dev/cli.sh | shAcepta un indicador de canal y un indicador de versión:
curl -fsSL https://download.crew.kiro.dev/cli.sh | sh -s -- --channel insider
curl -fsSL https://download.crew.kiro.dev/cli.sh | sh -s -- --version 0.1.3La imagen de contenedor se publica en ghcr.io/kirodotdev/kirocrew, para linux/amd64 y linux/arm64 en cada etiqueta. La compilación desde el código fuente requiere git clone y make build, y está dirigida a quienes modifican el código, no a quienes lo ejecutan.
Use el contenedor. Una instalación nativa coloca paquetes de Python, Node y kiro-cli en el mismo host que ejecuta los demás servicios. Si una actualización falla, tendrá que deshacer esos cambios manualmente. El contenedor mantiene el entorno de ejecución en una imagen y el estado en un volumen. Así, una reversión sólo requiere cambiar la etiqueta y reiniciar.
Fije la imagen en una etiqueta de versión, no en stable
El ejemplo del propio proyecto utiliza la etiqueta stable:
docker run -d --name kirocrew \
-p 127.0.0.1:5476:5476 \
-v kirocrew-home:/home/kirocrew \
ghcr.io/kirodotdev/kirocrew:stablestable es una etiqueta mutable. Apunta a la versión estable más reciente disponible, por lo que la siguiente extracción puede cambiar la versión que ejecuta sin que usted la haya seleccionado. Además, la etiqueta no indica qué versión era esa. Las etiquetas de versión son inmutables, así que utilice una de ellas. La versión más reciente al 6 de agosto de 2026 es 0.1.3, publicada el 5 de agosto de 2026. También existe la etiqueta nightly, que en un proyecto tan reciente significa que el código cambió esta mañana.
Escriba /opt/kirocrew/compose.yaml:
services:
kirocrew:
image: ghcr.io/kirodotdev/kirocrew:0.1.3
container_name: kirocrew
restart: unless-stopped
ports:
- "127.0.0.1:5476:5476"
volumes:
- kirocrew-home:/home/kirocrew
volumes:
kirocrew-home:Inícielo y compruebe después el endpoint de estado que la imagen también utiliza para su propio HEALTHCHECK:
cd /opt/kirocrew
docker compose up -d
docker compose ps
curl -s http://127.0.0.1:5476/api/healthdocker compose ps debería indicar que el contenedor está en buen estado en aproximadamente un minuto. /api/health responde sin token, al igual que /api/live y /api/ready, lo que permite utilizarlos como sondas. Si el estado permanece en starting, lea docker logs kirocrew antes de cambiar nada. La primera ejecución descarga el modelo de embeddings, por lo que una conexión lenta hace que el primer arranque tarde más.
Manténgalo en ejecución con systemd
restart: unless-stopped vuelve a iniciar el contenedor después de un fallo y después de reiniciar el sistema, siempre que Docker se inicie durante el arranque. Un archivo de unidad hace explícita esa dependencia y proporciona un único comando para detener toda la pila antes de una copia de seguridad. Iniciar una pila de Docker Compose durante el arranque explica el patrón general. Esta es la estructura para KiroCrew, en /etc/systemd/system/kirocrew.service:
[Unit]
Description=KiroCrew gateway
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/kirocrew
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now kirocrew
systemctl status kirocrewsystemctl status kirocrew debería mostrar active (exited), que es el resultado correcto para esta unidad. Type=oneshot con RemainAfterExit=yes es correcto en este caso porque docker compose up -d devuelve el control en cuanto se inicia el contenedor: systemd supervisa que la pila esté activa, no un proceso en primer plano. Escriba Type=simple en su lugar y systemd verá que el comando termina inmediatamente, marcará el servicio como detenido y después se rendirá o entrará en un bucle de reinicios, según la configuración de Restart=. En una instalación nativa, el proyecto incluye su propio equivalente, kirocrew service install, que escribe /etc/systemd/system/kirocrew.service y ejecuta el gateway con su usuario. No ejecute ambas unidades. Encontrará una explicación más amplia en servicios y temporizadores de systemd en un VPS. Una unidad que no vuelve a iniciarse permanece silenciosa a menos que haga que informe del fallo, así que añada un controlador OnFailure= que envíe una alerta a su propio servidor ntfy y sabrá desde el teléfono que el gateway está caído, en lugar de enterarse mediante una tarea programada que nunca se ejecutó.
Primera ejecución: iniciar sesión y obtener un token del dashboard
El contenedor inicia la gateway, pero el runtime del agente todavía no tiene una sesión iniciada. Inicie sesión dentro del contenedor:
docker exec -it kirocrew kiro-cli loginEl comando muestra un código de dispositivo y una URL que debe abrir en su propio navegador. Después, genere un token del dashboard:
docker exec kirocrew kirocrew token --ttl 2hLa URL del dashboard es http://localhost:5476/?token=<the token>. Los tokens caducan: las sesiones duran una hora de forma predeterminada y el máximo documentado es de veinte horas. Si el dashboard se carga en blanco o le devuelve directamente a la pantalla de inicio de sesión, normalmente el token ha caducado. Genere otro token. Nunca pegue un token en un ticket ni en un mensaje de chat, porque quien lo tenga controla su agente.
Acceda al panel mediante SSH y no publique nunca el puerto 5476
Revise la dirección de enlace del ejemplo del proyecto: -p 127.0.0.1:5476:5476. Dentro del contenedor, la puerta de enlace escucha en 0.0.0.0 porque debe ser accesible mediante la asignación de puertos, pero la asignación sólo publica el puerto en loopback del host. Elimine el prefijo 127.0.0.1: y la puerta de enlace quedará expuesta en Internet para cualquiera que analice ese puerto. Una regla del firewall tampoco le protegerá: Docker publica los puertos escribiendo reglas DNAT que se evalúan antes del filtrado de ufw, por lo que ufw deny 5476 no hace nada con un puerto publicado. Puertos de Docker que omiten ufw explica este mecanismo.
Reenvíe el puerto mediante SSH desde su portátil:
ssh -N -L 5476:127.0.0.1:5476 you@your-server.example.comDeje ese proceso en ejecución y abra http://localhost:5476/?token=<the token> localmente. Para activar el reenvío automáticamente en cada conexión, añádalo a ~/.ssh/config:
Host your-server.example.com
LocalForward 5476 127.0.0.1:5476Si el puerto 5476 ya está en uso en su portátil, cambie sólo el número de la izquierda: ssh -N -L 45476:127.0.0.1:5476 you@your-server.example.com, y después abra http://localhost:45476/?token=.... Empezará a encadenar reenvíos de este tipo en cuanto un segundo agente comparta el servidor, porque alojar open-kritt para análisis de seguridad añade otro panel accesible sólo por loopback en el mismo servidor, en el puerto 5173.
Hay un comportamiento documentado que debe tener en cuenta al usar un túnel: la puerta de enlace interpreta las peticiones reenviadas como remotas, por lo que los endpoints de escritura de configuración y revelación de secretos del panel las rechazan. Si un cambio de configuración no se guarda mediante SSH, se trata de este comportamiento y no de un error. Edite la configuración directamente en el host:
docker cp kirocrew:/home/kirocrew/.kiro/crew/config.json .
# edit config.json here
docker cp config.json kirocrew:/home/kirocrew/.kiro/crew/config.json
docker exec -u 0 kirocrew chown kirocrew:kirocrew /home/kirocrew/.kiro/crew/config.json
docker restart kirocrewPara el acceso desde el teléfono, el proyecto recomienda tailscale serve de Tailscale, que mantiene el panel dentro de tu propia tailnet en lugar de publicarlo con un nombre de host público. Es preferible a un reverse proxy público. El token viaja en la URL, y la URL queda registrada en cada registro de acceso que atraviesa. Esta regla se refiere al servicio que está detrás del puerto, no al puerto en sí: algo como Halcyon, que reconstruye una biblioteca de Jellyfin como una tienda de vídeos de los años 90 navegable está pensado para que otras personas lo abran y es un candidato adecuado para un reverse proxy, mientras que una puerta de enlace que puede ejecutar comandos en tu servidor no lo es.
Otorgue al agente el menor radio de impacto posible
El contenedor comprueba si existe compatibilidad con el sandbox durante el primer arranque, y el resultado determina si los agentes pueden ejecutar algo. Si el aislamiento mediante namespaces está disponible, los subprocesos del agente se ejecutan de forma aislada. Si no está disponible y KIROCREW_ALLOW_UNSANDBOXED=1 no está definido, la ejecución se rechaza en lugar de ejecutarse sin aislamiento. Por eso, cuando la puerta de enlace parece estar operativa pero todas las tareas se bloquean, esta suele ser la causa. La decisión se guarda en docker logs kirocrew durante esa primera ejecución. El proyecto también publica un perfil de seccomp (secure computing mode) que puede aplicar:
curl -fsSL https://raw.githubusercontent.com/kirodotdev/KiroCrew/main/docker/seccomp/kirocrew-seccomp.json \
-o /opt/kirocrew/kirocrew-seccomp.json security_opt:
- seccomp:./kirocrew-seccomp.jsonSi define KIROCREW_ALLOW_UNSANDBOXED=1, deje claro qué ha cambiado: el contenedor es ahora la única frontera entre el agente y su servidor. Conviene repetir íntegramente la advertencia del proyecto. No monte rutas del host que no entregaría directamente al agente. En la práctica, esto excluye el socket de Docker, cualquier bind mount de / y cualquier directorio que contenga datos de otro servicio.
El resto es el marco que se aplica a todos los agentes autorizados a ejecutar comandos. Restrinja sus credenciales al único repositorio o bucket que necesite. No use nunca un token personal con permisos para toda la cuenta. Ejecútelo como un usuario dedicado cuyo directorio personal no contenga nada más. Para eso sirven los usuarios con privilegios mínimos en un VPS. Cuando el agente escriba código y después lo ejecute, asígnele una máquina que pueda dejar inutilizable: una VM desechable para agentes de programación ofrece una frontera más sólida que cualquier flag de este archivo compose, porque puede eliminarla en lugar de limpiarla. El mismo razonamiento se aplica a ejecutar OpenClaw de forma segura en un VPS y alojar el agente Hermes en un VPS. Las herramientas también forman parte del radio de impacto: si entrega al agente acceso a búsquedas web, cada página que descargue se convierte en una entrada no fiable. Por eso, dirigirlo a su propia instancia de SearXNG es una decisión relacionada con la inyección de prompts tanto como con la configuración de red. Las tareas programadas también generan costes mientras duerme, porque la inferencia se factura a su plan de Kiro. Defina los límites descritos en controlar el coste de un agente de IA en un VPS antes de añadir una tarea nocturna.
Haga una copia de seguridad del volumen de estado antes de cada actualización
Primero, busque el nombre real del volumen. Compose antepone el nombre del proyecto a los volúmenes con nombre. De forma predeterminada, usa el nombre del directorio. Por tanto, el volumen declarado como kirocrew-home en /opt/kirocrew/compose.yaml se crea como kirocrew_kirocrew-home:
docker volume lsDetenga el gateway antes de copiar cualquier archivo. memory.db y memory_index.db son bases de datos SQLite. Copiar una base de datos mientras se está escribiendo puede capturar una transacción a medio escribir y restaurarla como un archivo dañado. Las instrucciones de migración del propio proyecto indican lo mismo: mueva la memoria sólo mientras los gateways estén detenidos. Esta regla de detener primero no es exclusiva de KiroCrew. Si un servidor de fotos comparte el equipo, la comparación entre PhotoPrism e Immich incluye los comandos de copia de seguridad exactos que necesita cada uno de ellos.
sudo systemctl stop kirocrew
docker run --rm -v kirocrew_kirocrew-home:/data:ro -v "$PWD":/backup \
alpine tar czf /backup/kirocrew-2026-08-06.tgz -C /data .
sudo systemctl start kirocrewCopie el archivo comprimido fuera del equipo. La restauración usa el mismo comando, con el contenedor detenido y tar xzf en lugar de tar czf:
sudo systemctl stop kirocrew
docker run --rm -v kirocrew_kirocrew-home:/data -v "$PWD":/backup \
alpine tar xzf /backup/kirocrew-2026-08-06.tgz -C /data
sudo systemctl start kirocrewMigrar a un host nuevo es una tarea distinta de restaurar en el mismo host, y el proyecto especifica cómo hacerlo. El historial de chat y las notas del proyecto almacenados en workspace/memory/ se conservan. También se conservan los dos archivos de base de datos y config.json. Los archivos PID, el registro de eventos de seguridad y .env están vinculados al host antiguo. No los copie y vuelva a introducir los secretos en el equipo nuevo.
Cómo revertir una actualización defectuosa
La actualización es breve y sólo es segura porque fijó una versión. Primero cree la copia de seguridad y después cambie la etiqueta:
sudo systemctl stop kirocrew
# take the backup here, as above
sudo nano /opt/kirocrew/compose.yaml # set the new image tag
sudo systemctl start kirocrew
docker compose -f /opt/kirocrew/compose.yaml ps
curl -s http://127.0.0.1:5476/api/healthdocker compose up -d descarga la imagen si todavía no está en el servidor, por lo que editar la etiqueta constituye toda la actualización. La reversión sigue la misma secuencia con el número anterior y le proporciona exactamente la imagen que tenía antes, porque las etiquetas de versión son inmutables.
El binario se revierte sin problemas. El estado es la parte que puede no hacerlo. Una versión más reciente del gateway puede reescribir config.json o migrar las bases de datos en memoria a un formato que un gateway anterior no pueda leer, y en agosto de 2026 no existe ningún procedimiento de downgrade documentado. Si la imagen anterior se inicia y después funciona de forma anómala, no la depure. Deténgala, restaure la copia de seguridad creada antes de la actualización y vuelva a iniciar el proceso. Esa es la razón por la que la copia de seguridad se crea primero y por la que el hábito de actualizar ahora y hacer la copia después falla en un proyecto tan reciente.
Qué no se demuestra aquí
Sea consciente de la antigüedad de este software. La versión 0.1.3 tiene pocos días en el momento de redactar este texto, sus notas de versión son enlaces automatizados a cambios, no notas de migración, y todavía no existe un historial de actualizaciones. Nada de lo indicado en esta guía es un resultado a largo plazo. Mida el crecimiento de la memoria, el tamaño de la base de datos y la fiabilidad del planificador en su propio sistema en lugar de darlos por supuestos.
Conviene probar por su cuenta dos comportamientos antes de depender de ellos. Primero, compruebe si una versión anterior puede leer el estado escrito por una versión más reciente. Hágalo con una copia del volumen cuando no sea crítico, no durante una interrupción del servicio. Segundo, compruebe qué hace el gateway cuando caduca el inicio de sesión de Kiro mientras debe ejecutarse un trabajo programado. Estos son problemas habituales en un proyecto joven, que pueden corregirse discretamente entre versiones. Ambos son fáciles de comprobar ahora.
FAQ
¿Por qué no se abre el panel de KiroCrew en la IP pública de mi servidor?
Porque el ejemplo publicado enlaza el puerto con loopback. -p 127.0.0.1:5476:5476 asigna el puerto del contenedor únicamente a la dirección loopback del host, de forma deliberada. Acceda mediante el reenvío del puerto por SSH con ssh -N -L 5476:127.0.0.1:5476 you@your-server y abra http://localhost:5476/?token=<token> en su portátil. Eliminar el prefijo 127.0.0.1: para que sea accesible expone el gateway a Internet pública, y una regla del firewall no lo impedirá, porque las reglas DNAT de puertos publicados por Docker se evalúan antes de que ufw filtre el tráfico.
¿Dónde almacena KiroCrew sus datos y qué debo respaldar?
Todo se encuentra en ~/.kiro/crew, que corresponde a /home/kirocrew/.kiro/crew dentro de la imagen del contenedor, y KIROCREW_HOME lo reubica. Haga una copia de seguridad del directorio completo o del volumen Docker completo, con el gateway detenido. memory.db y memory_index.db son bases de datos SQLite, por lo que una copia realizada mientras el gateway escribe puede ser incoherente. Al migrar a un host nuevo, workspace/memory/, los dos archivos de base de datos y config.json se trasladan, mientras que los archivos PID, el registro de eventos de seguridad y .env pertenecen al host antiguo.
¿Debo usar la etiqueta stable o una etiqueta de versión?
Use una etiqueta de versión. stable cambia cada vez que se publica una versión, por lo que la versión que ejecuta puede cambiar en la siguiente extracción y la propia etiqueta no indica qué se está ejecutando. Las etiquetas de versión, como 0.1.3, son inmutables. Eso es precisamente lo que permite realizar una reversión: restaura el número anterior y obtiene la misma imagen. A fecha de 6 de agosto de 2026, la versión más reciente es 0.1.3.
¿Por qué mi agente se niega a ejecutar comandos?
El contenedor comprueba si hay compatibilidad con el sandbox durante su primer arranque. Si no puede aislar los subprocesos del agente y KIROCREW_ALLOW_UNSANDBOXED=1 no está definido, se niega a ejecutarlos en lugar de ejecutarlos sin aislamiento. Por eso el gateway parece estar operativo mientras todas las tareas se bloquean. docker logs kirocrew muestra la decisión del sandbox tomada durante esa primera ejecución. Definir la variable hace que el contenedor sea la única barrera entre el agente y el host. Por tanto, si la define, no monte nada que no entregaría directamente al agente.
¿Necesito una cuenta de Kiro para alojar KiroCrew?
Sí, a fecha de agosto de 2026. KiroCrew es software libre bajo Apache 2.0, pero utiliza kiro-cli, que requiere un inicio de sesión único, y la inferencia del agente se factura a un plan de Kiro. En el contenedor, ejecute docker exec -it kirocrew kiro-cli login y apruebe el código del dispositivo en el navegador. Hasta que se complete ese inicio de sesión, el gateway se inicia y el panel se carga, pero el agente no tiene ningún modelo con el que comunicarse.