SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-25

Cấu hình dsh: API key, model và endpoint

Tìm đúng nơi dsh lưu config trên Linux, nối DeepSeek API key hoặc Ollama local, và biết chính xác dữ liệu nào rời khỏi máy trong từng 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 vào đó dưới dạng các file văn bản thuần. 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 mọi thứ bạn sẽ thao tác.

  • ~/.dsh/settings.yaml chứa các thiết lập do bạn viết và do UI ghi vào, bao gồm các route đến provider và model.
  • ~/.dsh/.credentials.yaml chứa các secret. Các thiết lập chỉ lưu tham chiếu đến credential, nên giá trị key thực tế nằm trong một file.
  • ~/.dsh/profiles/ chứa các profile đã đặt tên, còn ~/.dsh/storages/ chứa các session đã lưu.
  • ~/.dsh/cordis.patch.yml là lớp patch của riêng bạn. Lớp này được áp dụng lên cấu hình tích hợp cho mọi profile.

DeepSeek công bố harness này dưới dạng bản xem trước dành cho developer, được cấp phép MIT, vào ngày 17 August 2026. README nêu rõ sẽ có các thay đổi làm mất tính tương thích. Tên field và đường dẫn 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 cấu hình từ bất kỳ hướng dẫn nào, kể cả hướng dẫn này, vì bản xem trước có thể đổi tên giữa các release.

Bản tối thiểu thực tế để có output đầu tiên

dsh cần Node.js 22.19 trở lên trong nhánh 22, hoặc Node 24 trở lên. Node 23 nằm ngoài phạm vi này. Kiểm tra version trước, vì không khớp version sẽ khiến ứng dụng fail ngay khi khởi động và thông báo lỗi trông giống lỗi package bị hỏng.

node -v
npx @deepseek-ai/dsh web

npx tải package từ npm registry và khởi động Web UI trên http://127.0.0.1:3080. Nó bind vào địa chỉ loopback, 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 qua SSH thay vì mở cổng 3080 ra Internet. Nếu URL được in ra là phần khó hiểu, vì sao dsh khởi động trên địa chỉ đó giải thích loopback bind bảo vệ điều gì và không bảo vệ điều gì.

ssh -N -L 3080:127.0.0.1:3080 you@your-server

Mở 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ể dùng ngay, 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 DeepSeek Harness trên VPS trình bày phần chuẩn bị server mà hướng dẫn này giả định.

Sau khi lưu, hãy kiểm tra những gì app đã tạo.

ls -la ~/.dsh
stat -c '%a %n' ~/.dsh/.credentials.yaml

Bạ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"

Profile headless 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ó 2 cách cung cấp key cho dsh. Hai cách này 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) 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ữ một 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ể chỉ định một biến môi trường thay thế bằng apiKeyEnv. Đây là cấu trúc được tài liệu 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 là phần dễ thay đổi 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ừ environment 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 interactive sẽ không hiển thị với systemd unit. Vì vậy, cùng một config hoạt động khi bạn tự gõ dsh web sẽ trả về MISSING_CREDENTIAL khi chạy dưới dạng 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à để user chạy service làm owner.

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 model 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 đổi không sửa lại cuộc hội thoại cũ.

Provider ID là cố định. Request, session đã lưu, model mặc định và 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 chỉ xử lý text trừ khi bạn khai báo khác đi. 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 các model không được catalog mô tả. Route chat-completions của DeepSeek chỉ xử lý text và không thể cấu hình khác đi, 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 mọi base URL tương thích với OpenAI 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ách 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/models

ollama list in chính xác tag của từng model bạn đã pull. Hãy copy chuỗi đó. curl trả về các model tương tự 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 lắng nghe 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 dùng đượ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 tại nơi 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.env

Ba lỗi sau bao quát gần như mọi lần 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, nên 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, nên 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ừ quá trình discovery model, trong đó dsh 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.

Base URL cũng là một điểm dễ nhầm. Không thêm /v1 vào cuối URL thì request sẽ đi đến các path mà Ollama không cung cấp, khiến lệnh gọi trả về lỗi 404 và model không chạy. Hậu tố này là một phần của giao diện tương thích với OpenAI, 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 một host, hoặc đặt nó sau TLS (transport layer security) và authentication: bảo vệ endpoint Ollama được expose ra ngoài.

Những gì rời khỏi máy trong từng chế độ

Với DeepSeek key, mọi request đều được gử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 những command 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 thư mục nơi mình khởi chạy agent.

Với một catalog provider khác hoặc gateway của công ty, payload tương tự sẽ được gửi đến vendor đó. Base URL cho biết chính xác đích đến.

Với local endpoint, request đến model được gử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 được model vendor. Tuy vậy, vẫn có ba 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. Plugin cũng thuộc cùng nhóm, vì việc cài plugin sẽ chạy code của tác giả khác với các quyền của agent, nên bạn nên kiểm tra plugin có thể truy cập gì trước khi cài. Ngoài ra còn có telemetry, nếu bạn bật tính năng này.

Telemetry tắt cho đến khi bạn chủ động opt in. DSH_TELEMETRY_MODE là công tắc đồng ý, còn giá trị unset, rỗng hoặc không được nhận diện sẽ được chuyển thành DISABLED. Ở trạng thái đó, dsh không tạo provider, processor hoặc exporter cho OpenTelemetry (OTel), nên profile mới hoàn toàn không gửi request telemetry qua network. FEEDBACK_ONLY opt in việc chia sẻ log session khi có feedback. FULL cũng cho phép 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.

