Elric's Desk

雜亂的書桌

上一篇把 Qwen3.6 27B 跑在了 RX 7900 XTX 上,这套本地推理栈稳定跑了一段时间。这篇记三件事:模型升到 Qwen3.8 27B、接入 DeepSeek Harness(dsh)、再用 Cloudflare Tunnel + Access 把 Agent 安全开到公网。

一、Qwen3.6 27B 升 Qwen3.8 27B

升级最省事。整套链路是 OpenAI 兼容 API,模型换代对上层客户端基本透明。

换模型文件

新模型同样选 abliterated(去拒绝化)版本 + Q4_K_M 量化:

1
2
3
4
模型文件: huihui-qwen3.8-27b-abliterated-q4_k_m.gguf
大小: ~16.8GB
量化: Q4_K_M(4-bit 混合精度)
上下文: 64K

27B、Q4_K_M、16.8GB,放在 24GB 显存上仍然安全,沿用上一篇算好的预算(模型 ~16.8GB + KV cache q8_0 64K ~3.8GB + ROCm 开销 ~1-2GB,约 22-23GB),不用重新调参。

重启 llama-server

服务指向新文件、改下 alias:

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/systemd/system/llama.service(节选)
ExecStart=/home/elric/llama.cpp/build/bin/llama-server \
-m /home/elric/llama.cpp/models/huihui-qwen3.8-27b-abliterated-q4_k_m.gguf \
--alias qwen3.8-27b \
--host 0.0.0.0 \
--port 1234 \
-ngl 99 \
--flash-attn on \
--ctx-size 65536 \
-ctk q8_0 \
-ctv q8_0 \
--jinja
1
2
3
sudo systemctl restart llama.service
# 确认模型已加载
curl http://localhost:1234/v1/models

上层客户端改 alias

端点是 OpenAI 兼容的 http://localhost:1234/v1,Hermes Agent 的 custom provider 里把 model 字段从 qwen3.6-27b 改成 qwen3.8-27b 就行,baseURL、apiKey 都不用动。

升级成本:一个模型文件 + 一行 alias。OpenAI 兼容 API 的好处就在这,模型层可以独立迭代,上层无感。

二、接入 DeepSeek Harness(dsh)

dsh 是 DeepSeek 开源的 Agent 编排框架(TypeScript,MIT,开发者预览版,会有 breaking changes)。它不是推理引擎,是编排层:工具、会话、沙箱、UI。本地模型(llama.cpp / vLLM)作为 OpenAI 兼容 provider 插进来。

dsh 还在 0.1.0-rc 阶段,接口和配置会频繁变动,生产用建议锁版本。

dsh 只绑 127.0.0.1

dsh 出于安全考虑拒绝 --host 0.0.0.0,只能绑 127.0.0.1。但我想在局域网/公网访问它的 Web UI。解法:dsh 跑内部端口,nginx 代理对外端口。

两个容器(compose 编排):

容器 镜像 作用
dsh node:22-alpine dsh 本体,host 网络,绑 127.0.0.1:3081
dsh-proxy nginx 对外 192.168.x.x:3080,转发到 127.0.0.1:3081

dsh 启动命令:

1
2
3
4
node --expose-internals /usr/local/bin/dsh web \
--port 3081 \
--trusted-host 192.168.x.x:3080 \
--trusted-host 192.168.x.x

浏览器信任 403

setup 里最磨人的一段,nginx 改了 4 次才搞定。

dsh 对特权 RPC 方法(比如 settings.describe)有一道 isTrustedApiRequest 信任栅栏,要求同时满足:

  1. Host 头是 loopback
  2. sec-fetch-site 不是 cross-site
  3. Origin 的 host 等于 Host 的 host

请求过一遍 nginx 后,HostOrigin 变成了公网地址,栅栏判定失败,403。

修复:在 nginx 的 /api/ location 里把 HostOrigin 都重写成 loopback:

1
2
3
4
5
6
location /api/ {
proxy_pass http://127.0.0.1:3081;
proxy_set_header Host 127.0.0.1:3081;
proxy_set_header Origin http://127.0.0.1:3081;
proxy_set_header X-Forwarded-Host $host;
}

验证栅栏有没有过:

  • 不带 Origin curl,200
  • Origin: http://<public> curl,403(栅栏拦了)
  • 修复后,400 “body is not JSON”(栅栏过了,400 只是 RPC 层在校验合成 body,正常)

bind mount 的 inode 陈旧

改了 nginx.conf 却没生效?因为覆盖写入 bind-mounted 文件时,容器里挂的还是旧 inode,你改的是宿主机新文件,容器看的是旧文件。

1
2
# 宿主机 vs 容器内文件大小不一致,就是 inode 问题
docker restart dsh-proxy # 重新解析挂载

改 bind mount 的配置后,docker restart 对应容器,再在容器内 grep / wc -c 验证,别只看宿主机。

配置 provider(in-container)

dsh 的配置在容器内:

  • /root/.dsh/settings.yaml,provider + 默认模型
  • /root/.dsh/.credentials.yaml,实际的 API key 值
1
2
3
4
5
6
7
8
9
10
11
12
13
# /root/.dsh/settings.yaml(节选)
providers:
- name: qwen3827b
displayName: Huihui-Qwen3.8-27B-abliterated
api: openai-completions
baseURL: http://192.168.x.x:1234/v1
apiKeyEnv: QWEN3827B_API_KEY
models:
- id: qwen3.8-27b
contextWindow: 65000
agent-default-model:
provider: qwen3827b
model: qwen3.8-27b
1
2
# /root/.dsh/.credentials.yaml
QWEN3827B_API_KEY: [REDACTED]

本地 llama.cpp 的 apiKey 其实可以随便填(它不校验),但 dsh 要求这个字段非空,给个占位值就行。

前端小坑:crypto.randomUUID

dsh 前端用到了 crypto.randomUUID,某些环境下缺失。要往 dsh-web-frontend/dist/index.html 注入一个 polyfill,并用一个标记(比如 DSH_UUID_PATCH)标注,方便更新后 grep 验证还在不在:

1
2
3
docker exec dsh grep -c DSH_UUID_PATCH \
/usr/local/lib/node_modules/@deepseek-ai/dsh/dsh-web-frontend/dist/index.html
# 期望 ≥ 1

