Cấu hình dsh: API key, model và endpoint
Biết dsh lưu config Linux ở đâu, cách nối DeepSeek API key hoặc endpoint Ollama local, và chính xác dữ liệu nào rời khỏi máy bạn ở mỗi chế độ.
Nơi dsh lưu cấu hình
dsh (DeepSeek Harness) lưu cấu hình trong một thư mục: $DSH_HOME, mặc định là ~/.dsh. Mọi thiết lập bạn đặt trong Web UI đều được ghi ở đó dưới dạng các file văn bản thuần túy. Sao chép thư mục này sang server khác thì máy mới sẽ hoạt động giống máy cũ.
Bốn đường dẫn chứa toàn bộ nội dung bạn sẽ thao tác.
~/.dsh/settings.yamlchứa các thiết lập được viết thủ công và ghi từ UI, bao gồm route đến provider và model.~/.dsh/.credentials.yamlchứa các secret. Các thiết lập chỉ lưu tham chiếu đến credential, còn giá trị key nằm trong một file duy nhất.~/.dsh/profiles/chứa các profile có tên, còn~/.dsh/storages/chứa các session đã lưu.~/.dsh/cordis.patch.ymllà lớp patch riêng của bạn. Lớp này được áp dụng lên configuration tích hợp sẵn cho mọi profile.
DeepSeek công bố harness dưới dạng bản developer preview được cấp phép MIT vào ngày 17 August 2026, và README nêu rõ sẽ có các thay đổi gây mất compatibility. Tên field và path trong hướng dẫn này khớp với tài liệu của repository tại thời điểm August 2026. Hãy đối chiếu chúng với tài liệu của version bạn đã cài trước khi sao chép config từ bất kỳ hướng dẫn nào, kể cả hướng dẫn này, vì bản preview có thể đổi tên giữa các release.
Mức tối thiểu thực tế để nhận output đầu tiên
dsh cần Node.js 22.19 trở lên trong nhánh 22, hoặc Node.js 24 trở lên. Node 23 nằm ngoài các phiên bản này. Hãy kiểm tra version trước, vì version không tương thích sẽ khiến ứng dụng fail ngay khi khởi động và lỗi hiển thị giống như package bị hỏng.
node -v
npx @deepseek-ai/dsh webnpx tải package từ npm registry và khởi động Web UI trên http://127.0.0.1:3080. Nó bind vào loopback address, nên cổng này không thể truy cập từ máy khác ngay cả khi firewall cho phép. Trên VPS, hãy forward cổng này qua SSH thay vì mở cổng 3080 ra Internet.
ssh -N -L 3080:127.0.0.1:3080 you@your-serverMở http://127.0.0.1:3080 trên laptop, sau đó vào Settings và Models. Card DeepSeek có một trường API key. Dán key lấy từ platform.deepseek.com rồi lưu lại. Model route có thể sử dụng ngay mà không cần restart, vì server đang chạy lưu credential và resolve reference trực tiếp. Truy cập Web UI của dsh trên server từ xa trình bày trường hợp dùng tunnel và reverse proxy, còn cài đặt DeepSeek Harness trên VPS trình bày phần chuẩn bị server mà hướng dẫn này giả định đã hoàn tất.
Sau khi lưu, hãy kiểm tra những gì app đã tạo.
ls -la ~/.dsh
stat -c '%a %n' ~/.dsh/.credentials.yamlBạn sẽ thấy settings.yaml, .credentials.yaml và profiles/. Nếu stat in ra mode khác 600, hãy chạy chmod 600 ~/.dsh/.credentials.yaml. File credentials cho phép group hoặc mọi user đọc sẽ làm lộ key của bạn cho mọi account khác trên máy.
Để chạy lần đầu mà không cần browser, chỉ cần một command.
npx @deepseek-ai/dsh --profile headless "summarise the files in this directory"Headless profile chạy một session duy nhất và in ra câu trả lời cuối cùng.
Biến môi trường hoặc file cấu hình
Có hai cách cung cấp key cho dsh và chúng không thể thay thế cho nhau.
Catalog provider (DeepSeek, Anthropic, OpenAI và các provider khác trong danh sách tích hợp sẵn) nhận key thông qua trang Models. Giá trị được lưu vào ~/.dsh/.credentials.yaml, còn settings của bạn chỉ giữ tham chiếu đến giá trị đó. Web UI không hiển thị lại key sau khi bạn lưu.
Custom provider có thể thay vào đó chỉ định một biến môi trường bằng apiKeyEnv. Đây là cấu trúc tài liệu sử dụng cho ~/.dsh/settings.yaml.
llm-pi-ai:
providers:
my-gateway:
apiKeyEnv: GATEWAY_API_KEY
api: openai-completions
baseURL: https://gateway.example/v1
models:
- id: legacy-chat
- id: vision-preview
input: [text, image]Trước tiên, thêm một provider qua Web UI, sau đó mở ~/.dsh/settings.yaml và sao chép cấu trúc mà ứng dụng đã ghi. Trong giai đoạn developer preview, phần nesting có khả năng thay đổi nhiều nhất. File mà ứng dụng vừa ghi luôn là phiên bản hiện tại.
apiKeyEnv được đọc từ môi trường của tiến trình dsh, không phải từ login shell của bạn. Key được export trong một phiên tương tác sẽ không hiển thị với systemd unit. Vì vậy, cùng một cấu hình hoạt động khi bạn tự nhập dsh web lại trả về MISSING_CREDENTIAL khi chạy dưới service. Hãy cấp cho unit một file riêng.
[Service]
EnvironmentFile=/etc/dsh/dsh.envĐặt file đó với mode 600 và owner là user chạy service.
Chọn model và ID không thể đổi tên
Mọi provider đã cấu hình đều xuất hiện trong model picker. Chọn một model cũng đặt model đó làm mặc định cho các session mới. Những session đã tồn tại vẫn giữ model được ghi trong session, nên việc chuyển model không thay đổi conversation cũ.
Provider ID là cố định. Request, session đã lưu, model mặc định và các tham chiếu credential đều trỏ đến ID này, nên không có nút đổi tên. Muốn thay đổi, bạn phải tạo provider mới rồi xóa provider cũ. Hãy chọn một tên có thể dùng lâu dài: local-ollama thay vì test2.
Model được xem là chỉ hỗ trợ text, trừ khi bạn khai báo khác. Thêm input: [text, image] vào mục model để khai báo hỗ trợ image, hoặc đặt defaultInput ở cấp route làm giá trị dự phòng cho những model không được catalog mô tả. Route chat-completions riêng của DeepSeek chỉ hỗ trợ text và không thể cấu hình khác, nên image đính kèm vào route này sẽ bị từ chối trước khi có dữ liệu nào được gửi đi.
Trỏ dsh đến endpoint cục bộ để code vẫn chạy trên máy
Ollama cung cấp API tương thích với OpenAI tại http://127.0.0.1:11434/v1. dsh có thể kết nối đến bất kỳ base URL tương thích với OpenAI nào thông qua custom provider, nên hai thành phần này kết nối trực tiếp với nhau. Trước tiên, hãy thiết lập model server: tự host LLM bằng Ollama trên VPS hướng dẫn cài đặt và pull model.
Xác nhận endpoint phản hồi trước khi cấu hình dsh.
ollama list
curl -s http://127.0.0.1:11434/v1/modelsollama list in chính xác tag của từng model bạn đã pull. Hãy copy chuỗi đó. curl trả về cùng các model dưới dạng JSON. Danh sách rỗng nghĩa là Ollama đang chạy nhưng chưa có model nào được pull. Connection refused nghĩa là Ollama chưa chạy hoặc không listening trên 11434.
Bây giờ thêm provider. Ollama yêu cầu trường API key nhưng bỏ qua giá trị của trường này, nên mọi chuỗi không rỗng đều được.
llm-pi-ai:
providers:
local-ollama:
apiKeyEnv: OLLAMA_API_KEY
api: openai-completions
baseURL: http://127.0.0.1:11434/v1
models:
- id: <the exact tag printed by ollama list>Export biến này trong môi trường mà tiến trình dsh có thể đọc được.
sudo install -d -m 700 /etc/dsh
printf 'OLLAMA_API_KEY=ollama\n' | sudo tee /etc/dsh/dsh.env
sudo chmod 600 /etc/dsh/dsh.envBa lỗi sau bao quát gần như mọi trường hợp cấu hình không thành công. MISSING_CREDENTIAL nghĩa là dsh không đọc được biến có tên do apiKeyEnv chỉ định, vì vậy hãy kiểm tra environment của tiến trình, không phải environment của terminal. UNKNOWN_MODEL nghĩa là id không khớp với model đã cấu hình, vì vậy hãy so sánh với ollama list từng ký tự một, bao gồm cả tag sau dấu hai chấm. Lỗi 401 khi lấy danh sách model xuất phát từ model discovery, chức năng này gọi GET /models trên base URL của bạn; các endpoint không cung cấp path đó cần được nhập model thủ công.
Một lỗi khác thường gặp là base URL. Không thêm /v1 vào base URL khiến request đi đến các path mà Ollama không cung cấp, nên request trả về lỗi 404 và model không chạy. Suffix này là một phần của OpenAI-compatible surface, không phải phần trang trí.
Nếu Ollama chạy trên máy khác, địa chỉ của máy đó sẽ trở thành base URL, và prompt của bạn sẽ đi qua network dưới dạng cleartext qua HTTP thường. Hãy giữ Ollama trên cùng host, hoặc đặt nó phía sau TLS (transport layer security) và authentication: bảo vệ endpoint Ollama đã public ra ngoài.
Những gì rời khỏi máy trong từng chế độ
Với DeepSeek key, mọi request đều đi đến API của DeepSeek. Request đó chứa prompt của bạn, nội dung các file mà agent đã đọc để trả lời, output của các command mà agent đã chạy và mọi kết quả tool mà agent chọn đưa vào. Source code của bạn nằm trong payload đó bất cứ khi nào agent mở một file. Đây là cách model được host hoạt động, và đó là lý do bạn cần cân nhắc nên khởi động agent trong thư mục nào.
Với một catalog provider khác hoặc gateway của công ty, payload tương tự sẽ đi đến vendor đó. Base URL cho biết chính xác đích đến.
Với local endpoint, request đến model đi tới 127.0.0.1:11434 và nằm lại trên máy. Không phần nào trong code của bạn đến model vendor. Tuy vậy, vẫn có 3 loại dữ liệu đi qua network. npx tải package từ npm registry. Bất kỳ tool nào agent chạy cũng có thể tự truy cập Internet, bao gồm các MCP (model context protocol) server mà bạn đã kết nối; bài chạy MCP server trên VPS giải thích chi tiết vấn đề này. Ngoài ra còn có telemetry nếu bạn bật.
Telemetry tắt cho đến khi bạn chủ động opt in. DSH_TELEMETRY_MODE là công tắc consent; giá trị unset, rỗng hoặc không được nhận diện sẽ chuyển thành DISABLED. Ở trạng thái đó, dsh không tạo provider, processor hoặc exporter OpenTelemetry (OTel), nên profile mới hoàn toàn không gửi telemetry qua network. FEEDBACK_ONLY opt in cho việc chia sẻ session log khi có feedback. FULL cũng cho phép gửi báo cáo từ launcher. Session feed có thể export nội dung session, dữ liệu tool, prompt và path của workspace, vì vậy hãy xem FULL là hành động gửi công việc của bạn đến DeepSeek.
Để tắt hoàn toàn mà không phụ thuộc vào việc đặt đúng mode string, hãy đặt DSH_TELEMETRY_DISABLED=1. Mọi giá trị không rỗng đều được xem là opt-out có hiệu lực, và biến này được đọc trước khi run bắt đầu, nên code của project không thể bật lại trong giữa session. Địa chỉ collector mặc định là harness-telemetry.deepseeksvc.com. Đây là một giá trị hữu ích cần biết khi bạn đọc firewall log của chính mình.
Hãy verify thay vì chỉ tin vào setting. Khi một task đang chạy, hãy liệt kê các outbound connection mà process đang giữ.
sudo ss -tnp | grep -i nodeTrong local-model mode, bạn sẽ thấy connection loopback đến 11434 và không thấy connection đến public address nào. Bất kỳ connection nào khác cũng cần được xác định trước khi bạn tiếp tục. Bài Agent coding gửi dữ liệu gì về máy chủ thực hiện cùng kiểm tra với các harness khác và giải thích cách đọc kết quả.
Nơi không nên lưu secret
- Lịch sử shell.
export DEEPSEEK_API_KEY=sk-...được ghi rõ dạng plain text vào~/.bash_historyvà vẫn còn ở đó rất lâu sau khi bạn rotate key. Thêm một dấu cách trước lệnh khi đã bậtHISTCONTROL=ignorespace, hoặc không dùng shell và ghi thẳng giá trị vào một file có mode 600. - Dotfile đã commit. Key trong
~/.bashrchoặc~/.zshrcchỉ còn cách public repository mộtgit addnếu bạn lưu dotfile trong git. Chạygit grep -I -n 'sk-'trong repository đó trước khi push. settings.yaml. DùngapiKeyEnvcho custom provider để file chỉ chứa tên biến thay vì secret. Config file thường bị dán vào issue report và support chat. Credentials file thì không.- Output của
envvà ảnh chụp màn hình terminal. Bất kỳ lệnh nào in toàn bộ environment cũng in cả key. - Backup.
~/.dshđáng được backup, nhưng.credentials.yamlbên trong đó là secret đang hoạt động. Loại file đó khỏi backup hoặc mã hóa archive.
Các quy tắc này không chỉ áp dụng cho dsh, và giữ secret ngoài các file env của Compose đề cập cùng vấn đề ở phía container của cùng server.
Vận hành bản developer preview
Ghim version đã kiểm thử, vì bản preview có thể thay đổi một config key trong một patch release và provider của bạn sau đó sẽ không load được. Đưa settings.yaml và cordis.patch.yml vào version control, đồng thời loại credentials file khỏi đó, để bạn biết chính xác những gì đã thay đổi sau khi upgrade.
Có 2 flag hữu ích khi profile không hoạt động đúng. --dump-default-config in ra default configuration đã compose mà không khởi động, còn --dump-config in ra configuration đã compose cho profile của bạn theo cách tương tự. So sánh 2 bản này cho biết patch layer thực sự đã thay đổi gì, nhanh hơn so với đọc từng layer bằng tay.
dsh --profile web --dump-configKhi có lỗi sau khi upgrade, hãy chạy lệnh đó trước tiên. Một key được chuyển giữa các release sẽ xuất hiện dưới dạng branch bị thiếu trong dump. Khi đó, cách sửa chỉ là chỉnh 1 dòng thay vì reinstall.
FAQ
dsh lưu DeepSeek API key ở đâu?
Trong $DSH_HOME/.credentials.yaml, tức là ~/.dsh/.credentials.yaml nếu bạn không tự đặt DSH_HOME. Trang Models ghi key vào đó, còn settings chỉ lưu tham chiếu đến key, nên secret chỉ nằm trong một file. Kiểm tra mode bằng stat -c '%a %n' ~/.dsh/.credentials.yaml và đặt thành 600 nếu mode hiện tại rộng hơn. Custom provider có thể không dùng file bằng cách chỉ định một biến môi trường qua apiKeyEnv.
Làm thế nào để dsh dùng local model thay vì DeepSeek API?
Thêm một custom provider có base URL trỏ đến local endpoint tương thích với OpenAI. Với Ollama, URL là http://127.0.0.1:11434/v1, dùng api: openai-completions và model id được sao chép chính xác từ ollama list. Ollama yêu cầu giá trị API key nhưng không sử dụng giá trị đó, nên mọi chuỗi không rỗng đều được. Xác nhận endpoint phản hồi bằng curl -s http://127.0.0.1:11434/v1/models trước khi sửa bất kỳ dsh config nào, vì endpoint không hoạt động và config sai tạo ra các lỗi tương tự nhau.
Theo mặc định, dsh có gửi code của tôi đi đâu không?
Có, nếu bạn dùng hosted model. Prompt và nội dung các file mà agent đã đọc nằm trong API request gửi đến vendor đó. Với local endpoint, request được gửi đến loopback và ở lại trên máy. Telemetry là một luồng riêng và mặc định đang tắt: khi chưa đặt, DSH_TELEMETRY_MODE trả về DISABLED, và ở trạng thái đó không tạo exporter nào. Đặt DSH_TELEMETRY_DISABLED=1 để opt out; giá trị này được đọc trước khi run bắt đầu.
Tại sao dsh báo MISSING_CREDENTIAL dù biến của tôi đã được đặt?
Vì dsh đọc biến do apiKeyEnv chỉ định từ process environment của chính nó. Biến được export trong shell của bạn không được truyền đến systemd service, session của user khác hoặc process đã khởi động trước khi bạn export biến đó. Đặt giá trị trong EnvironmentFile với mode 600 cho unit, hoặc export biến trong chính shell dùng để khởi động dsh. Xác nhận process đang chạy thực sự giữ giá trị nào bằng sudo tr '\0' '\n' < /proc/$(pgrep -f dsh | head -1)/environ.
dsh cần phiên bản Node.js nào?
Node.js 22.19 hoặc mới hơn trong dòng 22, hoặc 24 trở lên. Node 23 không nằm trong phạm vi được hỗ trợ. Chạy node -v trước mọi thao tác khác, vì lỗi khởi động do runtime không được hỗ trợ trông giống lỗi cài đặt và khiến người dùng cài lại package thay vì runtime.