Self-host KiroCrew trên VPS, chạy agent 24/7
Chạy KiroCrew trong container cố định trên VPS để giữ memory và lịch sau reboot. Dùng Docker, systemd, SSH, backup và rollback khi upgrade lỗi.
Vì sao nên self-host KiroCrew trên VPS thay vì laptop
Self-host KiroCrew chỉ thực sự có ích trên một máy không bao giờ ngủ, vì vậy VPS phù hợp để chạy KiroCrew còn laptop thì không. KiroCrew lưu lịch sử session, semantic memory, scheduled job và hàng đợi phê duyệt trên disk, rồi nạp lại toàn bộ khi process khởi động lại. Những dữ liệu này không có tác dụng nếu process không chạy lúc 03:00 khi scheduled job đến hạn, và laptop đã đóng thì không chạy process.
KiroCrew là agent workspace mã nguồn mở của team Kiro, được cấp phép theo Apache 2.0, với các bản release công khai đầu tiên vào đầu tháng 08 năm 2026. Một process có tên gateway quản lý state và cung cấp web dashboard trên port 5476. Bạn truy cập gateway đó từ dashboard, từ kirocrew CLI hoặc từ một chat channel như Slack. Gateway là thành phần duy nhất bạn self-host, nên hướng dẫn này tập trung vào việc giữ gateway luôn chạy, không public gateway ra Internet và có thể khôi phục gateway sau một lần upgrade lỗi.
Có hai điều cần biết trước khi bắt đầu. KiroCrew điều khiển kiro-cli, thành phần này cần sign-in một lần bằng tài khoản Kiro, và agent inference được tính phí vào Kiro plan, nên tính đến tháng 08 năm 2026 đây không phải là setup offline. Project này cũng chỉ mới tồn tại được vài tuần. Hãy giả định rằng đến một lúc nào đó bạn sẽ cần rollback, rồi cài đặt theo cách cho phép thực hiện việc đó. Nếu trước đây bạn chưa chạy agent trên server, chạy coding agent trên VPS trình bày các nguyên tắc nền tảng mà hướng dẫn này sử dụng. Nếu agent còn mới với bạn hơn server, trước hết hãy tìm hiểu agent loop, tool và memory của agent thực sự là gì; khi đó các lựa chọn dưới đây sẽ dễ hiểu như những quyết định kỹ thuật thay vì các câu lệnh khó hiểu.
KiroCrew cần gì và state nằm ở đâu
Cài native cần Python 3.10 trở lên (project khuyến nghị 3.12), Node.js 18 trở lên nếu bạn build dashboard từ source, và kiro-cli. Ở lần chạy đầu tiên, KiroCrew sẽ tự cài và đăng nhập cho bạn vào kiro-cli. Cài bằng container không cần bất kỳ thành phần nào trong số đó trên host. Bạn chỉ cần Docker. Đây là lý do chính để ưu tiên cách cài này.
State nằm trong ~/.kiro/crew. Biến môi trường KIROCREW_HOME cho phép chuyển state sang vị trí khác. Bên trong có:
config.json: cấu hình gateway và credential của các kênh chat..env: secrets.workspace/memory/: tùy chọn, ghi chú project và lịch sử chat.memory.dbvàmemory_index.db: semantic index và full-text index.models/: embedding model, được download ở lần chạy đầu tiên.gateway.logvàsecurity_events.jsonl: runtime log và security event log.
Thư mục đó chính là bản cài đặt. Copy thư mục này sang một VPS mới là bạn đã chuyển toàn bộ agent, vì vậy phần backup bên dưới quan trọng hơn phần cài đặt.
Hãy dự trù disk thay vì RAM. Gateway là một tiến trình Python; thành phần thực sự tạo tải cho máy là những gì agent chạy, chẳng hạn một build hoặc test suite. Thư mục state tăng theo lịch sử chat, còn embedding model được tải ở lần khởi động đầu tiên. Vì vậy, sau vài tuần hãy dùng du -sh ~/.kiro/crew để đo trên chính máy của bạn, thay vì tin vào bất kỳ số liệu nào được công bố trong tháng đầu của một project. So sánh với runtime cấp cho mỗi worker một container riêng và một browser riêng. Khi đó, tự host các AI coworker của OpenBot sẽ là bài toán về RAM trước khi là bài toán về disk.
Bạn nên dùng cách cài đặt nào trong ba cách
Dự án cung cấp ba cách cài đặt. Trình cài đặt một dòng tải một wheel và thêm kirocrew vào PATH của bạn:
curl -fsSL https://download.crew.kiro.dev/cli.sh | shTrình cài đặt nhận một flag channel và một flag version:
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.3Container image được phát hành tại ghcr.io/kirodotdev/kirocrew, dành cho linux/amd64 và linux/arm64 trong mọi tag. Cách build từ source cần git clone và make build, dành cho người thay đổi code, không dành cho người chỉ chạy phần mềm.
Hãy dùng container. Cài đặt native đặt các package Python, Node và kiro-cli trên cùng host đang chạy các service khác của bạn. Vì vậy, nếu upgrade gặp lỗi, bạn phải tự xử lý lại từng phần. Container giữ runtime trong một image và state trong một volume. Khi cần rollback, bạn chỉ cần đổi tag rồi restart.
Gắn image vào release tag, không dùng stable
Ví dụ của chính dự án sử dụng tag stable:
docker run -d --name kirocrew \
-p 127.0.0.1:5476:5476 \
-v kirocrew-home:/home/kirocrew \
ghcr.io/kirodotdev/kirocrew:stablestable là một moving tag. Nó trỏ đến bất kỳ stable release mới nhất nào tại thời điểm đó. Vì vậy, lần pull tiếp theo có thể thay đổi version bạn đang chạy mà bạn không chủ động chọn. Tag này cũng không cho biết đó là version nào. Version tag là bất biến, vì vậy hãy pin vào một version cụ thể. Release mới nhất tính đến ngày 6 August 2026 là 0.1.3, được phát hành vào ngày 5 August 2026. Ngoài ra còn có tag nightly. Với một project còn mới như vậy, tag này có nghĩa là code đã thay đổi vào sáng nay.
Ghi /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:Khởi động container, sau đó kiểm tra health endpoint mà image cũng dùng cho HEALTHCHECK của chính nó:
cd /opt/kirocrew
docker compose up -d
docker compose ps
curl -s http://127.0.0.1:5476/api/healthdocker compose ps phải báo container ở trạng thái healthy trong khoảng một phút. /api/health trả về kết quả mà không cần token. /api/live và /api/ready cũng vậy, nên có thể dùng chúng làm probe. Nếu trạng thái vẫn là starting, hãy đọc docker logs kirocrew trước khi thay đổi bất kỳ thứ gì. Lần chạy đầu tiên sẽ tải embedding model. Vì vậy, kết nối chậm có thể khiến lần khởi động đầu tiên mất nhiều thời gian.
Giữ gateway chạy bằng systemd
restart: unless-stopped sẽ khởi động lại container sau khi bị crash và sau khi reboot, miễn là Docker tự khởi động cùng hệ thống. Unit file làm rõ dependency này và cung cấp một lệnh để dừng toàn bộ stack trước khi backup. Khởi động Docker Compose stack khi boot trình bày mẫu triển khai chung. Với KiroCrew, cấu hình có dạng như sau trong /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 phải hiển thị active (exited). Đây là kết quả bình thường của unit này. Việc dùng Type=oneshot cùng với RemainAfterExit=yes là đúng trong trường hợp này vì docker compose up -d trả về ngay sau khi container được khởi động: systemd theo dõi trạng thái stack đã chạy, không theo dõi một tiến trình foreground. Nếu thay bằng Type=simple, systemd sẽ thấy lệnh thoát ngay, đánh dấu service đã dừng, rồi hoặc bỏ cuộc hoặc restart liên tục tùy theo thiết lập Restart=. Với bản cài native, project cung cấp thành phần tương đương là kirocrew service install. Thành phần này ghi /etc/systemd/system/kirocrew.service và chạy gateway bằng user của bạn. Không chạy đồng thời cả hai unit. Nội dung mở rộng về chủ đề này có trong service và timer của systemd trên VPS. Unit không khởi động lại được sẽ không phát tín hiệu nếu bạn không cấu hình, vì vậy hãy thêm handler OnFailure= để đẩy cảnh báo đến ntfy server của bạn. Khi đó, bạn sẽ biết gateway đã dừng qua điện thoại thay vì phát hiện qua một scheduled job chưa từng chạy.
Lần chạy đầu tiên: đăng nhập và lấy dashboard token
Container đã khởi động gateway, nhưng agent runtime vẫn chưa đăng nhập. Hãy đăng nhập bên trong container:
docker exec -it kirocrew kiro-cli loginLệnh này in ra device code và một URL để bạn mở bằng trình duyệt của mình. Sau đó tạo dashboard token:
docker exec kirocrew kirocrew token --ttl 2hURL của dashboard là http://localhost:5476/?token=<the token>. Token sẽ hết hạn: session mặc định kéo dài một giờ và thời hạn tối đa được tài liệu công bố là hai mươi giờ. Nếu dashboard tải trang trắng hoặc ngay lập tức đưa bạn quay lại màn hình đăng nhập, nguyên nhân thường là token đã hết hạn; hãy tạo token khác. Không bao giờ dán token vào ticket hoặc tin nhắn chat, vì bất kỳ ai sở hữu token đều có quyền kiểm soát agent của bạn.
Truy cập dashboard qua SSH và không public port 5476
Xem lại bind address trong ví dụ của project: -p 127.0.0.1:5476:5476. Bên trong container, gateway lắng nghe trên 0.0.0.0 vì nó phải có thể nhận kết nối thông qua port mapping, nhưng mapping chỉ public ra loopback trên host. Xóa prefix 127.0.0.1: thì gateway sẽ nằm trên Internet công cộng và bất kỳ ai quét port đó cũng có thể truy cập. Rule của firewall cũng không bảo vệ được bạn: Docker public port bằng cách ghi các rule DNAT được xử lý trước lớp filtering của ufw, nên ufw deny 5476 không có tác dụng với port đã được publish. Docker bypass ufw khi publish port giải thích cơ chế này.
Forward port qua SSH từ laptop:
ssh -N -L 5476:127.0.0.1:5476 you@your-server.example.comGiữ kết nối đó đang chạy rồi mở http://localhost:5476/?token=<the token> trên máy local. Để tự động forward trong mỗi lần kết nối, thêm cấu hình vào ~/.ssh/config:
Host your-server.example.com
LocalForward 5476 127.0.0.1:5476Nếu port 5476 đã được sử dụng trên laptop, chỉ đổi số bên trái: ssh -N -L 45476:127.0.0.1:5476 you@your-server.example.com, rồi mở http://localhost:45476/?token=.... Bạn sẽ bắt đầu xếp chồng các forward như vậy ngay khi agent thứ hai dùng chung server, vì tự host open-kritt để quét bảo mật sẽ tạo thêm một dashboard chỉ bind vào loopback trên cùng server, tại port 5173.
Có một hành vi đã được ghi nhận cần lưu ý khi chạy qua tunnel: gateway xem các request được forward là request từ xa, nên các endpoint config-write và secret-reveal trong dashboard sẽ từ chối chúng. Một thay đổi setting không lưu được qua SSH là hành vi này, không phải bug. Hãy sửa config trực tiếp trên 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 kirocrewĐể truy cập bằng điện thoại, dự án hướng đến tailscale serve của Tailscale. Cách này giữ dashboard bên trong tailnet của bạn thay vì đưa lên một hostname public. Hãy ưu tiên cách này thay cho reverse proxy public. Token nằm trong URL, và URL đó sẽ được ghi vào mọi access log trên đường đi của request. Quy tắc này phụ thuộc vào dịch vụ phía sau cổng, không phải bản thân cổng: những thứ như Halcyon, công cụ dựng lại thư viện Jellyfin thành một video store thập niên 90 có thể duyệt được được tạo ra để người khác mở và phù hợp làm reverse proxy. Ngược lại, gateway có thể chạy command trên server của bạn thì không phù hợp.
Trao cho agent phạm vi ảnh hưởng nhỏ nhất có thể
Container kiểm tra khả năng hỗ trợ sandbox ở lần khởi động đầu tiên. Kết quả này quyết định agent có được phép thực thi hay không. Nếu có namespace isolation, các subprocess của agent sẽ chạy trong môi trường cô lập. Nếu không có và KIROCREW_ALLOW_UNSANDBOXED=1 chưa được thiết lập, hệ thống sẽ từ chối thực thi thay vì chạy không được cô lập. Vì vậy, gateway trông vẫn khỏe nhưng mọi task đều bị treo thường là do nguyên nhân này. Quyết định này được ghi trong docker logs kirocrew từ lần chạy đầu tiên. Project cũng cung cấp profile seccomp (secure computing mode) để bạn áp dụng:
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.jsonNếu bạn thiết lập KIROCREW_ALLOW_UNSANDBOXED=1, hãy hiểu rõ điều gì đã thay đổi: container giờ là ranh giới duy nhất giữa agent và server của bạn. Cảnh báo của project đáng được nhắc lại đầy đủ. Không mount các path trên host mà bạn sẽ không giao trực tiếp cho agent. Trên thực tế, điều này loại trừ Docker socket, mọi bind mount của / và mọi thư mục chứa dữ liệu của service khác.
Phần còn lại là khung bảo vệ áp dụng cho mọi agent được phép chạy command. Giới hạn credential của agent vào đúng một repository hoặc một bucket mà nó cần. Không bao giờ dùng personal token có quyền trên toàn bộ account. Chạy agent bằng một user riêng, với home chỉ chứa các file cần thiết. Đây là mục đích của user có quyền tối thiểu trên VPS. Khi agent ghi code rồi chạy chính code đó, hãy cấp cho nó một máy mà nó được phép làm hỏng: VM dùng một lần cho coding agent tạo ra ranh giới mạnh hơn bất kỳ flag nào trong compose file này, vì bạn chỉ cần xóa VM thay vì dọn dẹp. Cùng cách suy luận đó áp dụng cho chạy OpenClaw an toàn trên VPS và tự host agent Hermes trên VPS. Tool cũng góp phần tạo ra phạm vi ảnh hưởng: khi cấp cho agent web search, mọi trang nó tải về đều trở thành input không đáng tin cậy. Vì vậy, trỏ agent đến instance SearXNG của riêng bạn là một quyết định về prompt injection, không chỉ là quyết định cấu hình kết nối. Tác vụ được lên lịch cũng có thể tiêu tốn tiền trong lúc bạn ngủ, vì chi phí inference được tính vào plan Kiro của bạn. Do đó, hãy thiết lập các giới hạn được mô tả trong kiểm soát chi phí của AI agent trên VPS trước khi thêm job chạy hằng đêm.
Sao lưu state volume trước mỗi lần nâng cấp
Trước tiên, hãy tìm đúng tên volume. Compose thêm tên project vào tên các named volume. Tên project mặc định là tên thư mục. Vì vậy, volume khai báo là kirocrew-home trong /opt/kirocrew/compose.yaml sẽ được tạo thành kirocrew_kirocrew-home:
docker volume lsDừng gateway trước khi sao chép. memory.db và memory_index.db là các database SQLite. Sao chép database trong lúc đang được ghi có thể lấy phải một transaction chưa ghi xong, khiến file bị lỗi sau khi restore. Hướng dẫn migration của project cũng nêu đúng điều này: chỉ di chuyển memory khi các gateway đã dừng. Quy tắc dừng trước này không chỉ áp dụng cho KiroCrew. Nếu một photo server dùng chung máy, bài so sánh PhotoPrism và Immich có các lệnh backup chính xác mà từng ứng dụng cần.
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 kirocrewChuyển archive ra khỏi máy chủ. Restore dùng cùng lệnh đó, với container đã dừng và tar xzf thay cho 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 kirocrewChuyển sang host mới là một công việc khác với restore tại chỗ, và project có hướng dẫn cụ thể cho việc này. Lịch sử chat và ghi chú project trong workspace/memory/ sẽ được chuyển sang, cùng với 2 file database và config.json. Các file PID, security event log và .env gắn với host cũ, nên không chuyển chúng sang. Hãy nhập lại các secret trên máy chủ mới.
Cách rollback sau một lần upgrade lỗi
Upgrade mất ít thời gian và chỉ an toàn vì bạn đã pin version. Hãy backup trước, sau đó đổi tag:
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 sẽ pull image nếu image chưa có trên máy, nên sửa tag là toàn bộ quá trình upgrade. Rollback cũng thực hiện theo trình tự đó với số version cũ. Bạn sẽ nhận đúng image đã dùng trước đó vì các version tag là bất biến.
Binary rollback mà không gặp vấn đề. Phần state mới có thể phát sinh lỗi. Gateway mới hơn có thể ghi lại config.json hoặc migrate các memory database sang định dạng mà gateway cũ không đọc được. Tính đến tháng 8 năm 2026, chưa có downgrade path nào được dokument hóa. Vì vậy, nếu image cũ khởi động rồi hoạt động bất thường, đừng debug. Hãy stop nó, restore backup đã tạo trước khi upgrade, rồi khởi động lại. Đó là toàn bộ lý do phải backup trước. Đây cũng là lý do thói quen upgrade trước rồi backup sau không phù hợp với một project còn mới như vậy.
Những gì chưa được chứng minh ở đây
Hãy đánh giá đúng tuổi đời của phần mềm này. Phiên bản 0.1.3 mới được phát hành vài ngày tại thời điểm viết bài. Ghi chú phát hành của phiên bản này chỉ là các liên kết changelog tự động, không phải ghi chú migration. Phần mềm cũng chưa có lịch sử nâng cấp thực tế. Không có nội dung nào trong hướng dẫn này là kết quả đã được kiểm chứng trong thời gian dài. Vì vậy, hãy tự đo mức tăng bộ nhớ, kích thước database và độ tin cậy của scheduler trên máy chủ của bạn, thay vì mặc định rằng chúng sẽ ổn định.
Có 2 hành vi bạn nên tự kiểm tra trước khi phụ thuộc vào chúng. Thứ nhất là việc downgrade có đọc được state do phiên bản mới hơn ghi hay không. Hãy thử trên bản sao của volume khi việc thử nghiệm chưa gây ảnh hưởng, không thực hiện trong lúc hệ thống đang outage. Thứ hai là gateway xử lý thế nào khi phiên đăng nhập Kiro hết hạn đúng lúc scheduled job đến hạn chạy. Đây là những lỗi biên thường được một project còn mới âm thầm sửa giữa các lần release. Cả 2 vấn đề đều dễ kiểm tra ngay từ bây giờ.
FAQ
Vì sao dashboard KiroCrew không mở được bằng public IP của server?
Vì ví dụ được công bố bind port vào loopback. -p 127.0.0.1:5476:5476 chỉ map port của container vào địa chỉ loopback của host, và đây là chủ ý thiết kế. Hãy truy cập bằng cách forward port qua SSH với ssh -N -L 5476:127.0.0.1:5476 you@your-server, sau đó mở http://localhost:5476/?token=<token> trên laptop của bạn. Xóa tiền tố 127.0.0.1: để cho phép truy cập từ bên ngoài sẽ đưa gateway lên public Internet. Một rule của firewall cũng không ngăn được việc này vì các rule DNAT cho published port của Docker được áp dụng trước khi ufw filter lưu lượng.
KiroCrew lưu dữ liệu ở đâu và tôi nên backup những gì?
Toàn bộ dữ liệu nằm dưới ~/.kiro/crew, tương ứng với /home/kirocrew/.kiro/crew bên trong container image, và KIROCREW_HOME dùng để di chuyển vị trí này. Hãy backup toàn bộ thư mục hoặc toàn bộ Docker volume khi gateway đã dừng. memory.db và memory_index.db là các database SQLite, nên bản sao được tạo trong lúc gateway đang ghi dữ liệu có thể không nhất quán. Khi chuyển sang host mới, workspace/memory/, 2 database file và config.json sẽ được chuyển theo, còn PID file, security event log và .env thuộc về host cũ.
Tôi nên dùng tag stable hay version tag?
Hãy dùng version tag. stable thay đổi mỗi khi có release mới, nên version đang chạy có thể tự thay đổi sau lần pull tiếp theo, và bản thân tag không cho biết chính xác image nào đang chạy. Các version tag như 0.1.3 là immutable. Đây chính là điều giúp rollback hoạt động: khôi phục số version cũ và nhận lại image giống hệt. Tính đến ngày 6 August 2026, release mới nhất là 0.1.3.
Vì sao agent của tôi từ chối chạy mọi command?
Container sẽ kiểm tra khả năng hỗ trợ sandbox ở lần khởi động đầu tiên. Nếu không thể cô lập các subprocess của agent và KIROCREW_ALLOW_UNSANDBOXED=1 chưa được set, container sẽ từ chối thực thi thay vì chạy chúng ở chế độ không được cô lập. Vì vậy gateway vẫn có vẻ hoạt động bình thường nhưng mọi task đều bị treo. docker logs kirocrew hiển thị quyết định về sandbox từ lần chạy đầu tiên. Việc set biến này khiến container trở thành ranh giới duy nhất giữa agent và host. Vì vậy, nếu set biến này, bạn không nên mount bất kỳ thứ gì mà bạn không sẵn sàng đưa trực tiếp cho agent.
Tôi có cần Kiro account để self-host KiroCrew không?
Có, tính đến August 2026. KiroCrew là phần mềm miễn phí theo giấy phép Apache 2.0, nhưng nó điều khiển kiro-cli. Thành phần này yêu cầu sign-in một lần và việc inference của agent được tính phí vào Kiro plan. Trong container, chạy docker exec -it kirocrew kiro-cli login rồi approve device code trong browser. Cho đến khi hoàn tất sign-in, gateway vẫn khởi động và dashboard vẫn load, nhưng agent không có model để kết nối.