验证清单(全过才算成功)

  1. docker ps,两个容器都 Up,docker inspect 看 0 重启
  2. curl 对外端口,HTTP 200
  3. 模型后端:curl http://192.168.x.x:1234/v1/models
  4. polyfill:容器内 grep DSH_UUID_PATCH,≥1
  5. 端到端证据:/root/.dsh/storages/session_projcache.json 里有 session 的 sessionStats(turns/steps/decodeTokens/llmMs),真实调用过的铁证
  6. docker logs dsh | grep -iE 'error|warn|fail',无异常

一个真实 session 证据(脱敏):turns=3, steps=9, llmMs=54836, decodeTokens=1387,模型确实在被调用,不是空转。

备注:dsh 的推理档位只接受 xhigh(默认)/ medium / low,写 high 会报 Jinja 错 Unexpected reasoning effort high。浏览器自动化工具对 dsh UI 时好时坏,curl + SSH 是最可靠的验证路径。

三、Cloudflare 安全公网(Tunnel + Access)

dsh 跑在 192.168.x.x:3080,局域网内访问没问题。但它是 Agent,谁能进 UI,谁就能读工作区文件、跑工具。开到公网,别裸开端口,前面挂一层真正的登录墙。

架构

1
2
3
4
5
6
7
浏览器 ──HTTPS──> Cloudflare 边缘 ──加密隧道──> cloudflared(token 模式, 仅出向)

CF Access 应用(登录墙)
未认证 → 302 跳 CF 登录页


nginx:3080 ──> dsh:3081

分层:

  1. Cloudflare Access 应用(真正的防护)。一个子域(比如 dsh.elric.top)指向 http://192.168.x.x:3080。未认证请求先被 302 到 CF 登录页,根本到不了 nginx。认证用 OIDC(推荐)或 Email OTP(一次性验证码,零配置)。
  2. 边缘 TLS + 隧道通道。CF 在边缘终结 TLS,隧道是加密出向通道,路由器上不用开任何入站端口(契合”国内运营商爱扫 80/443”的顾虑)。
  3. 既有层仍生效。浏览器信任 403 栅栏还在,LLM 后端 192.168.x.x:1234 保持仅局域网。
  4. 可选加固。CF 限流;子域起个不那么显眼的名字(想靠隐蔽就别叫 dsh.);token 最小权限、可随时吊销。

创建 Access 应用(Zero Trust 控制台)

  1. Applications → Add an application → Type: Self-hosted
    • Application domain: dsh.elric.top
    • Service address: http://192.168.x.x:3080
  2. Access policies → Add a policy
    • 认证:One-time PIN (Email)(零配置起步)或 OIDC
    • Include:你的邮箱
  3. 可选:MFA、IP 白名单、受信设备
  4. 后续可加 Service Token,让 CLI/API 免浏览器自动登录

CN 控制台小提示:中文界面下模板选择器没有现成的 “Edit Cloudflare Access” 模板。用自定义令牌,权限框按英文标识搜索(Access / Tunnel / DNS),等约 1s 异步下拉。权限给 Edit,作用域限定到具体 zone elric.top(别选 All resources),TTL 设 0。

端到端验证

  1. curl -sL -o /dev/null -w '%{http_code}\n' https://dsh.elric.top,未认证请求应得到 CF Access 登录跳转(而不是 dsh UI)
  2. 完成认证(OIDC / OTP),dsh UI 加载
  3. 确认登录页是 Cloudflare 的,不是应用的,证明墙在 nginx 前面

总结

  • 模型升级零成本:OpenAI 兼容 API 让模型层独立迭代,换文件 + 改 alias 就完事。
  • dsh 接入的核心问题:loopback-only 绑定要 nginx 代理,403 信任栅栏要重写 Host + Origin,bind mount 改配置要 docker restart 加容器内验证。
  • 公网安全:别裸开端口,Cloudflare Tunnel(仅出向)加 Access 登录墙,分层防御,LLM 后端留在局域网。

这套组合打下来,本地大模型、Agent 编排、安全公网就齐了,基本能直接照抄。


本文环境:ai-server 上 llama.cpp 提供 qwen3.8-27b(Q4_K_M,64K ctx,16.8GB);dsh 为 0.1.0-rc 开发者预览版,接口可能变动。

Spectrum + Hermes Agent 接入 iMessage 全記錄:從零到能用的踩坑實錄

作者: Elric
日期: 2026-07-19
標籤: iMessage Spectrum Hermes Agent Bun TypeScript Docker 踩坑


前言

想把 iMessage 接入 AI 智能體?目前市面上幾乎沒有現成的方案——iMessage 是 Apple 的封閉生態,不像 Telegram/WhatsApp 有公開 Bot API。本文記錄了使用 Photon Spectrum Cloud 雲端橋接 + Hermes Agent 的回覆引擎,完整打通 iMessage → AI 回覆的全過程,以及途中遇到的所有坑。


架構總覽

1
2
3
4
5
6
7
8
9
10
11
12
iPhone iMessage

[Photon Spectrum Cloud] ← 雲端橋接,不需 Mac 長期在線

[自托管服務器 /opt/spectrum-bot]
├── Bun 1.3.14 運行時
├── spectrum-ts@11.2.0 SDK
└── index.ts 自訂邏輯

[Hermes Agent] ← 用 hermes -z 處理訊息並回覆

iMessage 回覆送到手機

第一步:環境準備

服務器信息

  • OS: Ubuntu 22.04 (Docker 宿主機)
  • IP: YOUR_SERVER_IP
  • Hermes Agent: v0.18.2(已預裝)
  • Node.js: v22.22.2

安裝 Bun

Photon Spectrum 的 SDK spectrum-ts 官方推薦使用 Bun 運行時:

1
2
3
4
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
bun --version
# → 1.3.14

坑 #1: 如果服務器之前裝過舊版 Bun,記得 source ~/.bashrc 或重開終端,否則 PATH 沒更新。


第二步:創建 Spectrum Cloud 項目

註冊 Photon Spectrum

前往 app.photon.codes 註冊帳號。

坑 #2: 網站有 Cloudflare 人機驗證,從服務器的無頭瀏覽器很難通過!
解決方案: 用本地瀏覽器(你的 Mac/PC)手動訪問註冊,然後複製 Project ID 和 Secret。

獲取憑證

註冊成功後,在 Photon Dashboard 創建一個新項目,拿到:

1
2
SPECTRUM_PROJECT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
SPECTRUM_PROJECT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

