dsh-vps 1.4.3 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +47 -6
- package/README.md +47 -6
- package/gate/server.js +37 -4
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -21,6 +21,16 @@
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
+
> **This is a VPS deployment tool for DSH, not a plugin you install inside DSH. Run the one-command install below on your VPS and it sets up DSH itself, complete with a login page.**
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/main/install.sh | sudo bash -s
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
With a domain, or behind the GFW, append arguments at the end, e.g. `bash -s -- --domain dsh.example.com --mirror cn`. See [Install](#install) below.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
24
34
|
## Overview
|
|
25
35
|
|
|
26
36
|
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) trusts the operator's own browser only: its privileged interfaces — settings, API keys, plugin management — sit behind a browser-trust fence, and a plain reverse proxy to the public internet leaves those pages dead.
|
|
@@ -80,7 +90,7 @@ dsh-vps puts a zero-dependency login gateway (dsh-gate) in front of DSH: public
|
|
|
80
90
|
|
|
81
91
|
- Ubuntu 22.04+ / Debian 12+ (root)
|
|
82
92
|
- 2 vCPU / 2 GB RAM or better; ports 80/443 open
|
|
83
|
-
- A domain gives you automatic HTTPS; a public IP with a self-signed certificate works too
|
|
93
|
+
- A domain gives you automatic HTTPS (point its A record at the server first); a public IP with a self-signed certificate works too
|
|
84
94
|
|
|
85
95
|
---
|
|
86
96
|
|
|
@@ -93,12 +103,43 @@ curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps
|
|
|
93
103
|
|
|
94
104
|
Add `--mirror cn` if you're behind the GFW (Node and DSH come from npmmirror).
|
|
95
105
|
|
|
96
|
-
|
|
106
|
+
No domain yet? Drop `--domain` and use the public IP:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/main/install.sh | sudo bash -s
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The certificate then comes from Caddy's internal CA, so the browser warns "Not secure / certificate not trusted". That is expected — proceed anyway. Add a domain in the wizard later and Caddy switches to a real certificate.
|
|
113
|
+
|
|
114
|
+
Or install through npm, running exactly the scripts shipped in this package (pinned, no network fetch; needs Node 22+ on the machine):
|
|
97
115
|
|
|
98
116
|
```bash
|
|
99
117
|
npx dsh-vps-install install --domain dsh.example.com
|
|
100
118
|
```
|
|
101
119
|
|
|
120
|
+
To pin a release instead of `main`, replace `main` with the version tag and point later gateway fetches at the same tag:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/v1.4.3/install.sh \
|
|
124
|
+
| sudo DSHVPS_RAW_BASE=https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/v1.4.3 bash -s -- --domain dsh.example.com
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If the final self-check reports that DSH is not ready yet, the setup link is still printed; the page shows startup progress and the actual error. Troubleshoot with `journalctl -u dsh-gate -n 80 --no-pager`.
|
|
128
|
+
|
|
129
|
+
## Update
|
|
130
|
+
|
|
131
|
+
Update the gateway code on an installed machine:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
sudo dsh-vps update-gate
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Machines installed with v1.4.1 or earlier that crash on start with `user patch-layer watching requires the Cordis HMR service` got a wrong dependency freeze point (it pulled in cordis releases incompatible with DSH 0.1.5-rc.2). Delete the DSH directory and run the install command again; accounts and data are kept:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
sudo systemctl stop dsh-gate && sudo rm -rf /opt/dsh-vps/dsh/0.1.5-rc.2
|
|
141
|
+
```
|
|
142
|
+
|
|
102
143
|
## Uninstall
|
|
103
144
|
|
|
104
145
|
```bash
|
|
@@ -106,13 +147,13 @@ curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps
|
|
|
106
147
|
| sudo bash -s -- --yes
|
|
107
148
|
```
|
|
108
149
|
|
|
109
|
-
Removes the service, install directory, Caddy site block and the DSH data directory, packing a backup to `/root/dsh-vps-uninstall-<timestamp>.tar.gz` first. `--keep-data` keeps the DSH data, `--purge-caddy` removes Caddy as well. Uninstall then install again gives you a clean environment.
|
|
150
|
+
Removes the service, install directory, Caddy site block and the DSH data directory, packing a backup (Caddyfile included) to `/root/dsh-vps-uninstall-<timestamp>.tar.gz` first. The Caddyfile you had before installing is restored, and only a wg0 created by `dsh-vps vpn` is removed — your own WireGuard setup is left alone. `--keep-data` keeps the DSH data, `--purge-caddy` removes Caddy as well. Uninstall then install again gives you a clean environment.
|
|
110
151
|
|
|
111
152
|
---
|
|
112
153
|
|
|
113
154
|
## First run
|
|
114
155
|
|
|
115
|
-
Installation prints a **setup link carrying a one-time token** — open it to reach the wizard: admin username/password → (optional) domain, DeepSeek API key & bundled plugins → log in. The wizard only answers to holders of the token, and the token is voided once setup completes. Lost the link? Print it again:
|
|
156
|
+
Installation prints a **setup link carrying a one-time token** — open it to reach the wizard (opening the bare IP or domain only shows a "setup token required" page, by design): admin username/password → (optional) domain, DeepSeek API key & bundled plugins → log in. The wizard only answers to holders of the token, and the token is voided once setup completes. Lost the link? Print it again:
|
|
116
157
|
|
|
117
158
|
```bash
|
|
118
159
|
sudo dsh-vps setup-url
|
|
@@ -120,7 +161,7 @@ sudo dsh-vps setup-url
|
|
|
120
161
|
|
|
121
162
|
Skipping the API key is fine; you can add it later via the "Add API key" prompt or Settings → Models → DeepSeek.
|
|
122
163
|
|
|
123
|
-
The checked plugins install in the background (tens of seconds) and DSH restarts to activate them. Two of them:
|
|
164
|
+
The checked plugins install in the background (tens of seconds), always at their latest npm version, and DSH restarts to activate them. Two of them:
|
|
124
165
|
|
|
125
166
|
- **dsh-market**: browse, search and install community plugins and themes from Settings. Everything else is left to you — add whatever you want from the marketplace afterwards
|
|
126
167
|
- **dsh-vps-manager**: manage this very VPS from inside DSH — `/vps-` queries that skip the model and cost no tokens, a terminal in the conversation, AI operations confirmed by risk level, and a recipe library. Add this machine under Settings → VPS Manager (SSH key login)
|
|
@@ -167,7 +208,7 @@ sudo dsh-vps update-gate # pull and restart the gateway code itself (no git re
|
|
|
167
208
|
sudo dsh-vps ownshost on # apply the settings-page patch (restores settings on a public domain)
|
|
168
209
|
sudo dsh-vps selfcheck # run the regression self-check (login / RPC / WebSocket / session)
|
|
169
210
|
sudo dsh-vps rollback # switch back to the previous DSH version
|
|
170
|
-
sudo dsh-vps reset-admin # emergency reset if you lose the admin password (re-runs the wizard, new token)
|
|
211
|
+
sudo dsh-vps reset-admin # emergency reset if you lose the admin password (re-runs the wizard, new token, signs out every session)
|
|
171
212
|
sudo dsh-vps setup-url # re-print the setup link with its one-time token
|
|
172
213
|
sudo dsh-vps backup # back up data (keeps the latest 3)
|
|
173
214
|
sudo dsh-vps vpn setup macbook # build a WireGuard tunnel and switch to "tunnel only"
|
package/README.md
CHANGED
|
@@ -22,6 +22,16 @@
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
> **这是 DSH 的 VPS 部署工具,不是在 DSH 里安装的插件,在 VPS 上执行下面的一键安装命令,它会装好带登录界面的 DSH 本身。**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/main/install.sh | sudo bash -s
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
有域名、在国内网络时,在末尾追加参数,例如 `bash -s -- --domain dsh.example.com --mirror cn`,详见下方[安装](#安装)。
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
25
35
|
## 简介
|
|
26
36
|
|
|
27
37
|
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)默认只认本机浏览器:它的特权接口(设置、API Key、插件管理)受浏览器信任围栏保护,直接反代到公网后这些页面全部失效。
|
|
@@ -85,7 +95,7 @@ dsh-vps puts a zero-dependency login gateway (dsh-gate) in front of DSH: public
|
|
|
85
95
|
|
|
86
96
|
- Ubuntu 22.04+ / Debian 12+(root)
|
|
87
97
|
- 2C2G 以上,端口 80/443 开放
|
|
88
|
-
- 有域名即可自动 HTTPS
|
|
98
|
+
- 有域名即可自动 HTTPS(先把 A 记录解析到本机);暂无域名也能先用公网 IP + 自签证书
|
|
89
99
|
|
|
90
100
|
---
|
|
91
101
|
|
|
@@ -103,12 +113,43 @@ curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps
|
|
|
103
113
|
| sudo bash -s -- --domain dsh.example.com --mirror cn
|
|
104
114
|
```
|
|
105
115
|
|
|
106
|
-
|
|
116
|
+
还没有域名?去掉 `--domain` 即可,按公网 IP 访问:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/main/install.sh | sudo bash -s
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
此时证书由 Caddy 内置 CA 自签,浏览器会提示「不安全 / 证书不受信任」,属预期现象,选择继续访问即可。之后在向导里填上域名,Caddy 自动换成正式证书。
|
|
123
|
+
|
|
124
|
+
走 npm 也行,装的是这个包自带的同一份脚本(版本固定,不联网拉取;需本机已有 Node 22+):
|
|
107
125
|
|
|
108
126
|
```bash
|
|
109
127
|
npx dsh-vps-install install --domain dsh.example.com
|
|
110
128
|
```
|
|
111
129
|
|
|
130
|
+
想固定在某个发布版本(而非 `main`),把地址里的 `main` 换成版本 tag,并让后续拉取的网关文件也用同一版本:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/v1.4.3/install.sh \
|
|
134
|
+
| sudo DSHVPS_RAW_BASE=https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps/v1.4.3 bash -s -- --domain dsh.example.com
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
安装末尾的自检若报「DSH 尚未就绪」,设置链接照样会打印;页面会显示启动进度与具体错误,排障见 `journalctl -u dsh-gate -n 80 --no-pager`。
|
|
138
|
+
|
|
139
|
+
## 更新
|
|
140
|
+
|
|
141
|
+
已安装的机器更新网关代码:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
sudo dsh-vps update-gate
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
用 v1.4.1 及更早版本装出、启动即报 `user patch-layer watching requires the Cordis HMR service` 的机器,是当时依赖冻结点有误(装进了与 DSH 0.1.5-rc.2 不兼容的 cordis 新版本)。删掉 DSH 目录后重跑安装命令即可修复,账号与数据保留:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
sudo systemctl stop dsh-gate && sudo rm -rf /opt/dsh-vps/dsh/0.1.5-rc.2
|
|
151
|
+
```
|
|
152
|
+
|
|
112
153
|
## 卸载
|
|
113
154
|
|
|
114
155
|
```bash
|
|
@@ -116,13 +157,13 @@ curl -fsSL https://raw.githubusercontent.com/AIcivilization/deepseek-harness-vps
|
|
|
116
157
|
| sudo bash -s -- --yes
|
|
117
158
|
```
|
|
118
159
|
|
|
119
|
-
删除服务、安装目录、Caddy 站点块与 DSH
|
|
160
|
+
删除服务、安装目录、Caddy 站点块与 DSH 数据目录,删除前打包备份(含 Caddyfile)到 `/root/dsh-vps-uninstall-<时间戳>.tar.gz`。安装前原有的 Caddyfile 会被还原;WireGuard 只移除 `dsh-vps vpn` 建的 wg0,你自己的隧道配置不动。`--keep-data` 保留 DSH 数据,`--purge-caddy` 连 Caddy 一起移除。卸载完再跑安装命令即为全新环境。
|
|
120
161
|
|
|
121
162
|
---
|
|
122
163
|
|
|
123
164
|
## 首次使用
|
|
124
165
|
|
|
125
|
-
|
|
166
|
+
安装结束时终端会打印一条**带一次性令牌的初始设置链接**,浏览器打开它进入向导(直接打开 IP 或域名只会看到「需要启动令牌」页,这是有意的):填管理员用户名/密码 → (可选)域名、DeepSeek API Key 与预置插件 → 登录即用。向导只对持有令牌的人开放,令牌在设置完成后自动作废。链接丢了随时重取:
|
|
126
167
|
|
|
127
168
|
```bash
|
|
128
169
|
sudo dsh-vps setup-url
|
|
@@ -130,7 +171,7 @@ sudo dsh-vps setup-url
|
|
|
130
171
|
|
|
131
172
|
API Key 跳过也无妨,登录后仍可在「添加 API Key」引导或 设置 → 模型 → DeepSeek 中补填。
|
|
132
173
|
|
|
133
|
-
|
|
174
|
+
勾选的插件在后台安装(约几十秒),始终取 npm 上的最新版本,装完 DSH 自动重启生效,共两款:
|
|
134
175
|
|
|
135
176
|
- **dsh-market**:设置页内浏览、搜索、一键安装社区插件与主题。其余插件留给你自己挑,装好后在市场里按需添加
|
|
136
177
|
- **dsh-vps-manager**:在 DSH 里直接管理这台 VPS——`/vps-` 系列查询命令不经过模型、不花 token,对话内嵌终端,AI 操作按风险分级确认,另有运维菜谱库。需在 设置 → VPS Manager 中添加本机(SSH 密钥登录)
|
|
@@ -177,7 +218,7 @@ sudo dsh-vps update-gate # 拉取并重启网关自身代码(安装目录非
|
|
|
177
218
|
sudo dsh-vps ownshost on # 应用设置页可用性补丁(公网域名下恢复设置页)
|
|
178
219
|
sudo dsh-vps selfcheck # 跑一遍回归自检(登录 / RPC / WebSocket / 会话)
|
|
179
220
|
sudo dsh-vps rollback # 切回上一 DSH 版本
|
|
180
|
-
sudo dsh-vps reset-admin #
|
|
221
|
+
sudo dsh-vps reset-admin # 忘记管理员密码时的应急重置(重新走向导并换发令牌,已登录的会话全部失效)
|
|
181
222
|
sudo dsh-vps setup-url # 重新打印带一次性令牌的初始设置链接
|
|
182
223
|
sudo dsh-vps backup # 备份数据(保留最近 3 份)
|
|
183
224
|
sudo dsh-vps vpn setup macbook # 建 WireGuard 隧道并切到「仅隧道可访问」
|
package/gate/server.js
CHANGED
|
@@ -106,6 +106,16 @@ const FORWARDING_HEADERS = new Set(["forwarded", "x-forwarded-for", "x-real-ip"]
|
|
|
106
106
|
// 在 gate 之外拉起一个新的 DSH 进程,抢占 3080 端口,gate 的子进程随后
|
|
107
107
|
// EADDRINUSE 且再也抓不到 launchToken → 永久"会话尚未就绪"。
|
|
108
108
|
const MARKET_RESTART_PATHS = new Set(["/dsh-market/restart", "/dsh-market/restart/"]);
|
|
109
|
+
// dshmarket 1.64+ 的 v1 接口:内部直接调用上面那个旧端点(不经 HTTP),必须一起接管
|
|
110
|
+
const MARKET_RESTART_V1_PATHS = new Set(["/dsh-market/api/v1/restart", "/dsh-market/api/v1/restart/"]);
|
|
111
|
+
const MARKET_V1_SCHEMA = "dsh-market/update-api/v1";
|
|
112
|
+
|
|
113
|
+
// dshmarket 的写操作(安装/更新/卸载/备份导出……)为防 DNS 重绑定,要求 Host 必须是回环地址,
|
|
114
|
+
// Origin 必须与 Host 一致;经 gate 转发时 Host 是公网域名,于是一律 403 "untrusted origin"。
|
|
115
|
+
// gate 已完成登录校验,这里替它做同样的同源检查(Origin 与公网 Host 一致、非跨站),
|
|
116
|
+
// 通过后把 Host/Origin 改写成 DSH 的回环地址再转发。设 GATE_MARKET_LOOPBACK=0 可关闭。
|
|
117
|
+
const MARKET_PREFIX = "/dsh-market/";
|
|
118
|
+
const MARKET_LOOPBACK = process.env.GATE_MARKET_LOOPBACK !== "0";
|
|
109
119
|
// 设 GATE_TAKEOVER_RESTART=0 则放行给 DSH 自己处理(会退回到上面那个坑,仅供对照排障)
|
|
110
120
|
const TAKEOVER_RESTART = process.env.GATE_TAKEOVER_RESTART !== "0";
|
|
111
121
|
|
|
@@ -889,6 +899,11 @@ function proxyHttp(req, res) {
|
|
|
889
899
|
}
|
|
890
900
|
const cookie = upstreamCookieHeader(req.headers.cookie, authority);
|
|
891
901
|
if (cookie !== void 0) headers.cookie = cookie;
|
|
902
|
+
if (MARKET_LOOPBACK && (req.url || "").startsWith(MARKET_PREFIX)) {
|
|
903
|
+
const loopback = `127.0.0.1:${DSH_PORT}`;
|
|
904
|
+
headers.host = loopback;
|
|
905
|
+
if (headers.origin !== void 0) headers.origin = `http://${loopback}`;
|
|
906
|
+
}
|
|
892
907
|
|
|
893
908
|
let responded = false;
|
|
894
909
|
const upstreamReq = http.request(
|
|
@@ -952,6 +967,18 @@ function proxyHttp(req, res) {
|
|
|
952
967
|
req.pipe(upstreamReq);
|
|
953
968
|
}
|
|
954
969
|
|
|
970
|
+
/** 市场请求的同源检查:Origin(若有)须与浏览器访问的公网 Host 一致,且不是跨站请求。 */
|
|
971
|
+
function marketRequestSameOrigin(req) {
|
|
972
|
+
if (String(req.headers["sec-fetch-site"] || "") === "cross-site") return false;
|
|
973
|
+
const origin = req.headers.origin;
|
|
974
|
+
if (origin === void 0) return true; // 同源 GET 导航(如备份下载)不带 Origin
|
|
975
|
+
try {
|
|
976
|
+
return new URL(origin).host === requestAuthority(req.headers);
|
|
977
|
+
} catch {
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
955
982
|
function denyUnauthenticated(req, res, pathname) {
|
|
956
983
|
if (pathname.startsWith("/api")) {
|
|
957
984
|
sendText(res, 401, "gate authentication required");
|
|
@@ -969,15 +996,16 @@ function denyUnauthenticated(req, res, pathname) {
|
|
|
969
996
|
* 这里按官方客户端的协议回 202 + ok,然后由 gate 自己重启 DSH 子进程:
|
|
970
997
|
* 子进程是全新的,/dsh-market/status 的 boot id 随之变化,前端会自动 reload。
|
|
971
998
|
*/
|
|
972
|
-
function handleMarketRestart(req, res) {
|
|
999
|
+
function handleMarketRestart(req, res, v1) {
|
|
973
1000
|
if (req.method !== "POST") {
|
|
974
1001
|
res.writeHead(405, { allow: "POST", "content-length": "0" });
|
|
975
1002
|
res.end();
|
|
976
1003
|
return;
|
|
977
1004
|
}
|
|
978
|
-
log(
|
|
1005
|
+
log(`market restart requested${v1 ? " (v1)" : ""}; gate takes over`);
|
|
1006
|
+
const result = { ok: true, managedBy: "dsh-gate", note: "由 gate 重启 DSH 子进程" };
|
|
979
1007
|
res.writeHead(202, { "content-type": "application/json", "cache-control": "no-store" });
|
|
980
|
-
res.end(JSON.stringify({
|
|
1008
|
+
res.end(JSON.stringify(v1 ? { schema: MARKET_V1_SCHEMA, result } : result));
|
|
981
1009
|
// 让 202 先落地,再动手(客户端随后轮询 /dsh-market/status 等 boot id 变化)
|
|
982
1010
|
setTimeout(() => restartDsh("market restart"), 300);
|
|
983
1011
|
}
|
|
@@ -1666,7 +1694,12 @@ function main() {
|
|
|
1666
1694
|
denyUnauthenticated(req, res, pathname);
|
|
1667
1695
|
return;
|
|
1668
1696
|
}
|
|
1669
|
-
if (
|
|
1697
|
+
if (pathname.startsWith(MARKET_PREFIX) && !marketRequestSameOrigin(req)) {
|
|
1698
|
+
sendText(res, 403, "cross-origin market request refused by gate");
|
|
1699
|
+
return;
|
|
1700
|
+
}
|
|
1701
|
+
if (TAKEOVER_RESTART && MARKET_RESTART_PATHS.has(pathname)) return handleMarketRestart(req, res, false);
|
|
1702
|
+
if (TAKEOVER_RESTART && MARKET_RESTART_V1_PATHS.has(pathname)) return handleMarketRestart(req, res, true);
|
|
1670
1703
|
proxyHttp(req, res);
|
|
1671
1704
|
})
|
|
1672
1705
|
.catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vps",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "Ship DeepSeek Harness to your own VPS: one command installs a zero-dependency login gateway, automatic HTTPS through Caddy, systemd supervision, and optional WireGuard-only access.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|