Cài DeepSeek Harness trên VPS riêng với SSH tunnel
Cài DeepSeek Harness trên Linux VPS, pin version npm, hiểu quyền của plugin và mở web UI port 3080 qua SSH tunnel mà không public port này.
DeepSeek Harness là gì
DeepSeek Harness (dsh) là một agent runtime Node.js có thể chạy trên VPS (virtual private server). Cách chạy an toàn là bind nó vào 127.0.0.1, sau đó truy cập bằng trình duyệt thông qua một SSH (secure shell) tunnel. Nó cung cấp web UI (user interface) trên port 3080 thay vì chạy trong terminal. Web server này không tự yêu cầu password. Vì vậy, nếu public port 3080, bất kỳ ai tìm thấy port này đều có thể truy cập một agent có quyền đọc file và chạy command bằng user Linux của bạn.
DeepSeek phát hành nó vào 13 August 2026 theo MIT licence, dưới dạng npm package @deepseek-ai/dsh. Dự án tự mô tả là bản developer preview và nêu rõ rằng các thay đổi làm hỏng compatibility là điều có thể xảy ra. Mọi version number bên dưới đều là snapshot của August 2026. Hãy kiểm tra repository trước khi copy bất kỳ nội dung nào vào một máy chủ quan trọng.
Một ý tưởng xuyên suốt toàn bộ thiết kế: mọi thứ đều là plugin. Model adapter, tool registry, session log, sandbox, scheduler và chính agent loop đều là các plugin được nạp vào một context dùng chung, và bất kỳ thành phần nào cũng có thể được thay thế. Không có một core đặc quyền để các plugin chỉ bổ sung chức năng. Đây là lý do harness này đáng để thử, đồng thời cũng là nơi tồn tại rủi ro thực sự duy nhất. Trade-off này có phù hợp hay không còn tùy vào tiêu chí đối chiếu, và so sánh với Claude Code và Omnigent đặt thiết kế mọi thứ là plugin bên cạnh 2 cách tiếp cận khác về mức độ phụ thuộc vào model, license và lượng tài nguyên VPS mà mỗi công cụ yêu cầu.
Harness không phải là model
Harness chạy vòng lặp agent. Phần suy luận diễn ra trong một model ở nơi khác, vì vậy sẽ không có gì hoạt động cho đến khi bạn cung cấp API (application programming interface) key hoặc địa chỉ của một model endpoint do bạn tự host. Mọi nội dung trong bài này là cấu hình của harness, không phải hành vi của model. Bạn nên phân biệt rõ ranh giới giữa hai phần này trước khi mất cả buổi chiều để xác định sự cố bắt nguồn từ phía nào.
Bạn cấu hình trong UI tại Settings, sau đó vào Models. Catalog có sẵn các card cho những nhà cung cấp API lớn (DeepSeek, OpenAI, Anthropic), nơi bạn chỉ cần dán key. Tùy chọn đáng chú ý là "Add a custom provider": tùy chọn này yêu cầu provider ID, display name, base URL, API protocol và credential. Nó sử dụng OpenAI-compatible protocol, nên mọi gateway hoặc local server triển khai protocol này đều hoạt động. Custom provider cũng có thể truy vấn endpoint OpenAI-compatible GET /models để tự điền danh sách model.
Đó là cách trỏ harness đến một model trên cùng VPS. Ollama cung cấp OpenAI-compatible API tại http://127.0.0.1:11434/v1/. API key field phải được điền bằng bất kỳ chuỗi nào, theo quy ước là ollama, vì field này bắt buộc nhưng sau đó bị bỏ qua. Model đủ nhỏ để chạy trên VPS có điều khiển agent đủ tốt hay không là câu hỏi khó hơn. Sự khác biệt giữa Ollama và vLLM khi làm local model server quyết định câu trả lời sẽ tiêu tốn bao nhiêu RAM.
Các key nhập trong UI chỉ có thể ghi, không thể đọc lại. Harness lưu chúng trong $DSH_HOME/.credentials.yaml và chỉ giữ một credential reference trong settings.yaml. $DSH_HOME mặc định là ~/.dsh. Hãy coi file đó như file chứa password, vì đúng là như vậy: bất kỳ ai đọc được file đều có thể sử dụng ngân sách API của bạn. Nếu muốn sửa trực tiếp các file đó thay vì thao tác qua Settings, bài hướng dẫn về các file cấu hình, key và model endpoint của dsh giải thích chức năng của từng key và dữ liệu nào rời khỏi máy của bạn trong mỗi chế độ.
Những gì cần chuẩn bị trước khi cài đặt
- một VPS chạy Ubuntu 24.04 hoặc một Linux hiện hành khác, có quyền truy cập SSH
- Node.js 22.19 trở lên trong nhánh 22.x, hoặc Node.js 24 trở lên; đây là các phiên bản mà project dùng để build và test
- một tài khoản người dùng thông thường, không phải
root, vì agent chạy shell command với quyền của người khởi chạy process pnpmtrong PATH nếu bạn định cài plugin, vì plugin command gọi nó qua shell- đóng port 3080 trên firewall của bạn và firewall mạng riêng do nhà cung cấp quản lý
Gói nodejs của Ubuntu cũ hơn mức harness yêu cầu. Vì vậy, hãy cài Node từ NodeSource hoặc nvm thay vì dùng apt install nodejs. Nếu VPS mới được tạo, hardening SSH trước mọi việc khác là việc đáng dành mười phút, vì tunnel mà bạn sắp phụ thuộc vào chỉ an toàn ở mức SSH server phía sau nó.
Cài DeepSeek Harness trên VPS và cố định một phiên bản
node --version
npx @deepseek-ai/dsh@0.1.0-rc.6 webnpx tải package xuống và chạy binary dsh của nó. web là alias của --profile web, lệnh này khởi động browser application, rồi process in ra địa chỉ mà nó đang lắng nghe. Giá trị mặc định là http://127.0.0.1:3080. Các giá trị này là quyết định ràng buộc, không chỉ là giá trị mặc định cho đẹp. Vì sao dsh in ra địa chỉ loopback giải thích harness sẽ và sẽ không phản hồi như thế nào trước khi bạn tìm nó từ laptop.
Hãy cố định version. npx @deepseek-ai/dsh web phân giải tag mà latest trỏ tới tại thời điểm bạn chạy lệnh, trong khi project đã phát hành nhiều release candidate và cho biết các breaking change sắp tới. 0.1.0-rc.6 là giá trị mà latest trỏ tới vào ngày 13 August 2026. Cố định version giúp VPS bạn cấu hình hôm nay hoạt động giống hệt vào tháng sau. Khi đó, upgrade là quyết định do bạn đưa ra thay vì sự cố bạn tình cờ phát hiện. Nếu command đã cố định version nhưng vẫn khởi động sai build hoặc hoàn toàn không cài được, các lỗi cài đặt và version dsh thường gặp hướng dẫn xóa npx cache và kiểm tra npm mà Node của bạn tích hợp.
Để dùng hằng ngày, hãy cài một lần thay vì phân giải lại ở mỗi lần khởi động.
npm install -g @deepseek-ai/dsh@0.1.0-rc.6
dsh --profile web --helpDòng thứ hai đáng để chạy, vì launcher và web app có các bộ flag riêng. dsh --help hiển thị các option riêng của launcher. dsh --profile web --help hiển thị các flag mà web application chấp nhận. Đây là nơi có --port, --host và --trusted-host có thể lặp lại.
Bây giờ hãy xác nhận process đang lắng nghe trên địa chỉ nào.
ss -tlnp | grep 3080Cột địa chỉ cục bộ phải hiển thị 127.0.0.1:3080. Nếu hiển thị 0.0.0.0:3080, UI có thể truy cập từ Internet. Hãy dừng process trước khi làm bất kỳ việc gì khác.
Vì sao tuyệt đối không được public port 3080
Web server này không có lớp xác thực. Cấu hình của nó expose một listen host và một listen port, và đó là toàn bộ bề mặt truy cập. Kiểm soát truy cập cho các deployment không dùng loopback là một setting trusted host riêng, không phải màn hình đăng nhập.
Bây giờ hãy xét những gì nằm phía sau port đó. Agent chỉnh sửa các file trong workspace và chạy shell command, còn credential của provider được lưu trên disk ngay bên cạnh nó. Vì vậy, port 3080 mở ra thực chất là một remote shell có giao diện chat, chạy với user đã khởi động agent và đi kèm API key của bạn. Kẻ tấn công không cần exploit. Chúng chỉ cần biết port number, và các scanner sẽ tìm ra port này trong vòng vài giờ sau khi host online.
CLI (command line interface) cũng xác nhận điều đó. Kể từ 0.1.0-rc.6, CLI cố ý không hỗ trợ --host 0.0.0.0 và sẽ thoát với lỗi usage thay vì khởi động. Việc từ chối này là một tính năng, vì vậy đừng tìm patch để gỡ bỏ nó.
Có 2 cách deployment khác vẫn hợp lý khi tunnel không phù hợp. Đưa máy vào một private overlay network để máy chỉ có một địa chỉ mà các thiết bị của bạn có thể route tới; một Headscale control server tự host cung cấp mô hình này. Hoặc đặt một reverse proxy phía trước để xác thực request trước khi request đến port 3080, chẳng hạn một Authentik single sign-on server thực hiện forward auth. Reverse proxy không có auth ở phía trước không phải là một security control. Đó chỉ là một URL dài hơn.
Truy cập giao diện web qua SSH tunnel
Chạy lệnh này trên laptop của bạn, không chạy trên server.
ssh -N -L 3080:127.0.0.1:3080 you@your-server-L mở cổng 3080 trên laptop và chuyển tiếp mọi kết nối đến cổng đó qua phiên SSH đã mã hóa. Phần 127.0.0.1:3080 được phân giải trên server, nên kết nối đến harness từ loopback, giống hệt như khi bạn đang ngồi trực tiếp trên máy. -N cho biết không khởi động remote shell, vì bạn chỉ cần tunnel và không cần gì khác.
Sau đó, mở http://127.0.0.1:3080 bằng trình duyệt cục bộ. Nếu cổng 3080 đã được sử dụng trên laptop, hãy đổi số ở bên trái: ssh -N -L 3180:127.0.0.1:3080 you@your-server, rồi truy cập http://127.0.0.1:3180. Số bên trái là cổng cục bộ, còn số bên phải thuộc về server, nên chỉ thay đổi số bên trái.
Lưu vào ~/.ssh/config để không phải nhập lại.
Host dsh
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
LocalForward 3080 127.0.0.1:3080Sau đó, ssh -N dsh sẽ khởi động tunnel. Nếu trình duyệt báo kết nối bị từ chối, thường là tunnel đã hoạt động nhưng không có tiến trình nào lắng nghe ở đầu bên kia, vì SSH vẫn chuyển tiếp cổng dù harness có đang chạy hay không. Kiểm tra server bằng lệnh ss ở trên.
Duy trì harness sau khi đăng xuất
Một lệnh npx sẽ dừng cùng shell của bạn. systemd user service vẫn tiếp tục chạy và khởi động lại harness sau khi tiến trình bị crash hoặc máy reboot. Unit ở đây được cố ý viết tối giản. Nếu bạn muốn harness chạy bằng một account riêng đã được giới hạn quyền, pin version ngay trong unit và có log để tìm kiếm thực tế, hướng dẫn thiết lập systemd headless cho dsh trình bày đầy đủ.
loginctl enable-linger $USER
mkdir -p ~/.config/systemd/user
command -v dshenable-linger quan trọng vì user service thường dừng khi session cuối cùng của bạn kết thúc. Nếu thiếu tùy chọn này, harness sẽ dừng ngay khi bạn đóng tunnel. Lấy đường dẫn tuyệt đối do command -v dsh in ra và đặt đường dẫn đó vào unit, vì systemd không tìm kiếm PATH do login shell của bạn tạo.
[Unit]
Description=DeepSeek Harness web UI
After=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/projects/site
ExecStart=/usr/local/bin/dsh web
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.targetWorkingDirectory không phải tùy chọn cho có. Process dsh dùng thư mục mà nó được gọi từ đó làm vị trí mặc định trên filesystem. Vì vậy, nếu service khởi động ở sai thư mục, agent sẽ dùng sai workspace mặc định. Bạn vẫn có thể chọn workspace trong UI.
systemctl --user daemon-reload
systemctl --user enable --now dsh
systemctl --user status dshMột unit không khởi động gần như luôn do đường dẫn ExecStart sai hoặc do binary không chấp nhận version của Node. journalctl --user -u dsh -n 50 cho biết trường hợp nào xảy ra. Cùng mẫu này cũng dùng được cho việc duy trì bất kỳ coding agent nào chạy trên VPS, và các dạng lỗi cũng giống nhau.
Plugin được phép làm gì
Plugin là một module cung cấp service, typed event và hiệu ứng có thể hoàn tác cho một context dùng chung. Các extension point là phần cần đọc kỹ:
- đăng ký model provider trên
ctx.llm - thêm tool dành cho model trên
ctx.tools - cung cấp shell backend phía sau
ctx.shell - cung cấp quyền truy cập filesystem hoặc policy phía sau
ctx.fs - đăng ký lệnh dành cho người dùng trên
ctx.commands - chạy tác vụ nền thông qua
ctx.jobs - bọc các process được tạo bằng backend
ctx.sandbox - chặn request và tool call thông qua các event
agent/*vàtools/* - mở rộng trạng thái session bền vững
- điều khiển UI thông qua
ctx.agents
Hãy đọc danh sách này theo cách một kẻ tấn công sẽ đọc. Plugin có thể cung cấp filesystem layer và shell layer, đồng thời đứng giữa mọi tool call do model thực hiện. Không có hộp thoại cấp quyền nào ngăn plugin truy cập các điểm này, vì plugin là mã Node thông thường được load vào cùng process với mọi thành phần khác. Cài đặt plugin đồng nghĩa với chạy code của người lạ bằng quyền của agent, mà quyền của agent chính là quyền của Unix user của bạn.
Đây cũng là quyết định về mức độ tin cậy bạn đưa ra khi gắn MCP server vào agent trên VPS, trong đó MCP là model context protocol. Đây cũng là lý do chạy coding agent an toàn trên VPS phải bắt đầu từ account mà agent sử dụng, thay vì bắt đầu từ model, và là lý do các cuộc tấn công chuỗi cung ứng npm gây ảnh hưởng nghiêm trọng trên server: bước install chính là lúc server bị breach, và không có gì hỏi xin phép bạn.
Plugin đến từ đâu
Plugin nằm trong các profile. Profile là một composition có tên được lưu dưới $DSH_HOME, mặc định là ~/.dsh. Thư mục của từng profile chứa các plugin out-of-tree mà profile đó cài đặt. CLI quản lý chúng bằng cách chuyển thẳng các đối số của bạn đến pnpm, với thư mục của profile làm working directory.
dsh plugin --profile web add github:deepseek-harness/turtle-ui
dsh plugin --profile web remove turtle-uiVì các đối số đến pnpm không bị thay đổi, add, remove, update và why hoạt động giống như trong mọi dự án pnpm. Plugin có thể là một npm package hoặc một GitHub reference. pnpm phải có sẵn trong PATH trước. Trên Node 22 trở lên, corepack enable pnpm sẽ đưa nó vào PATH.
Cơ chế discovery dùng một GitHub topic. Tác giả plugin thêm topic dsh-plugin vào repository của họ. Bạn tìm plugin hiện có bằng cách duyệt topic đó. Topic là nhãn do tác giả tự gắn cho repository của mình. Không ai review hoặc ký xác nhận topic này. Trang topic xếp hạng theo số star, chỉ phản ánh mức độ phổ biến chứ không phản ánh độ an toàn.
Bốn thói quen giúp việc này dễ kiểm soát. Đọc source trước khi cài, vì hầu hết plugin đủ nhỏ để đọc trong mười phút. Pin đúng version hoặc commit thay vì theo dõi một branch. Chạy harness dưới một user không sở hữu tài nguyên nào khác, trên một VPS mà bạn sẵn sàng rebuild. Cấp cho agent một API key riêng với spending limit riêng, tách khỏi key mà các production service của bạn sử dụng. Khi đọc một plugin và muốn biết file nào chứa rủi ro, phần hướng dẫn kiểm tra plugin dsh sẽ đi qua manifest, entry point và các extension point mà plugin đăng ký.
Nếu bạn muốn so sánh các thiết kế trước khi chọn một thiết kế, Omnigent multi-agent harness giải quyết cùng một vấn đề với cấu trúc khác, và các đánh đổi sẽ trở nên rõ ràng khi bắt đầu dùng plugin. Nếu cuối cùng bạn giữ lại 2 hoặc 3 harness trên cùng một máy thay vì chọn một giải pháp, đặt mọi harness phía sau một API tự host sẽ giúp bạn không phải tạo một tunnel cho từng cổng, nhưng phải vận hành thêm một service. Service này phải bind vào loopback và được đặt mật khẩu thực ngay từ ngày đầu.
Điều gì bị hỏng trước
Node quá cũ. Project yêu cầu Node 22.19 và các bản mới hơn trong dòng 22.x, hoặc Node 24 trở lên, và CI của project cũng kiểm thử các phiên bản này. Runtime cũ hơn sẽ fail khi khởi động vì code sử dụng cú pháp và API không có trong phiên bản đó. Chạy node --version trước mọi thao tác khác.
Cổng 3080 đã được sử dụng. Có thể một harness thứ hai, một process cũ hoặc một ứng dụng khác cũng sử dụng 3080. Tìm process đó bằng ss -tlnp | grep 3080, sau đó stop nó hoặc khởi động harness ở cổng khác bằng dsh web --port 3180. --port thuộc về web app, nên phải đặt sau web.
Browser không thể kết nối qua tunnel. Xác nhận bạn đã truy cập 127.0.0.1, không phải địa chỉ public của server, vì port được forward chỉ tồn tại trên laptop của bạn. Sau đó xác nhận harness đang listen trên server, vì SSH vẫn thiết lập forward dù phía đích có process phản hồi hay không.
dsh plugin fail ngay lập tức. Command này là wrapper của pnpm, nên nếu thiếu binary pnpm, command sẽ dừng trước khi bắt đầu xử lý plugin.
Agent không nhìn thấy project của bạn. Workspace mặc định là thư mục nơi process được khởi động. Vì vậy, nếu WorkingDirectory của một unit là home directory, agent sẽ nhận home directory của bạn. Chọn workspace trong UI hoặc sửa unit rồi reload unit đó.
FAQ
Có an toàn khi expose web UI của DeepSeek Harness trên port 3080 không?
Không. Web server không có cơ chế đăng nhập riêng, còn agent phía sau có thể chỉnh sửa file và chạy shell command với quyền của user đã khởi động process. Provider API key của bạn cũng được lưu trên cùng disk. Hãy giữ listener trên 127.0.0.1 và truy cập qua SSH tunnel. Bạn cũng có thể dùng private overlay network hoặc reverse proxy xác thực mọi request trước khi request đến port này. Từ version 0.1.0-rc.6, CLI từ chối --host 0.0.0.0 và thoát với usage error. Điều này cho thấy tác giả đánh giá ý tưởng đó như thế nào.
Tôi có cần DeepSeek API key không, hay có thể dùng local model?
Cả hai đều dùng được, vì harness là runtime chứ không phải model. Trong Settings, rồi vào Models, bạn có thể dán key vào card của catalog provider. Hoặc chọn "Add a custom provider" và nhập base URL sử dụng protocol tương thích với OpenAI. Local Ollama server lắng nghe tại http://127.0.0.1:11434/v1/ và chấp nhận bất kỳ chuỗi nào trong trường API key. Các key được lưu tại $DSH_HOME/.credentials.yaml, mặc định là ~/.dsh/.credentials.yaml.
Việc cài plugin DeepSeek Harness thực sự cấp cho plugin những gì?
Plugin có các quyền của account đang chạy harness. Plugin là code Node được load vào cùng process. Các extension point bao gồm shell backend, filesystem layer, tool registry và các event bao quanh mọi tool call. Không có cơ chế sandbox nào tách plugin khỏi các điểm kết nối này, trừ khi chính plugin cung cấp sandbox. Hãy đọc source trước khi cài và chạy harness bằng một user không sở hữu dữ liệu nào quan trọng với bạn.
Tôi nên cài version nào, và nó có tiếp tục hoạt động không?
Hãy cài một version cụ thể, ví dụ npx @deepseek-ai/dsh@0.1.0-rc.6 web. Đó là version mà tag latest trỏ tới vào ngày 13 August 2026. Project tự mô tả là developer preview và cho biết các thay đổi phá vỡ compatibility là điều có thể xảy ra. Vì vậy, command không pin version có thể hoạt động khác nhau từ ngày này sang ngày khác. Hãy kiểm tra repository trước khi upgrade và chuẩn bị cho việc config key cũng như plugin interface thay đổi trong thời gian version vẫn bắt đầu bằng 0.