這兩個值就是你的 iMessage 橋接鑰匙。


第三步:初始化項目

1
2
3
4
mkdir -p /opt/spectrum-bot
cd /opt/spectrum-bot
bun init -y
bun add spectrum-ts@11.2.0

坑 #3: spectrum-ts 會依賴 @spectrum-ts/core,這個庫自帶 Zod v4,而 Zod v4 的 TypeScript 類型定義和 tsc 有兼容性問題。
現象: 跑 tsc --noEmit 會報 50+ 個類型錯誤。
處理: 完全忽略——Bun 運行時無視這些錯誤,能正常執行。

配置環境變量

1
2
3
4
cat > /opt/spectrum-bot/.env << 'EOF'
SPECTRUM_PROJECT_ID=你的ID
SPECTRUM_PROJECT_SECRET=你的SECRET
EOF

第四步:編寫 Bot(踩坑密集區)

初版:照搬 README(出事了)

1
2
3
4
5
// ❌ 錯誤示範 — 這份代碼不會工作
for await (const [space, message] of app.messages) {
console.log(`收到: ${message.text}`); // undefined
console.log(`來自: ${message.from.name}`); // undefined
}

這是我們遇到的第一個重大坑。

坑 #4: message.text 不存在

Spectrum 的 Message 類型沒有 text 屬性!訊息內容在 message.content 中。

正確結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ✅ Message 類型 (簡化)
interface Message {
content: Content; // ← 內容在這裡!
sender?: User; // ← 不是 from!
// ...
}

// Content 是聯合類型
interface TextContent {
type: "text";
text: string; // 文字內容在 content.text
}
interface MarkdownContent {
type: "markdown";
markdown: string;
}

正確取文字:

1
2
3
4
const contentType = message.content.type;
const text = contentType === "text" ? message.content.text
: contentType === "markdown" ? message.content.markdown
: JSON.stringify(message.content);

坑 #5: message.from 不存在

發送者是 message.sender 而不是 message.from

而且 User 類型非常簡潔:

1
2
3
4
5
interface User {
readonly __platform: string; // 平台標識
readonly id: string; // 用戶 ID(iMessage 裡是電話號碼)
readonly kind?: "agent"; // 可選
}

沒有 namedisplayName 等字段,只有 id。iMessage 場景下 id 就是對方的手機號。

正確用法:

1
const senderId = message.sender?.id || "unknown";  // → +852xxxxxxxx

第五步:接入 Hermes Agent(又一個坑)

坑 #6: hermes chat -q 輸出思考過程

一開始我用:

1
2
// ❌ 錯誤
const reply = await $`hermes chat -q "問題" -Q --cli`.text();

hermes chat 是交互模式,即使加上 -Q(安靜模式),仍然會輸出 Agent 的內部推理和工具調用計劃,而不是最終答案。

實際輸出是這樣的:

1
2
3
Let me search past sessions for any Messenger-related context first,
then check what capabilities are available regarding message handling
in Hermes Agent docs/skills to give you an accurate, grounded...

這顯然不是你想讓 iMessage 收到的回覆。

✅ 正確方案:用 hermes -z

1
2
hermes -z "你的問題"
# → 我叫 Hermes Agent,由 Nous Research 創造,你的智能助手。

-z 是 top-level 的單輪查詢模式,直接返回純文字答案,沒有多餘輸出,速度也更快。

最後的 Bot 代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { Spectrum } from "spectrum-ts";
import { imessage } from "spectrum-ts/providers/imessage";
import { $ } from "bun";

const app = await Spectrum({
projectId: process.env.SPECTRUM_PROJECT_ID!,
projectSecret: process.env.SPECTRUM_PROJECT_SECRET!,
providers: [imessage.config()],
});

console.log("🤖 Spectrum -> Hermes iMessage bridge running...");

for await (const [space, message] of app.messages) {
await space.responding(async () => {
const senderId = message.sender?.id || "unknown";
const contentType = message.content.type;
const text = contentType === "text" ? message.content.text
: contentType === "markdown" ? message.content.markdown
: JSON.stringify(message.content);

console.log(`📩 iMessage from ${senderId}: ${text}`);

// 關鍵一行:用 hermes -z 獲取 AI 回覆
const hermesReply = await $`hermes -z ${`[iMessage from ${senderId}]: ${text}`}`.text();
const cleanReply = hermesReply.trim();

console.log(`🤖 Hermes replies: ${cleanReply.slice(0, 200)}`);

await message.reply(cleanReply);
});
}

第六步:啟動和維護

啟動 Bot(後臺運行)

1
2
cd /opt/spectrum-bot
bun run index.ts &

建議用 Hermes Agent 的 cron 或 process 管理來保持長期運行。

驗證是否正常

發送一條 iMessage 到自己的號碼,觀察 Bot 日誌:

1
2
📩 iMessage from +852xxxxxxxx: 你好
🤖 Hermes replies: 你好!我是 Hermes Agent,有什麼可以幫你的?

踩坑總結

# 錯誤寫法 正確寫法
1 類型錯誤(Zod v4) 試圖修復 tsc 錯誤 忽略,Bun 能跑
2 Cloudflare 驗證 用服務器瀏覽器註冊 本地瀏覽器手動註冊
3 message.text 直接取 text message.content.text
4 message.from message.from.name message.sender?.id
5 User 無 name message.sender.name 只用 sender.id
6 Hermes 輸出推理過程 hermes chat -q hermes -z

結語

打通 iMessage + AI 的鏈路雖然折騰,但一旦跑通,體驗非常順暢。Photon Spectrum Cloud 解決了 iMessage 橋接最頭痛的「需要 Mac 長期在線」問題,而 Hermes Agent 提供了強大的 AI 處理能力。

後續可以擴展的功能:

  • 多輪對話上下文(用 hermes --resume 保持 session)
  • 指令系統(特定前綴觸發不同技能)
  • 圖片/附件處理

如果你也遇到了類似問題,或者有更好的方案,歡迎交流討論!

背景

大疆 4G 图传模块有两种芯片方案:早期批次使用 移远 EG25-G,后期批次换用了 百望 QDC507。两种模块的默认 USB VID:PID 都是大疆私有的 2ca3:4006,通用 Linux 驱动无法直接识别。

VoHive 平台原生支持 Quectel 系列模块(VID:PID 2c7c:0125),通过 AT 命令改写 USB 身份后,百望模块也能无缝接入。

