OpenHanako 云端化实录:frp 内网穿透 + 任务代理 + WebDAV,附踩坑速查表

作者:燃烧的箫
日期:2026-08-03
环境:Windows Server 云主机(2C2G)+ 开发机(Windows,RTX3060)+ 鸿蒙手机

你将得到什么

读完这篇文章,你将收获:

  • 一台 7×24 在线的私人 AI 助手(OpenHanako 部署在云主机,记忆私有)
  • 一条 加密隧道(frp stcp),让公司、家里、手机三端安全访问
  • 一个 手机能浏览的文件服务(WebDAV,工作台像网盘一样随时看)
  • 十几个真金白银换来的坑(cmd 批处理、鸿蒙保活、Caddy 版本……)

全套折腾下来约一个周末。内容基于真实搭建经历,每一步都可复现。

一、为什么需要"云端 AI 调度中枢"

如果你手里有一台吃灰的云主机(比如我,2 核 2G 两年期),又日常重度使用 AI 助手,这篇文章可能对你有用。

我的诉求很简单:无论在公司还是家里,都能随时跟我的 AI 助手对话,并且它能帮我在不同网络环境里干活。

  • 在公司:AI 助手要能触达公司内网资源、调用开发机的 GPU
  • 在家里:躺床上用手机就能跟同一个 AI 助手聊,记忆无缝衔接
  • 核心矛盾:AI 助手跑在哪?记忆怎么统一?

答案是:把 AI 助手搬到云主机上,作为唯一驻地;开发机和手机都通过隧道连它。

二、基石:OpenHanako 简介

OpenHanako(项目名 HanaAgent)是一个开源的个人 AI Agent,Apache 2.0 协议,GitHub 5.7k+ stars,支持 macOS / Windows / Linux。

它和 ChatGPT 网页版最大的区别:

特性 说明
记忆 长期记忆 + 细节记忆,记得你说过的事
人格 人格自定义,可自由塑造(每个 Agent 独立)
工具 读写文件、执行命令、浏览网页、搜索、截图,操作你的电脑
技能 兼容 Skills 生态,可自主学习新技能
多 Agent 创建多个 Agent,各有独立记忆和人格,可协作
多平台接入 同一个 Agent 可接入 Telegram / 飞书 / QQ / 微信
移动端 PWA Server 托管 /mobile/ PWA,手机浏览器直接访问
桌面远程端 另一台桌面端可通过 LAN URL + access key 连接同一 Server
数据私有 所有数据存在自己的机器上(~/.hanako),不上传第三方

关键能力:OpenHanako 采用 Server 架构,Agent 引擎跑在 Server 所在机器,各种前端(桌面端、PWA、远程桌面端)都只是 UI。这意味着:

把 Server 放在云主机上 = Agent 就在云端,记忆天然统一。

(注意:正因为引擎在 Server 侧,开发机连上云主机后,执行命令跑在云主机而非开发机——这个后面会详细说,它是整个架构设计的转折点。)

三、架构总览

手机(家里)

开发机(公司)

云主机(Agent 唯一驻地)

stcp 隧道

stcp 隧道

OpenHanako Server
记忆+引擎+工作台

frps 隧道服务端 :7000

云主机 frpc
stcp 服务端 + 访客端

Caddy WebDAV :8080

frpc 客户端

任务代理服务 :9000

frp-Android

若 mermaid 图未渲染,以上方文字拓扑为准。stcp 链路实际是各端 frpc 主动连 frps,再由云主机上的 frpc(同时扮演 stcp 服务端与访客端)转发到本地 HA / Caddy,并经访客端反向取开发机上的任务代理服务。

  • 云主机:OpenHanako Server(Agent 唯一驻地)+ frps(隧道服务端)+ Caddy(WebDAV 文件服务)
  • 开发机:frpc 客户端 + 任务代理服务(FastAPI,供云主机远程调用执行重活)
  • 手机:frp-Android 客户端,PWA 访问

四、分步教程

