在 VPS 上自托管 KiroCrew:让代理持续运行
使用固定版本的 Docker 容器在 VPS 上运行 KiroCrew,让记忆和计划任务跨重启保留。本文涵盖 systemd、SSH、备份、升级失败后的回滚,以及避免暴露 5476 端口。
为什么选择在 VPS 上自托管 KiroCrew,而不是在笔记本电脑上
只有在一台不会休眠的机器上运行 KiroCrew,自托管才有意义。因此,VPS 适合运行它,笔记本电脑则不适合。KiroCrew 会将会话历史记录、语义记忆、计划任务和审批队列保存到磁盘,并在进程重启后重新加载这些数据。如果计划任务在 03:00 到期时进程没有运行,这些数据就没有作用;而笔记本电脑合上后不会运行进程。
KiroCrew 是 Kiro 团队开发的开源代理工作区,采用 Apache 2.0 许可证,首批公开版本于 2026 年 8 月初发布。一个称为 gateway 的进程负责保存状态,并在 5476 端口提供 Web 控制面板。您可以通过控制面板、kirocrew CLI,或 Slack 等聊天渠道访问 gateway。您自托管的只有 gateway,因此本指南重点介绍如何让它持续运行、避免将其暴露在公网,以及在升级失败后恢复它。
开始前需要了解两点。KiroCrew 会调用 kiro-cli,首次使用时需要通过 Kiro 帐户登录一次;代理推理费用计入 Kiro 方案,因此截至 2026 年 8 月,这不是离线部署。该项目也只有几周历史。请假设您迟早需要回滚,并采用支持回滚的安装方式。如果您以前没有在服务器上运行过代理,请参阅在 VPS 上运行编码代理,其中介绍了本指南所依据的基本规则。
KiroCrew 的依赖项及其状态存储位置
原生安装需要 Python 3.10 或更高版本(项目推荐 3.12)。如果从源代码构建 dashboard,还需要 Node.js 18 或更高版本,以及 kiro-cli;首次启动时,系统会自动安装并完成登录。容器安装不要求主机具备这些依赖,只需要 Docker。这是优先选择容器安装的主要原因。
状态存储在 ~/.kiro/crew 中,KIROCREW_HOME 环境变量可将其移动到其他位置。其中包含:
config.json:网关设置和聊天频道凭据。.env:密钥。workspace/memory/:首选项、项目备注和聊天历史记录。memory.db和memory_index.db:语义索引和全文索引。models/:首次运行时下载的嵌入模型。gateway.log和security_events.jsonl:运行时日志和安全事件日志。
该目录就是整个安装内容。将它复制到新的 VPS,即可迁移您的 agent。因此,下面的备份部分比安装部分更重要。
请按磁盘空间而不是 RAM 进行规划。网关是一个 Python 进程;真正占用主机资源的是 agent 运行的任务,例如构建或测试套件。状态目录会随着聊天历史记录增长,嵌入模型也会在首次启动时下载。因此,请在运行几周后使用 du -sh ~/.kiro/crew 测量您自己的主机,而不要依赖项目发布初期公布的任何数据。
应使用哪种安装方式
该项目提供 3 种安装方式。单行安装程序会下载 wheel,并将 kirocrew 添加到您的 PATH:
curl -fsSL https://download.crew.kiro.dev/cli.sh | sh它接受 channel flag 和 version flag:
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.3容器镜像发布在 ghcr.io/kirodotdev/kirocrew,每个 tag 都提供 linux/amd64 和 linux/arm64。源码构建需要 git clone 和 make build,适用于修改代码的人员,不适用于运行该项目的人员。
请使用容器。原生安装会将 Python 包、Node 和 kiro-cli 安装到运行其他服务的同一台主机上。升级失败后,您需要手动清理这些改动。容器将运行时放在一个镜像中,将状态放在一个卷中。这样,回滚只需更改 tag 并重启。
将镜像固定到发布版本标签,而不是固定到 stable
项目自身的示例使用 stable 标签:
docker run -d --name kirocrew \
-p 127.0.0.1:5476:5476 \
-v kirocrew-home:/home/kirocrew \
ghcr.io/kirodotdev/kirocrew:stablestable 是一个会移动的标签。它始终指向当前最新的稳定版本,因此下一次拉取可能在您未主动选择的情况下更改正在运行的版本,而且该标签无法记录具体使用的是哪个版本。版本标签不可变,因此应固定到某个版本。以 2026 年 8 月 6 日为准,最新发布版本是 0.1.3,发布于 2026 年 8 月 5 日。项目还提供 nightly 标签。对于这样一个成立不久的项目,这意味着代码可能就在今天早上发生过变化。
写入 /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:启动容器,然后检查镜像用于自身 HEALTHCHECK 的健康检查端点:
cd /opt/kirocrew
docker compose up -d
docker compose ps
curl -s http://127.0.0.1:5476/api/healthdocker compose ps 应在大约一分钟内将容器报告为健康,/api/health 无需令牌即可返回响应(/api/live 和 /api/ready 也是如此,因此可以将它们用作探针)。如果状态一直停留在 starting,请先读取 docker logs kirocrew,再进行任何修改。首次运行会下载嵌入模型,因此网络连接较慢时,首次启动会耗时较长。
使用 systemd 保持服务运行
restart: unless-stopped 会在容器崩溃和系统重启后重新启动容器,前提是 Docker 本身会在启动时启动。单元文件可以明确声明这一依赖,并提供一条命令,在备份前停止整个服务栈。系统启动时启动 Docker Compose 服务栈介绍了通用模式。KiroCrew 的配置如下,在 /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 应显示为 active (exited),这表示该单元运行正常。这里使用 Type=oneshot 配合 RemainAfterExit=yes 是正确的,因为容器启动后,docker compose up -d 会立即返回:systemd 跟踪的是服务栈已启动这一状态,而不是前台进程。如果改为 Type=simple,systemd 会看到命令立即退出,将服务标记为已停止,然后根据 Restart= 设置决定放弃重启,或进入反复重启循环。对于原生安装,项目提供了等效的 kirocrew service install,它会写入 /etc/systemd/system/kirocrew.service,并以您的用户身份运行网关。不要同时运行这两个单元。有关该主题的更完整介绍,请参阅 VPS 上的 systemd 服务和计时器。
首次运行:登录并获取仪表板令牌
容器会启动网关,但代理运行时尚未登录。请在容器内登录:
docker exec -it kirocrew kiro-cli login命令会输出设备代码和 URL。请在您自己的浏览器中打开该 URL。然后生成仪表板令牌:
docker exec kirocrew kirocrew token --ttl 2h仪表板 URL 为 http://localhost:5476/?token=<the token>。令牌会过期:会话默认持续一小时,文档规定的最长时长为二十小时。仪表板显示空白,或打开后立即将您退出,通常是因为令牌已过期,请重新生成令牌。切勿将令牌粘贴到工单或聊天消息中,因为持有令牌的人即可控制您的代理。
通过 SSH 访问仪表板,绝不要发布端口 5476
重新查看项目示例中的绑定地址:-p 127.0.0.1:5476:5476。容器内的网关监听 0.0.0.0,因为它必须能够通过端口映射访问;但该映射只将端口发布到主机的回环地址。删除 127.0.0.1: 前缀后,任何扫描该端口的人都可以从公网访问网关。防火墙规则也无法解决此问题:Docker 通过写入 DNAT 规则来发布端口,而这些规则的处理顺序早于 ufw 的过滤规则,因此 ufw deny 5476 对已发布的端口不起作用。Docker 端口绕过 ufw详细说明了这一机制。
在笔记本电脑上通过 SSH 转发该端口:
ssh -N -L 5476:127.0.0.1:5476 you@your-server.example.com保持该命令运行,然后在本机打开 http://localhost:5476/?token=<the token>。若要在每次连接时自动建立转发,将其写入 ~/.ssh/config:
Host your-server.example.com
LocalForward 5476 127.0.0.1:5476如果笔记本电脑上的端口 5476 已被占用,只修改左侧的端口号:ssh -N -L 45476:127.0.0.1:5476 you@your-server.example.com,然后访问 http://localhost:45476/?token=...。
通过隧道访问时,请注意一个文档记录的行为:网关会将转发的请求识别为远程请求,因此仪表板中的配置写入和机密信息显示端点会拒绝这些请求。通过 SSH 无法保存设置时,这是预期行为,不是错误。请直接在主机上编辑配置:
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 kirocrew对于手机访问,项目建议使用 Tailscale 的 tailscale serve,这样仪表板会保留在您自己的 tailnet 内,而不是暴露在公网主机名下。优先使用这种方式,不要配置公网反向代理。令牌会出现在 URL 中,而请求经过的每个访问日志都会记录该 URL。
尽可能缩小代理的爆炸半径
容器首次启动时会探测是否支持沙箱,探测结果决定代理是否可以执行任何操作。如果支持命名空间隔离,代理子进程会在隔离环境中运行。如果不支持,且未设置 KIROCREW_ALLOW_UNSANDBOXED=1,则拒绝执行,而不是在无隔离的情况下运行。因此,如果网关看起来运行正常,但每个任务都停滞不前,通常就是这个原因。该决定会记录在首次运行生成的 docker logs kirocrew 中。项目还发布了一个 seccomp(安全计算模式)配置文件,您可以应用它:
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.json如果确实设置了 KIROCREW_ALLOW_UNSANDBOXED=1,请明确了解发生了什么变化:此时,容器成为代理与服务器之间唯一的隔离边界。项目的警告值得完整重申。不要挂载您不会直接交给代理的主机路径。实际上,这意味着不能挂载 Docker 套接字、/ 的任何绑定挂载,以及存放其他服务数据的任何目录。
其余措施适用于所有获准执行命令的代理。将凭据权限限制在它所需的一个仓库或一个存储桶内,绝不要使用具有整个账户权限的个人令牌。使用专用用户运行代理,并确保其 home 目录中不存放其他内容;这正是 VPS 上的最小权限用户 的用途。当代理编写代码后又运行这些代码时,应为它提供一台即使被破坏也不会造成问题的机器:供编码代理使用的一次性 VM 比此 compose 文件中的任何标志都更强,因为您可以直接删除它,而不必清理环境。同样的思路也适用于 在 VPS 上安全运行 OpenClaw 和 在 VPS 上自行托管 Hermes 代理。计划任务会在您休息时继续产生费用,因为推理费用会计入您的 Kiro 计划。因此,在添加每晚运行的任务前,请先按照 控制 AI 代理在 VPS 上的费用 中的说明设置限制。
每次升级前备份状态卷
先确认实际的卷名称。Compose 会使用项目名称为命名卷添加前缀。项目名称默认为目录名称,因此 /opt/kirocrew/compose.yaml 中声明为 kirocrew-home 的卷会创建为 kirocrew_kirocrew-home:
docker volume ls复制任何内容前,先停止网关。memory.db 和 memory_index.db 是 SQLite 数据库。在数据库写入期间复制,可能会捕获未完成的事务,恢复后会得到损坏的文件。项目自身的迁移说明也要求执行相同操作:只有在网关停止后才能迁移记忆数据。
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 kirocrew将归档复制到本机以外的位置。恢复时使用相同的命令,但必须先停止容器,并使用 tar xzf 代替 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 kirocrew迁移到新主机与在原主机上恢复是两项不同的工作,项目对此有明确说明。workspace/memory/ 下的聊天记录和项目备注需要一并迁移,两个数据库文件和 config.json 也需要迁移。PID 文件、安全事件日志和 .env 与旧主机关联,因此不要迁移它们;在新主机上重新输入密钥。
如何回滚有问题的升级
升级过程很短,而且只有在固定版本后才安全。先创建备份,再修改标签:
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会在本机尚未存在该镜像时拉取它,因此修改标签就是完整的升级过程。回滚时使用相同的步骤,但改回旧版本号。这样可以准确恢复到升级前使用的镜像,因为版本标签不可变。
二进制文件可以顺利回滚。状态数据可能无法回滚。较新的网关可能会重写 config.json,或将内存数据库迁移为旧版网关无法读取的格式。截至 2026 年 8 月,没有记录在案的降级路径。因此,如果旧镜像启动后行为异常,不要继续排查。停止它,恢复升级前创建的备份,然后重新启动。备份必须先于升级,原因就在这里。对于这样仍处于早期阶段的项目,先升级、之后再备份的习惯会导致回滚失败。
这里尚未得到证实的内容
请如实看待这款软件的使用年限。撰写本文时,0.1.3 版本发布还不到几天,其发布说明只是自动生成的变更日志链接,并非迁移说明,而且目前还没有升级记录可供参考。本指南中的内容都不是长期运行结果。因此,请在您自己的服务器上测量内存增长、数据库大小和调度器可靠性,不要直接假定它们符合预期。
有两种行为值得您在依赖它们之前自行测试。第一,降级版本是否能够读取由更新版本写入的状态:请在问题尚不重要时对卷的副本进行测试,不要等到服务中断时再测试。第二,当计划任务即将执行时,Kiro 登录状态已过期,网关会如何处理。这两种情况都属于早期项目可能在版本之间悄然修复的边缘问题,现在验证它们的成本很低。
FAQ
为什么 KiroCrew 控制面板无法通过服务器的公网 IP 打开?
因为发布的示例将端口绑定到了回环地址。-p 127.0.0.1:5476:5476 仅将容器端口映射到主机的回环地址,这是有意设计的。使用 ssh -N -L 5476:127.0.0.1:5476 you@your-server 通过 SSH 转发端口,然后在笔记本电脑上打开 http://localhost:5476/?token=<token>。删除 127.0.0.1: 前缀可以使其可访问,但会将网关暴露到公网。防火墙规则无法阻止这种访问,因为 Docker 的已发布端口 DNAT 规则会在 ufw 过滤流量之前生效。
KiroCrew 将数据存储在哪里?应该备份哪些内容?
所有数据都位于 ~/.kiro/crew 下,该路径在容器镜像中是 /home/kirocrew/.kiro/crew,而 KIROCREW_HOME 可将其重新定位。在网关停止运行后,备份整个目录或整个 Docker 卷。memory.db 和 memory_index.db 是 SQLite 数据库,因此在网关写入期间复制可能导致数据不一致。迁移到新主机时,workspace/memory/、两个数据库文件和 config.json 会一并迁移;PID 文件、安全事件日志和 .env 则属于旧主机。
应使用 stable 标签还是版本标签?
使用版本标签。stable 每次发布新版本时都会移动,因此下次拉取时,正在运行的版本可能发生变化,而且标签本身无法说明当前运行的版本。0.1.3 等版本标签不可变,这正是回滚能够正常工作的原因:恢复旧版本号即可获得完全相同的镜像。截至 6 August 2026,最新版本是 0.1.3。
为什么我的代理拒绝执行任何命令?
容器会在首次启动时检测沙箱支持。如果无法隔离代理子进程,且未设置 KIROCREW_ALLOW_UNSANDBOXED=1,容器会拒绝执行这些进程,而不是在无隔离环境中运行它们。因此,网关看似正常,但每个任务都会停滞。docker logs kirocrew 显示首次运行时作出的沙箱决策。设置此变量后,容器将成为代理与主机之间唯一的隔离边界。因此,如果设置该变量,请不要挂载任何不会直接交给代理使用的内容。
自托管 KiroCrew 是否需要 Kiro 账户?
是,截至 August 2026。KiroCrew 是基于 Apache 2.0 许可的自由软件,但它驱动 kiro-cli,该组件需要一次性登录,且代理推理费用计入 Kiro 计划。在容器中运行 docker exec -it kirocrew kiro-cli login,然后在浏览器中批准设备代码。在登录完成前,网关可以启动,控制面板也可以加载,但代理没有可连接的模型。