本文记录百望 QDC507 芯片模块的 VID:PID 改写过程与踩坑记录。移远 EG25 的改写方法可参考 之前的文章

硬件信息

项目
芯片 百望 QDC507GLEFM21
接口 USB Type-C
默认 VID:PID 2ca3:4006 (DJI Technology)
目标 VID:PID 2c7c:0125 (Quectel EC25)
操作环境 Ubuntu 24.04.4 LTS, Kernel 6.8.0

操作步骤

第一步:加载驱动并绑定设备

1
2
3
4
5
6
# 加载 usb-serial 和 option 驱动
sudo modprobe usbserial
sudo modprobe option

# 将 DJI 的 VID:PID 注册到 option 驱动
echo "2ca3 4006" | sudo tee /sys/bus/usb-serial/drivers/option1/new_id

此时系统会生成 /dev/ttyUSB0 ~ /dev/ttyUSB4 串口设备。

第二步:发送 AT 命令改写 USB 身份

1
2
3
4
5
# 写入新 VID:PID(永久生效,存入 NVRAM)
echo 'AT+QCFG="usbcfg",0x2C7C,0x0125,1,1,1,1,1,0,0' | sudo socat -t 3 - /dev/ttyUSB2,b115200,crnl

# 重启模块使更改生效
echo 'AT+CFUN=1,1' | sudo socat -t 3 - /dev/ttyUSB2,b115200,crnl

两个命令都应返回 OK

第三步:验证改写结果

1
2
3
# 等待 5 秒后查看
lsusb | grep 2c7c
# 应显示: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem

踩坑记录

坑1:socat 参数必须用 crnl

最初我用的参数是 raw,echo=0

1
2
3
4
# ❌ 无效 — AT 命令无响应
sudo socat - /dev/ttyUSB2,b115200,raw,echo=0 <<'EOF'
AT+QCFG="usbcfg",0x2C7C,0x0125,1,1,1,1,1,0,0
EOF

百望 QDC507 对终端模式有要求,必须使用 crnl 参数(自动处理 CRLF 换行):

1
2
# ✅ 正确
echo 'AT+QCFG="usbcfg",0x2C7C,0x0125,1,1,1,1,1,0,0' | sudo socat -t 3 - /dev/ttyUSB2,b115200,crnl

坑2:AT 查询走 QMI 通道

百望 QDC507 与移远 EG25 的一个区别是:标准串口上的 AT 命令查询全部返回 ERROR。百望芯片将 AT 查询路由到了 QMI 通道,而非传统的 /dev/ttyUSB* 串口。

这意味着:

  • 写入命令(如 AT+QCFG 改写 VID:PID)在 /dev/ttyUSB2 上有效
  • 查询命令(如 AT+CGSN 查 IMEI)在串口上无效,需通过 QMI 协议读取

VoHive 走的是 QMI 通道,所以不受影响——设备注册、短信、网络状态等功能全部正常。

坑3:qmi_wwan 驱动未自动绑定

改写后模块重新枚举为 2c7c:0125,但 qmi_wwan 驱动可能没有自动绑定到网卡接口。需要手动注入:

1
echo "2c7c 0125" | sudo tee /sys/bus/usb/drivers/qmi_wwan/new_id

绑定成功后会看到 /dev/cdc-wdm0 设备。

VoHive 配置

VoHive 检测到新设备后,在 Web UI 添加即可。配置中 modem_type 保持 quecteldevice_backend 使用 qmi

VoHive 日志确认:

1
2
QMI: modem 支持 27 个 QMI 服务
[baiwang] 收到新短信通知 (QMI)

总结

芯片 socat 参数 AT 查询 QMI 兼容 VoHive 可用
移远 EG25-G crnlraw,echo=0 ✅ 正常 ✅ 原生
百望 QDC507 必须 crnl ❌ 走 QMI 通道 ✅ 兼容

两种芯片改写 VID:PID 的核心步骤相同,只是百望对 socat 终端参数更敏感。改写后永久生效,下次插入任何 Linux 设备都会直接识别为 Quectel EC25。

大疆 1 代 4G 模块本质是移远 Quectel EG25-G 公版模组,只是 USB VID/PID 被写成了大疆私有值。VoHive 平台只认标准 EC25 身份,不改就用不了。本文记录完整的改写和部署过程,包括踩过的坑。

背景

手头有一个大疆 1 代 4G 模块(Type-C 口),想用来跑 VoHive 平台——一个面向高通 4G/LTE 模组的综合管理与代理服务平台。

但大疆给这个模块写了一个私有的 USB 身份标识(VID:PID = 2ca3:4006),而 VoHive 只认标准的 Quectel EC25 (2c7c:0125)。插上 Linux 后虽然能识别,但 VoHive 不会搭理它。

解决方案: 通过 AT 命令把 USB 身份永久改写为标准 EC25,然后部署 VoHive 的 Docker 版。

VoHive 能做什么?

VoHive 由 Go 后端(Gin + GORM + SQLite)和 Vue 3 前端组成,把 4G 模组的管理能力打包成一个开箱即用的 Web 服务。以下是它的核心能力:

📡 多模组并发管理

  • USB 热插拔自动发现,多设备实时状态监控
  • 支持 Quectel EC20/EC25/EC21/EG25/EM20 等主流高通模组
  • 同时管理多张 SIM 卡 / eSIM,互不干扰

🌐 轻量级代理引擎

  • 内建 SOCKS5 / HTTP 代理,每个模组可独立开一个代理实例
  • 基于 SO_BINDTODEVICE 严格绑定出站流量到指定网卡
  • 典型场景:一张卡一个代理 IP,组成私有移动代理池

💬 短信收发中心

  • Web 界面统一收发短信,支持会话和联系人管理
  • 历史短信自动落库(SQLite),可搜索可导出
  • USSD 交互(查询余额、套餐等)
  • 实用场景:多卡接码、验证码统一管理

📱 eSIM 全生命周期管理

  • 通过 AT 指令通道直接管理 eSIM 芯片
  • Profile 下载、启用、停用、重命名、删除
  • 配合多 eSIM 卡,无需插拔物理卡即可切换运营商

🔔 多渠道通知推送

  • 重要短信和系统告警可推送至:
    • TelegramEmailPushPlusBark飞书QQ
  • 不漏掉任何关键短信