第一步:云主机部署 OpenHanako

  1. 在云主机下载 OpenHanako Windows 版安装包,正常安装
  2. 首次启动配置:语言、名字、模型供应商(OpenAI 兼容 API key + Base URL)、三个模型
  3. 开启局域网访问:设置 → 访问与设备 → 局域网访问 → 开启
  4. 记录访问地址:
    • 手机端:http://IP:端口/mobile
    • 电脑端:http://IP:端口/desktop

验证:本机浏览器打开 http://127.0.0.1:端口/desktop 能出界面即部署成功。

部署提示:首次安装需要图形界面(配置向导、开启局域网访问)。如果公司网络封了 3389(RDP),用云厂商的网页版 VNC 控制台完成部署,日常访问再走 frp 隧道。

第二步:打通 frp 隧道(核心)

为什么用 frp? 直接公网访问 http://IP:端口/mobile/ 时,公司网络会掐掉 WebSocket 长连接(页面能开但一直转圈,判定为上网行为管理系统对明文 HTTP/WS 的干扰)。而 frp 走加密二进制协议,公司网络放行。

frp(Fast Reverse Proxy) 是成熟的内网穿透工具,我们用 stcp(secret tcp)模式——端口不暴露公网,靠预共享密钥匹配,安全。请使用 0.69.1 或更新稳定版(当前最新 v0.70.1)。

2.1 云主机:frps 服务端

下载 frp 到云主机 C:\frp_0.69.1_windows_amd64,配置 frps.toml

bindPort = 7000
auth.method = "token"
auth.token = "换成你的强随机token"
log.to = "./frps.log"
log.level = "info"
log.maxDays = 7

启动:

frps.exe -c frps.toml

验证frps.log 出现 frps started successfully 即成功。

2.2 云主机:frpc 客户端(暴露 HanaAgent)

云主机再跑一个 frpc,把本机的 OpenHanako 端口注册成 stcp 服务:

frpc.toml

serverAddr = "127.0.0.1"
serverPort = 7000
auth.method = "token"
auth.token = "换成你的强随机token"
loginFailExit = false

[[proxies]]
name = "hana-server"
type = "stcp"
secretKey = "换成你的stcp密钥"
localIP = "127.0.0.1"
localPort = 端口

loginFailExit = false 很重要:开机时网络未就绪,默认 true 会让 frpc 直接退出,加这个参数它会持续重试。

2.3 开发机:frpc 客户端(访问云主机)

开发机 frpc.toml,用 visitor 访问云主机的 hana-server:

serverAddr = "云主机公网IP"
serverPort = 7000
auth.method = "token"
auth.token = "换成你的强随机token"
loginFailExit = false

[[visitors]]
name = "hana-visitor"
type = "stcp"
secretKey = "换成你的stcp密钥"
serverName = "hana-server"
bindAddr = "127.0.0.1"
bindPort = 端口

验证:开发机浏览器打开 http://127.0.0.1:端口/mobile/,能出登录页即隧道通了。

2.4 手机:frp-Android

手机装 frp-Android(frpc 客户端),同样配置 stcp visitor 访问 hana-server。我的手机是鸿蒙 4.2(兼容安卓 APK),安装 arm64 版。

版本兼容性:frp 从 0.52 起才支持 TOML 配置。确认 frp-Android 内置内核 ≥ 0.52(应用内可查看),否则 TOML 配置不生效。当前 frp-Android(AceDroidX 版)构建时默认拉取最新 frp 内核,一般没问题。同样建议配置 loginFailExit = false,应对开机时网络未就绪。

frp-Android 没有配置文件,在 GUI 里新建代理:

  1. 新建配置 → 类型选 stcp visitor
  2. serverName 填 hana-server(与云主机 proxy 名一致)
  3. secretKey 填与云主机一致的 stcp 密钥
  4. bindPort 填与桌面端 visitor 相同的端口(如 38084)
  5. 保存并启动

验证:手机浏览器打开 http://127.0.0.1:bindPort/mobile/,能出登录页即隧道通了。