Để chặn hoàn toàn mà không phụ thuộc vào việc đặt đúng chuỗi mode, hãy đặt DSH_TELEMETRY_DISABLED=1. Bất kỳ giá trị không rỗng nào cũng là lệnh 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 hostname hữu ích khi bạn kiểm tra firewall log của chính mình.

Hãy xác minh thay vì chỉ tin vào setting. Khi task đang chạy, hãy liệt kê các kết nối outbound mà process đang giữ.

sudo ss -tnp | grep -i node

Trong local-model mode, bạn sẽ thấy kết nối loopback đến 11434 và không thấy kết nối đến địa chỉ public nào. Bất kỳ kết nối nào khác đều 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ả.

Những nơi không nên lưu secret

  • Lịch sử shell. export DEEPSEEK_API_KEY=sk-... được ghi rõ dạng văn bản vào ~/.bash_history và vẫn nằm ở đó lâu sau khi bạn rotate key. Thêm một dấu cách ở đầu lệnh khi HISTCONTROL=ignorespace được set, hoặc bỏ qua shell và ghi thẳng giá trị vào một file có mode 600.
  • Dotfile đã commit. Một key trong ~/.bashrc hoặc ~/.zshrc chỉ còn cách một git add là xuất hiện trong public repository nếu bạn lưu dotfile bằng git. Chạy git grep -I -n 'sk-' trong repository đó trước khi push.
  • settings.yaml. Dùng apiKeyEnv cho 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 env và ảnh chụp terminal. Bất cứ lệnh nào in toàn bộ environment cũng in cả key.
  • Backup. ~/.dsh đáng được backup, nhưng .credentials.yaml bên trong nó là một secret đang hoạt động. Loại file đó khỏi archive hoặc mã hóa archive.

Các quy tắc này không chỉ áp dụng cho dsh, và không lưu secret trong file env của Compose đề cập cùng vấn đề ở phía container trên cùng server.

Vận hành với bản preview dành cho nhà phát triển

Hãy ghim version bạn đã kiểm thử, vì bản preview có thể thay đổi một config key trong bản patch release khiến provider của bạn không tải được. Nếu bản cài đặt đã ghim version vẫn không khởi động, hoặc npx liên tục cung cấp một build bạn không yêu cầu, các lỗi cài đặt và version do bản preview tạo ra sẽ giải thích về npx cache và npm đi kèm với Node của bạn. Hãy đưa settings.yaml và cordis.patch.yml vào version control, đồng thời loại trừ credentials file, để bạn biết được những gì đã thay đổi sau khi upgrade.

Hai flag hữu ích khi profile không hoạt động như mong đợi. --dump-default-config in ra cấu hình mặc định đã ghép mà không boot, còn --dump-config in ra cấu hình đã ghép cho profile của bạn theo cách tương tự. So sánh hai cấu hình này cho thấy patch layer của bạn thực sự đã thay đổi gì, nhanh hơn so với đọc từng layer bằng tay.

dsh --profile web --dump-config

Khi 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 một branch bị thiếu trong bản dump, và cách sửa chỉ là chỉnh một dòng thay vì cài đặt lại.

FAQ

dsh lưu DeepSeek API key ở đâu?

Trong $DSH_HOME/.credentials.yaml, mặc định 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. Vì vậy 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 với apiKeyEnv.

Làm thế nào để dsh dùng model local thay vì DeepSeek API?

Thêm một custom provider có base URL trỏ đến endpoint tương thích với OpenAI local của bạn. Với Ollama, URL đó là http://127.0.0.1:11434/v1, cùng api: openai-completions và model id được sao chép chính xác từ ollama list. Ollama yêu cầu một giá trị API key nhưng bỏ qua giá trị đó, nên mọi chuỗi không rỗng đều được. Xác nhận endpoint trả lờ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. Endpoint không hoạt động và config sai có thể tạo ra các lỗi giống nhau.

Mặc định dsh có gửi code của tôi đi đâu không?

Có, khi dùng model hosted. Prompt của bạn và nội dung các file agent đã đọc nằm trong API request gửi đến vendor đó. Khi dùng local endpoint, request đi đến loopback và vẫn nằm trên máy. Telemetry là một luồng riêng và mặc định đang tắt: DSH_TELEMETRY_MODE trả về DISABLED khi chưa được đặt. Ở trạng thái đó, không exporter nào được tạo. Đặt DSH_TELEMETRY_DISABLED=1 để opt out trước khi run bắt đầu.

Tại sao dsh báo MISSING_CREDENTIAL khi biến của tôi đã được đặt?

Vì dsh đọc biến có tên do apiKeyEnv chỉ định từ process environment của chính nó. Biến được export trong shell của bạn sẽ không đến được 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 khởi chạy dsh. Xác nhận process đang chạy thực sự có gì 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 trở lên trong nhánh 22, hoặc 24 trở lên. Node 23 không nằm trong khoảng phiên bản được hỗ trợ. Chạy node -v trước mọi thao tác khác. Lỗi khởi động do runtime không được hỗ trợ trông giống lỗi cài đặt hỏng, khiến người dùng cài lại package thay vì runtime.