📞 VoWiFi (IMS 通话)

  • 通过宽带网络隧道建立 IMS 连接
  • 地下室、弱覆盖场景下保证通话不掉线(本文暂未启用)

🏗️ 多架构支持

  • 原生编译 amd64 / arm64 / armv7
  • 可在路由器、树莓派、小主机上跑,部署灵活

VoHive 的 License 是 PolyForm Noncommercial 1.0.0,个人学习研究免费,商用需联系作者。

第一步:硬件识别与驱动加载

模块插到 Linux 机器上后,第一步是加载 USB 串口驱动:

1
2
sudo modprobe usbserial
sudo modprobe option

然后注入大疆的 VID/PID,让 option 驱动绑定这个设备:

1
echo "2ca3 4006" | sudo tee /sys/bus/usb-serial/drivers/option1/new_id

绑定成功后,/dev/ttyUSB0 ~ /dev/ttyUSB3 四个串口设备出现。其中 /dev/ttyUSB2 是 AT 命令通道。

⚠️ 注意:模块需要插入 SIM 卡才能正常枚举 USB,无 SIM 卡只亮红灯、不出现 ttyUSB 设备。

第二步:USB 身份改写(关键)

使用 socat 向模块发送 AT 命令,将 VID/PID 永久写入 NVRAM:

1
2
3
4
sudo socat - /dev/ttyUSB2,b115200,raw,echo=0,crnl <<'EOF'
AT+QCFG="usbcfg",2c7c,0125,0,0,8100,40E4,6300
AT+CFUN=1,1
EOF

参数解析:

  • 2c7c,0125 — 目标 VID:PID,即 Quectel EC25
  • 8100,40E4,6300 — 其他配置参数(厂商保留字段)

AT+CFUN=1,1 触发模块软复位。约 10 秒后模块重新枚举,lsusb 显示:

1
ID 2c7c:0125  Quectel Wireless Solutions Co., Ltd. 

改写成功!以后这模块插任何 Linux 机器都直接认成 EC25,无需重复操作。

踩坑 1:AT 命令语法

第一次发送 AT+QCFG 时返回 ERROR,经排查是 socat 需要 crnl 标志\n 转为 \r\n,否则模块不认识换行符。

踩坑 2:云内核没有 option 驱动

踩了个大坑——Docker VM 跑的 cloud kernel (linux-image-cloud-amd64) 不包含 usb-serialoption 驱动。lsusb 能看到设备,但 /dev/ttyUSB* 一个都没有。

解决: 切换到 Debian 标准内核:

1
2
3
4
5
6
7
# 查看 grub 菜单项
grep menuentry /boot/grub/grub.cfg

# 切换到标准内核 6.1.0-50-amd64
sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT="1>2"/' /etc/default/grub
update-grub
reboot

Debian 12 在 ESXi VM 上 grub-reboot 不生效,必须直接改 /etc/default/grub

第三步:VoHive 平台部署

准备配置目录

1
mkdir -p /opt/vohive/{config,data,logs}

创建配置文件

首次部署必须提供配置文件,否则容器反复重启。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server:
debug: false
port: 7575

web:
username: admin
password: admin

devices:
- name: DJI-4G
port: /dev/ttyUSB2
modem_type: quectel

vowifi:
enabled: false

webhook:
enabled: false

Docker Compose 部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
vohive:
image: iniwex/vohive:latest
container_name: vohive
restart: unless-stopped
network_mode: "host"
privileged: true
volumes:
- ./config:/app/config
- ./data:/app/data
- ./logs:/app/logs
- /dev:/dev
environment:
- TZ=Asia/Shanghai

关键点:

  • network_mode: "host" — 模块通过 AT 串口通信,不需要端口映射,host 模式最直接
  • privileged: true — 访问 /dev/ttyUSB* 需要特权模式
  • 挂载 /dev — 让容器内能访问串口设备

启动:

1
2
3
cd /opt/vohive
docker compose -f docker-compose.custom.yml pull
docker compose -f docker-compose.custom.yml up -d

验证

1
2
3
4
curl -s -o /dev/null -w '%{http_code}' http://localhost:7575/
# 返回 200

docker logs vohive | tail -5

VoHive Web Dashboard 访问:http://<服务器IP>:7575,默认账号 admin/admin(首次登录后务必修改密码)。

第四步:SIM 卡状态确认

部署完成后通过 AT 命令查询模块和网络状态:

项目 备注
模块型号 Quectel QDC507 (EG25-G) 硬件版本
固件版本 QDC507GLEFM21
SIM 状态 READY ✅ 已识别
运营商 中国电信 (460/11) LTE FDD
网络注册 已注册 GPRS+EPS 双附着
APN CTNET 电信默认
IP 地址 10.40.xxx.xxx PPP 内网 IP
CSQ 信号强度 28/31 ✅ 良好
RSRP -87 dBm 🟡 中等
DNS xxx.xxx.xxx.xxx / xxx.xxx.xxx.xxx 电信 DNS

附录:关于原作者删库

就在部署完成不久后,VoHive 原作者 iniwex5 宣布「无限期停止维护」,清空了源码仓库。vohive-release 仓库(含预编译二进制)仍公开,但需注意后续独立部署的可能性。

建议做法:

  • Fork 备份:将关键仓库 fork 到自己的 GitHub,确保后续可用
  • 保留 Docker Hub 镜像iniwex/vohive:latest 是现成的,优先使用
  • 社区备份hzlmy2002/vohive-collection 备份了完整源码 + 所有 Go 依赖(netlink、qqbot、euicc-go、quectel-qmi-go 等)

总结

整个过程不算复杂,但有几个关键注意点:

  1. USB 身份改写一次,永久生效 — 以后再也不用管了
  2. ⚠️ 必须用标准内核 — cloud kernel 没有 usb-serial 驱动
  3. 🔑 crnl 参数 — socat 发 AT 命令必须加,否则 ERROR
  4. 🐳 Docker host 网络 + privileged — 串口设备访问必备
  5. 📡 模块需要 SIM 卡才能正常枚举 — 无 SIM 只亮红灯

VoHive 的 Web 界面可以发短信、管理 eSIM、开代理、接推送通知,作为 4G 模块的管理平台非常实用。下一步可以探索它的 VoWiFi 和代理池功能。

在 AI 大模型的时代,”数据隐私”和”响应速度”越来越成为关注点。与其把敏感信息发送到云端 API,不如在自家局域网里跑一个本地模型。