第三步:记忆全量迁移

开发机积累了几年记忆(会话、长期记忆、置顶记忆),要整体搬到云主机。分步做:

  1. 打包:开发机压缩 ~/.hanako(即 C:\Users\<用户名>\.hanako)整个目录(我的是 4.5GB,压缩后 1.8GB)
  2. 起 HTTP 服务:开发机执行 python -m http.server 8888(起在打包文件所在目录)
  3. 云主机拉取:云主机通过 frp 隧道下载 http://127.0.0.1:7445/hanako.zip

这一步需要一条临时的 frp 隧道(和第四步方向相同:开发机是服务方,云主机是访问方):

开发机 frpc.toml 增加

[[proxies]]
name = "file-transfer"
type = "stcp"
secretKey = "换成传输用stcp密钥"
localIP = "127.0.0.1"
localPort = 8888   # 开发机本地 HTTP 服务端口

云主机 frpc.toml 增加

[[visitors]]
name = "file-transfer-visitor"
type = "stcp"
secretKey = "换成传输用stcp密钥"
serverName = "file-transfer"
bindAddr = "127.0.0.1"
bindPort = 7445   # 云主机本地访问端口,对应 http://127.0.0.1:7445

8888 是开发机起 HTTP 服务的端口,7445 是它在云主机侧映射出的端口,两者通过 stcp 隧道对接。

  1. 覆盖:解压覆盖云主机 ~/.hanako,重启 OpenHanako
  2. 校验:用 Get-FileHash(PowerShell)对比两端压缩包的 SHA256,确保传输完整

安全提醒python -m http.server 监听 0.0.0.0,含全部私密记忆的压缩包会在内网短暂暴露,传输完立即关闭该服务。

清理:迁移完成后,删除开发机和云主机 frpc.toml 里的 file-transfer 相关配置(proxy + visitor),避免遗留不再使用的隧道。

版本一致性:OpenHanako 迭代极快。迁移前把云主机版本升到与开发机一致,覆盖前先备份云主机原始数据目录。

第四步:任务代理服务(让云主机指挥开发机)

关键认知:OpenHanako 引擎在 Server 侧,开发机连上云主机后,执行命令跑在云主机,不是开发机。要让开发机的 GPU 和内网能力被用上,需要任务代理服务

开发机跑一个 FastAPI 服务(Python 3.11,conda 环境),反向通过 frp 暴露给云主机(注意:这一步隧道方向和第二步相反):

开发机 frpc.toml 增加

[[proxies]]
name = "dev-agent"
type = "stcp"
secretKey = "换成任务代理的stcp密钥"
localIP = "127.0.0.1"
localPort = 9000

云主机 frpc.toml 增加

[[visitors]]
name = "dev-agent-visitor"
type = "stcp"
secretKey = "换成任务代理的stcp密钥"
serverName = "dev-agent"
bindAddr = "127.0.0.1"
bindPort = 9000

云主机 frpc 可以同时声明多个 proxy 和 visitor(如 hana-server、dev-agent-visitor,以及第五步将加的 workspace-files),互不冲突。它同时扮演 stcp 服务端(被访问方)和访客端(访问方)双重角色,这是 stcp 架构的关键点。

任务代理接口设计(都是踩过的坑):