本文记录我在 ai-server 上部署 Qwen 3.6 27B 的全过程 —— 从硬件选型、ROCm 环境搭建、llama.cpp 编译,到 systemd 守护和性能调优。希望给同样想在消费级 AMD 显卡上跑大模型的朋友一些参考。

🛠 一、硬件清单

组件 规格
主板 Gigabyte B460M AORUS ELITE(PCIe 3.0 x16)
CPU Intel Core i5-10400F(6 核 12 线程,2.9~4.3GHz)
GPU AMD Radeon RX 7900 XTX 24GB(蓝宝石 PULSE)
内存 24GB DDR4-2400(计划升级到 128GB)
系统盘 171GB SSD(可用 103GB)
系统 Ubuntu 24.04.4 LTS,Kernel 6.8.0-124
网络 无线 wlp5s0,内网环境

为什么选 AMD 显卡?

RX 7900 XTX 拥有 24GB GDDR6 显存。在消费级显卡里,24GB 这个价位段的选择并不多 —— NVIDIA 这边要 RTX 4090 才能达到 24GB,而 AMD 的 7900 XTX 价格更友好,性价比明显。配合 ROCm 7 的日益成熟,在消费级 AMD GPU 上跑 LLM 已经是一条完全可行的路。

⚠️ 注意: B460 主板的 PCIe 3.0 x16 带宽约为 16 GB/s,而 GDDR6 显存带宽超过 600 GB/s,两者相差 40 倍。这意味着当 KV cache 溢出到系统内存时,PCIe 带宽会成为非常明显的瓶颈。如果你要装机,建议至少选 PCIe 4.0 的主板。

🐳 二、ROCm 环境搭建

ROCm 是 AMD 的 GPU 计算平台,类似于 NVIDIA 的 CUDA。在 Ubuntu 24.04 上安装 ROCm 比想象中要顺利。

安装步骤

Ubuntu 24.04 的官方源已经包含了 ROCm 7 系列的软件包,直接通过 apt 安装即可:

1
2
3
# 添加 ROCm 仓库并安装
sudo apt update
sudo apt install rocm-hip-libraries rocm-device-libs rocm-smi-lib

安装完成后,确认 ROCm 版本:

1
2
3
# 查看 ROCm 信息
rocm-smi
hipcc --version

输出结果:

1
2
HIP version: 7.2.53211-97f5574fe2
AMD clang version 22.0.0git
1
2
Device  Node  IDs              Temp    Power  Partitions          SCLK  MCLK    Fan    Perf  PwrCap  VRAM%  GPU%
0 1 0x744c, 5113 67.0°C 61.0W N/A, N/A, 0 0Mhz 772Mhz 60.0% auto 303.0W 86% 0%

GPU 被正确识别为 gfx1100(Navi 31 架构),ROCm 运行正常。

安装过程中的注意点

内核模块amdgpu 内核模块是 Ubuntu 24.04 自带的,安装完 ROCm 后会自动加载:

1
2
3
lsmod | grep amd
# amdgpu 17166336 3
# amdxcp 12288 1 amdgpu

GPU 目标架构:RX 7900 XTX 对应的是 gfx1100。编译 llama.cpp 时需要指定这个目标,否则 GPU 加速无法生效。如果你的显卡型号不同,可以在 AMD GPU 列表 中查到对应的 gfx 代号。

用户权限:确保运行推理服务的用户在 video 用户组中,这样才有权限访问 GPU 设备:

1
sudo usermod -aG video elric

🔨 三、编译 llama.cpp

llama.cpp 是一个用纯 C/C++ 编写的 LLM 推理框架,支持 GGUF 格式的模型文件,对 AMD GPU 通过 ROCm/HIP 提供了良好的支持。

源码克隆与构建

1
2
3
4
5
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
mkdir build && cd build
cmake .. -DGGML_HIP=ON -DGPU_BUILD_TARGETS=gfx1100 -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

关键构建参数说明

参数 说明
-DGGML_HIP=ON 启用 HIP 后端,让 AMD GPU 加速生效
-DGPU_BUILD_TARGETS=gfx1100 指定 GPU 目标架构为 Navi 31(RX 7900 XTX)
-DCMAKE_BUILD_TYPE=Release Release 模式编译,性能更好

构建结果确认

编译完成后,可以通过 cmake -LH .. 查看配置摘要,确认关键项:

1
2
3
4
5
GGML_HIP:BOOL=ON
GGML_HIP_GRAPHS:BOOL=ON
GGML_HIP_MMQ_MFMA:BOOL=ON
GPU_BUILD_TARGETS:STRING=gfx1100
CMAKE_BUILD_TYPE:STRING=Release
  • GGML_HIP_GRAPHS=ON 表示 GPU 计算图优化已启用,可以提升推理效率
  • GGML_HIP_MMQ_MFMA=ON 表示使用了 AMD 的矩阵乘法加速指令
  • GGML_AVXGGML_AVX2GGML_AVX512 全部为 OFF —— 因为 GPU 承担了主要计算,CPU 指令集优化的收益不大

经验之谈: 编译时间取决于 CPU 核心数。i5-10400F(6 核)大约需要 15-20 分钟。如果用的是更多核心的 CPU,可以进一步缩短。

📦 四、模型选择

模型是本次部署的核心选择。我选用了 Qwen 3.6 27Babliterated 版本:

1
2
3
模型文件: huihui-qwen3.6-27b-abliterated-q4_k_m.gguf
大小: 16.5GB
量化: Q4_K_M(4-bit 混合精度)

为什么是 abliterated 版本?

abliterated(去拒绝化)版本是通过 OBLITERATUS 工具处理过的模型。它去除了模型的安全拒绝机制,让输出更加自由灵活。

对于本地私有部署来说,这个特性非常实用:

  • 不会无缘无故拒绝回答问题 —— 云端模型经常因为安全策略拒绝回答一些完全正常的问题,本地部署的 abliterated 版本则直接给出答案
  • 输出更直接 —— 不需要绕过安全过滤,回答更自然
  • 更适合个人使用和开发调试 —— 没有安全层的干扰,方便测试和迭代

为什么选 Qwen 3.6 27B?

27B 参数规模是一个甜蜜点 —— 比 7B/8B 强一个档次,同时 24GB 显存用 Q4_K_M 量化(约 16.5GB)后可以装下,还留有显存给 KV cache 和系统开销。

如果你显存更大(48GB+),可以考虑 Qwen 3.6 更大参数的版本。如果显存更小(12GB 左右),7B/8B 的模型会更合适。

⚙️ 五、systemd 守护进程

为了让模型服务持续运行,配置了 systemd 服务。这样即使 SSH 断开,服务也不会停止。

服务文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# /etc/systemd/system/llama.service
[Unit]
Description=Llama CPP Server with ROCm Acceleration (64K + Continuous Batching)
After=network.target

[Service]
Type=simple
User=elric
ExecStart=/home/elric/llama.cpp/build/bin/llama-server \
-m /home/elric/llama.cpp/models/huihui-qwen3.6-27b-abliterated-q4_k_m.gguf \
--alias qwen3.6-27b \
--host 0.0.0.0 \
--port 1234 \
-ngl 99 \
--flash-attn on \
-np 1 \
-b 4096 \
-ub 1024 \
--ctx-size 65536 \
-ctk q8_0 \
-ctv q8_0 \
--threads 6 \
--jinja
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

然后启用服务:

1
2
sudo systemctl enable llama.service
sudo systemctl start llama.service

启动参数详解

参数 说明
-ngl 99 将所有层 offload 到 GPU,CPU 只做调度和采样
--flash-attn on 开启 FlashAttention,大幅加速注意力计算
-b 4096 批次大小,更大的批次提升 GPU 利用率
-ub 1024 微批次大小,影响单次计算粒度
--ctx-size 65536 上下文窗口 64K tokens
-ctk / -ctv q8_0 KV cache key/value 量化为 q8_0
--threads 6 CPU 线程数(与 i5-10400F 核数匹配)
--jinja 启用 Jinja 模板,支持 ChatML 等模板格式

显存预算:为什么是 q8_0 + 64K?

这部分值得多花点篇幅,因为这是整个配置最关键的决策。

KV cache 存储了对话历史中的注意力信息。它越大,能记住的上下文就越长,但也越占显存。量化策略需要在精度和显存之间做权衡。

24GB 显存的账本:

项目 q8_0 + 64K ✅ q8_0 + 128K ❌ q4_0 + 128K ✅
模型权重(Q4_K_M) ~16.5 GB ~16.5 GB ~16.5 GB
KV cache(最大) ~3.8 GB ~7.5 GB ~3.8 GB
ROCm 运行时 + 框架 ~1-2 GB ~1-2 GB ~1-2 GB
合计 ~21-22 GB ~25-26 GB ~21-22 GB
结果 ✅ 安全 ❌ 溢出到系统内存 ✅ 安全

q8_0 + 128K 会溢出 24GB 显存。 之前配置就是这样,VRAM 占用达到 86%,KV cache 溢出走 PCIe 3.0(仅 16 GB/s),生成速度直接从 25 t/s 掉到 10 t/s 以下。

最终方案:q8_0 + 64K

  • ✅ 显存安全(~22 GB,留了 ~2 GB 余量)
  • ✅ q8_0 高精度 KV cache,长对话不丢失上下文精度
  • ✅ 64K 上下文对日常使用完全够用(约 4-5 万汉字)
  • ✅ 速度稳定在 ~25 t/s,不波动

如果你选择 q4_0 KV cache: 每个 token 只需约 32KB,128K 上下文占用约 3.8GB,显存压力更小。适合想要更大上下文窗口的情况。

q8_0 的优势: 精度更高,长对话中缓存命中率更好,减少不必要的重算。实测下来,在显存够用的前提下,q8_0 带来的稳定性提升是值得的。

📊 六、性能实测

以下是实际运行中的数据,全部从服务日志直接抓取(journalctl -u llama.service):

生成速度(Decoding)

场景 速度 延迟
持续长生成(800+ tokens) ~25 tokens/s ~40ms/token
短对话(KV 缓存命中) ~25 tokens/s ~40ms/token
长对话(KV 缓存未命中) ~24.6-24.8 t/s ~40.5ms/token

~25 tokens/s 的持续生成速度意味着一段 200 词的英文回复大约需要 8 秒完成,完全满足实时对话的需求。

Prompt 处理速度(Prefill)

Prompt 长度 速度 延迟
~1000 tokens(典型对话) ~428 tokens/s ~2.3ms/token

FlashAttention 的加速效果非常明显。

系统资源

指标 数值
GPU 显存占用 ~76%(约 18.2GB / 24GB)
GPU 温度 42°C(待机),63°C(负载)
GPU 功耗 88W(空闲) / ~300W(峰值)
服务运行时间 持续运行,稳定无故障
日志错误 0 条

💡 七、调优心得

1. 显存预算是第一要务

最开始用了 q8_0 + 128K 上下文,显存压到 86%,KV cache 溢出走 PCIe 3.0,速度直接腰斩。将 --ctx-size 降到 64K 后,显存降到 ~76%,速度稳定在 25 t/s,问题彻底解决。

教训: 24GB 显存不是无限的,q8_0 精度虽好,但 128K KV cache 会吃掉 7.5GB,加上 16.5GB 模型就 24GB+,一定会溢出。先算账,再调参。

2. PCIe 3.0 是隐形的瓶颈

B460 主板的 PCIe 3.0 带宽只有 ~16 GB/s。当显存不足、KV cache 被 offload 到系统内存时,每次 token 生成都要通过 PCIe 总线搬运数据,延迟显著增加。

实际体验: 当 KV cache 溢出到 CPU 内存时,生成速度能从 25 t/s 掉到 10 t/s 以下。确保 KV cache 完全留在显存里是提升性能的第一要务。

如果你要装机: 尽量选 PCIe 4.0 以上的主板。PCIe 3.0 在显存溢出时拖累严重。

3. 批次参数影响很大

-b 从 2048 提升到 4096、-ub 从 512 提升到 1024 后,GPU 利用率更高,生成速度从 ~21 tokens/s 提升到了 ~25 tokens/s。更大的批次意味着 GPU 的计算单元能更好地并行工作,减少等待。

建议: 如果你的显卡显存充裕,可以把 -b 设得更大(8192),看看效果。

4. KV cache 量化策略

早期配置使用 q4_0 KV cache,后来调整为 q8_0。虽然显存占用从 ~65% 上升到了 ~76%,但长对话场景下的生成速度更加稳定。原因是 KV cache 精度更高,减少了缓存失效带来的重算 —— 每次不用重新处理之前的上下文。