云主机 Agent ──frp stcp──> 开发机 FastAPI 服务(127.0.0.1:9000)
   ├── /api/exec         执行命令
   ├── /api/exec/async   异步长任务
   ├── /api/files/*      文件读写
   └── /api/process/*    进程管理

最小骨架(Python 3.11 + FastAPI,重点是统一鉴权):

from fastapi import FastAPI, Depends, Header, HTTPException

app = FastAPI(title="Task Agent")
API_TOKEN = "换成你的API密钥"

def require_auth(authorization: str = Header(None)):
    if not authorization or authorization != f"Bearer {API_TOKEN}":
        raise HTTPException(status_code=401, detail="unauthorized")

@app.post("/api/exec", dependencies=[Depends(require_auth)])
async def exec_cmd(payload: dict):
    import subprocess
    proc = subprocess.run(
        payload["cmd"], shell=True, capture_output=True, text=True, timeout=120,
        creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
    )
    return {"exit_code": proc.returncode, "stdout": proc.stdout[-4000:]}

验证:开发机上 curl.exe -X POST http://127.0.0.1:9000/api/exec -H "Authorization: Bearer 密钥" -d "{\"cmd\":\"hostname\"}",返回开发机主机名即成功。
(注意用 curl.exe 而非 curl:PowerShell 里 curl 是 Invoke-WebRequest 的别名,不认 -X/-d 参数。PowerShell 下推荐用单引号 -d '{"cmd":"hostname"}',cmd 下用双引号并转义 \"

  1. 认证必须统一:用 FastAPI 的 Depends 依赖注入统一鉴权(见上方骨架)。即使经隧道,接口本身也要 API key(防云主机本地被注入的 Agent 或恶意插件直接打 127.0.0.1:9000)

    上方骨架仅演示鉴权与基本执行,生产环境需按坑 2~4 补全超时处理与进程树清理。

  2. 超时杀进程树:Windows 下 subprocess.run(timeout=) 只杀 cmd.exe,孙进程残留。用 CREATE_NEW_PROCESS_GROUP + taskkill /T /F

  3. 并发控制:信号量统一管理,任务完成要清理,否则自锁

  4. 文件编码探测:Windows 上 GBK/UTF-8 混存,读取要自动探测,否则改坏配置文件

  5. 插件热加载 = RCE 通道:LLM 写的插件代码直接加载有风险,必须人工确认

第五步:WebDAV 文件服务(开发机/手机浏览工作台)

OpenHanako 的远程端看不到工作台文件,所以单独搭了一个文件服务,让开发机和手机能像网盘一样浏览工作台。

云主机装 Caddy(单 exe,含 WebDAV 插件):

下载带 webdav 插件的版本:

https://caddyserver.com/api/download?os=windows&arch=amd64&p=github.com%2Fmholt%2Fcaddy-webdav

注意:Windows 下这个 API 通常直接返回可执行文件(MZ 头),下载后改名 caddy.exe 即可用;若拿到的是 zip 包,解压得到 caddy.exe。

Caddyfile

127.0.0.1:8080 {   # 只监听本机,frp 隧道之外多一层纵深
    basic_auth {
        admin $2a$14$你的密码哈希
    }
    rewrite /dav /dav/
    handle /dav/* {
        route {
            webdav {
                root C:/Users/Administrator/Desktop/OH-WorkSpace
                prefix /dav
            }
        }
    }
    handle {
        file_server {
            root C:/Users/Administrator/Desktop/OH-WorkSpace
            browse
        }
    }
}

密码哈希生成:caddy hash-password --plaintext "你的密码"

frp 暴露:云主机 frpc.toml 加一条 stcp 代理(workspace-files,端口 8080):

[[proxies]]
name = "workspace-files"
type = "stcp"
secretKey = "换成文件服务stcp密钥"
localIP = "127.0.0.1"
localPort = 8080

手机/开发机加对应 visitor(serverName = “workspace-files”,bindPort = 8080),访问 http://127.0.0.1:8080/ 即可看到网页式文件列表;/dav/ 端支持 WebDAV 客户端上传编辑。

验证:开发机/手机浏览器打开 http://127.0.0.1:8080/,输入用户名密码后看到文件列表即成功。

注意:Windows 下 Caddy 进程需对工作台目录有写权限,上传/编辑才可用,否则报错。

WebDAV 客户端选择:Windows 资源管理器"映射网络驱动器"要求 HTTPS + 基础认证,纯 HTTP 会被拒绝。推荐 RaiDrive / Cyberduck(Windows)、CX 文件管理器(手机)等支持 HTTP WebDAV 的应用。

五、踩坑速查表

类别 解法
网络 公司网络拦明文 HTTP/WS frp 隧道(加密二进制协议)
网络 RDP 端口被封 部署用云厂商网页 VNC,日常走 frp
cmd BOM 编码 批处理保存为无 BOM
cmd LF 换行 cmd 批处理必须 CRLF
cmd echo 含括号 if/else 块内 echo 文本禁括号
cmd %errorlevel% 预展开 块内用 if errorlevel 1
frp stcp 跨版本 0.65 客户端连 0.69 服务端可用,别急着加装服务端
frp custom listener doesn't exist 先看 proxy 端日志是否 start proxy success,核对 serverName 与 proxy 名完全一致(配了 user 要带前缀)
任务代理 超时杀进程树 Windows 下 subprocess.run(timeout=) 只杀 cmd.exe,孙进程残留;用 CREATE_NEW_PROCESS_GROUP + taskkill /T /F
任务代理 并发自锁 信号量统一管理,任务完成要清理,否则跑满后永久 429
任务代理 插件热加载 = RCE 通道 LLM 写的插件代码加载前必须人工确认
手机 鸿蒙后台杀连接 应用启动管理手动 + 电池不限制 + WLAN+ 关闭
手机 Tailscale 国内延迟高 放弃,用自建 frp
安全 access key 明文传输 全链路走 stcp 隧道,不暴露公网
Caddy Windows 下官网 API 返回 exe 非 zip 下载后直接改名 caddy.exe 用
Caddy webdav 模块不在标准版 用官网 API 下载带插件版
Caddy /dav(无尾斜杠)不匹配 handle /dav/* Caddyfile 加 rewrite /dav /dav/

六、安全加固

  1. 公网只开 frps 控制端口(7000,token 认证),云主机防火墙只放行必要端口
  2. HanaAgent 的端口不暴露公网——所有访问走 frp stcp 隧道,本机回环
  3. 访问凭据:PWA 需要 access key,WebDAV 需要用户名密码,隧道需要 token + secretKey,多层防护
  4. 信任边界:stcp 的 visitor 与 proxy 通过预共享密钥(secretKey)相互认证,密钥对不上隧道就建不起来;frps 本身验证的是 token。密钥明文存于配置文件,云主机是信任核心,配置文件权限收紧,token/secretKey 定期轮换(换密钥即可让旧访客失效)
  5. 任务代理 = 开发机完全交给云主机 Agent:FastAPI 接口本身要求 API key,防云主机本地被注入的 Agent 直接打 127.0.0.1:9000

七、资源与性能提示

  1. 内存:OpenHanako 安装包 400MB+(Electron 类应用),加 frps、frpc、Caddy 常驻,2G 内存的 Windows Server 很紧张。建议:加大虚拟内存(pagefile)、关闭不必要的 Server 服务;有条件直接升 4G
  2. 带宽:所有流量(PWA、文件、任务代理)都经 frps 中转,4.5GB 迁移数据量耗时取决于云主机带宽。NAT 条件好时可试 xtcp(打洞直连,需配置 fallbackTo 实现失败回退 stcp)作为进阶优化

八、使用体验与总结

日常使用:

  • 上班:开发机 PWA 连云主机 → 同一个 Agent、同一套记忆
  • 回家:手机 PWA 连云主机 → 无缝续上
  • 重活(编译/推理/大数据):云主机通过 frp 下发到开发机任务代理执行

任务执行位置约定(避免云主机卡死):

重活上开发机,轻活留云主机,拿不准先问。

三点感想:

  1. 架构决策要先实证再动手:很多"理论可行"(比如远程端执行在开发机)被实测推翻,早验证早省事
  2. 踩坑记录比功能更重要:cmd 四坑、鸿蒙保活三开关、Caddy 版本坑,每一个都是真金白银换来的
  3. AI 助手 + 自有基础设施:这套体系让 AI 助手真正"长"在了自己的网络环境里——能远程调度内网资源、能调用 GPU、记忆私有。这是云端 AI 服务给不了的

下一步打算把任务代理的插件体系扩充起来,折腾过 frp 内网穿透的朋友评论区聊聊你的玩法。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