结论: 在显存预算内,优先给 KV cache 更高的量化精度。但前提是 总显存不溢出 —— 如果 q8_0 会溢出,那就果断用 q4_0。

5. 16GB 内存偏紧

系统原只有 16GB 内存,llama 进程本身就要占用约 6GB。加上系统和后台进程,可用内存比较紧张。在高负载时,系统会用到 Swap,影响响应速度。

已升级到 24GB,计划最终升级到 128GB M.2,不仅给 llama.cpp 更多余量,还能彻底解决内存瓶颈。

🔗 八、接入 Hermes Agent

部署完成后,模型通过 OpenAI 兼容 API 提供服务。Hermes Agent 通过自定义 provider 连接到本地端点:

1
http://localhost:1234/v1

这意味着:

  • 数据不出局域网 —— 所有对话内容完全私有
  • 无 API 调用费用 —— 一次部署,长期使用
  • 低延迟 —— 局域网内响应,没有公网往返

我的日常使用场景是:通过 Telegram 发消息给 Hermes,Hermes 调本地模型推理,整个流程在局域网内完成。写文章、查资料、调试代码……完全不需要把数据送到云端。

📝 九、总结

在消费级硬件上部署 27B 参数的本地大模型是完全可行的。RX 7900 XTX 的 24GB 显存是一个甜蜜点,配合 ROCm 7 和 llama.cpp,可以实现稳定的推理服务。

核心经验:

  1. 显存预算是硬约束 —— 24GB 要精确计算:模型 + KV cache + ROCm 开销,超出就会溢出
  2. q8_0 + 64K 是 24GB 显存的甜点配置 —— 高精度 KV cache + 安全显存余量 + 稳定速度
  3. PCIe 带宽不容忽视 —— 尽量让数据留在显存内,装机时选 PCIe 4.0 主板
  4. abliterated 版本更适合本地私有部署 —— 没有安全层的干扰,输出更自由
  5. systemd 守护 + OpenAI API 兼容 = 即插即用的服务 —— 任何支持 OpenAI API 的客户端都能直接接入

下一步: 内存升级到 128GB M.2,移除 Windows 11,让这台机器纯粹为 AI 推理服务。


本文中的性能数据来自 2026 年 7 月的实际运行日志,测试环境为局域网内部。llama.cpp 版本为 v9873(commit a4107133a)。

背景:为什么在有了 Telegram 后还需要 Matrix?

在使用 AI 助理(OpenClaw)的过程中,我最初主要依赖 Telegram 进行交互。但由于网络波动和节点稳定性问题,Telegram 偶尔会出现指令断连或响应延迟。为了建立更稳健的通讯冗余,我部署了私有化的 Matrix (Synapse) 服务。

为了确保与 AI 助理对话的绝对私密性,开启 端到端加密 (E2EE) 是必不可少的一步。以下是基于 OpenClaw 与 Synapse 的实战配置流程。

1. Matrix 的核心优势

  • 自托管控制:所有聊天记录存储在自己的服务器上。
  • 高可用性:作为 Telegram 的互补通道,即使公网代理波动,通过隧道加密的 Matrix 依然能保持高可用。
  • 安全性:原生支持端到端加密,确保只有发送者和接收者(你和 AI)能解密消息。

2. 开启步骤

2.1 修改 OpenClaw 配置

在 OpenClaw 的 openclaw.json 配置文件中,找到 channels.matrix 部分,添加 "encryption": true 配置项。

1
2
3
4
5
6
7
8
9
10
11
{
"channels": {
"matrix": {
"enabled": true,
"provider": "matrix",
"homeserverUrl": "https://matrix.yourdomain.com",
"accessToken": "your_access_token",
"encryption": true // 关键配置:开启加密
}
}
}

2.2 应用配置与重启

修改完成后,需要重启 OpenClaw 以加载新的加密模块。

1
2
# 执行热重启 (SIGUSR1)
openclaw gateway restart

3. 关键:设备验证 (Manual Verification)

开启加密后,你的 Matrix 客户端(如 Element)会提示「未经验证的设备」。这是 E2EE 的核心机制——你需要手动信任 AI 助理这个「新设备」。

  • 操作提示:在 Element 中打开与助理的私聊窗口,点击助理的头像进入个人信息,选择「验证 (Verify)」。
  • 完成握手:按照提示完成对比图表或确认,一旦显示绿色小盾牌,即表示加密链路正式建立。

4. 推荐客户端 (Multi-platform Clients)

为了获得最佳的 E2EE 体验,建议选择对加密支持完善的客户端:

  1. Element X (iOS / Android) —— 强烈推荐

    • 官方最新旗舰版,底层使用 Rust 重新编写。响应极快,UI 更加现代化。针对 E2EE 进行了大幅优化,验证流程更顺滑。
  2. Cinny (Web / Desktop)

    • 极简主义风格,非常轻量。如果你喜欢类似 Slack 或 Discord 的多频道布局,Cinny 是最佳选择。
  3. SchildiChat (Android / Desktop)

    • 基于 Element 修改的社区版,结合了 Element 的功能和更传统的即时通讯布局(如气泡对话框)。
  4. FluffyChat (Linux / Android / iOS / Web)

    • 界面非常可爱、清新,操作门槛极低,跨平台一致性好。

5. 常见问题:联邦路由

如果你的助理需要跨服务器通讯(联邦),请确保通过 Cloudflare Tunnel 或反代正确暴露了 /.well-known/matrix/server 接口,否则加密握手包可能会在联邦链路上解析失败。


总结

通过 Matrix + E2EE 的组合,不仅解决了 Telegram 在特殊网络环境下的连通性痛点,还实现了金融级的对话隐私保护。现在,我可以放心地在任何网络环境下调教我的助理了。


本文由 Elric 的 不太聪明智能助理「小龍蝦 🦞」协助整理与发布。

在长期将 RouterOS 运行在 ESXi 8.0 虚拟机后,笔者最近终于入手了实体“神机”—— MikroTik RB5009UG+S+。实体硬件带来的 L3 硬件加速(HW Offloading)与 10G SFP+ 扩展性是虚拟环境无法比拟的。本文将从迁移背景、基础拨号、进阶分流到 RustDesk 深度优化,全面记录这台设备的配置精华。

阅读全文 »
0%