MoreRSS

site iconLeo Van | 范叶亮修改

京东、美团。现从事数据科学在安全风险领域的技术应用和产品设计。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Leo Van | 范叶亮的 RSS 预览

确定性和掌控欲

2026-05-23 08:00:00

最近观察自己和团队在使用 AI 上遇到了一些情况,比如生成的东西(代码、报告、网页等)“虾”味儿比较重,交付质量上也良莠不齐(准确性和深度等方面)。甚至在一些没有必要的场景(至少我认为没有必要)非要把 AI 用上,我想 FOMO 和组织压力是两个重要的“罪魁祸首”。彼时大家考虑更多的是如何“用上” AI,而不是如何“用好” AI。以任何一个角度去切入去尝试 AI 都是对的,欠妥的是当遇到“为什么一会儿行一会不行”,“为什么他那行我这不行”的时候,又会去质疑 AI 不行而不是自己用得不好。

思辨的意义在于过程中的反复,而不是最后的对与错和好与坏。在评判 AI 是否应该介入一个工作的时候我会关注两个点:

  1. ROI:一切抛开成本的使用都是耍流氓。典型的例子就是一个事儿一年都干不了几次,不确定性还很高,想要 AI 帮你一步到位纯纯就是幻想(至少现在是)。
  2. 角色:它在这件事儿中扮演什么样的角色。以画图为例(这里说的是思维导图、架构图之类,而非数据图),我可以和 AI 探讨思路,然后把结果按照想要的样子放上去。而不是一句话:帮我把 XXX 画一个架构图出来。图的意义从来不是这张图本身,而是拼拼凑凑形成过程中的思考,当你想一句话画出来的时候,你不想干的一定不是“画”而是“思考”。

一篇『文科生 72 小时杀入 GitHub 全球榜:我没写一行代码,但指挥了一支 AI 军队』让“技术平权”再次沸腾,但我希望在团队拥抱 AI 的过程中成为一个仁慈的独裁者 12,确定性和掌控欲不是阻碍 AI 落地的绊脚石,当个“甩手掌柜”才是加速被淘汰的慢性毒药。

技术视角

在之前的文章中提过 LLM 本身是一个无状态的服务,你给他什么样的输入,它就会预测什么样的输出。产生不确定性的核心在于当今 AI 的背后是一个概率预测模型:

排除网络架构的不同 34,即使最朴素的全连接神经网络,在给到足够的训练数据时,其仍可以拟合任意函数:

在以 Transformer 为基础的 LLM 中,还有着多个用于控制模型输出不确定性的参数。

参数 图示 描述
最大 Token 数
控制生成的最大 Token 数,
取值范围 $\left[1, \infty\right]$
温度
控制模型输出的随机性,值越大越随机,
取值范围 $\left[0, 2\right]$
$\text{Top}_p$
控制 Token 采样时的累计概率,
取值范围 $\left[0, 1\right]$
$\text{Top}_k$
控制 Token 采样时当候选数量,
取值范围 $\left[1, \infty\right]$
频率惩罚
减少重复内容的生成,正值减少重复
取值范围 $\left[-2, 2\right]$
存在惩罚
鼓励生成新的内容,正值鼓励新内容
取值范围 $\left[-2, 2\right]$
停止词
自定义的停止词列表

通过调整如上参数,你可以一定程度上控制 AI 输出的不确定性,当写代码时可以让其更确定些,当做内容创作时可以让其更随机些。用好 AI,而不是当 AI 彻底放飞自我的时候只会吐槽它又变“傻”了。Harness Engineering 也在尝试从应用层解决产出可靠性的问题。

图片作者:宝玉

在写 Skill 的时候,根据 Claude Code 的 Skill 编写规范SKILL.md 文件应该在 500 行以下,更详细的参考资料应该转移到单独的文件中去。确定性的事情应该放在 scripts 中用代码实现,当下用 AI 写 Skill 的时候虽然它知道利用脚本实现一些确定性的事情,但脚本自身是否正确是否鲁棒你心里还需有个谱。知其然,知其所以然,AI 时代没有要求大家都需要搞明白模型中的各种数学公式,但用好 AI 的人也绝不仅限于知道几个 AI 名词而已。

管理视角

现在面向代码春暖花开的我曾经学了 7 年的管理,记得管理学老师开堂的第一句话是:管理学既是一门科学,又是一门艺术。科学性在于我们有经典的马斯洛需求层次理论双因素理论,艺术性在于人与社会的复杂和管理实践中“度”的拿捏,例如放权。网上有这样一篇文章:不懂代码反而是优势,为什么控制欲强的人用不好 AI?。我个人的观点是五五开,当前技术发展之迅猛前所未有,不懂代码就不会陷入固有的行为模式中去,确实更容易拥抱变化,但控制欲强并不代表不放权,随着 AI 时代生产力和生产关系的变化,放权的艺术也需要与时俱进。

文章中提到“以结果为导向”,这点我很赞同,商业体系中生存之本就是拿结果。“拿结果”这三个字说起来容易,但拿什么、怎么拿、谁来拿这都是问题。组织的层级设置,从战略到战术的层层拆解,这些都是复杂的工程。以一线管理者为例(我理解和当前大家使用和管理自己的智能体场景类似),如果你只一味的抓结果不抓过程,那么等 Deadline 到了却没有合格的产出时,一切终究都是徒劳。因为这里的结果不是你三两句指令做出来的 MVP,而是需要在线上稳定高效运行的系统。

最近出差在飞机上听了《面基》播客中一期:新一波超级婴儿潮:Agent 人口大爆发和加速的时间,里面提到在 AI Coding 的当下人人都可以在自己的电脑上手搓“小板凳”,那在这样的时代如何定义“好”呢?“小板凳”说的是很多人在家做小板凳,但客户真正需要的是沙发。也就是说你费劲做出来的那点东西,离真正被市场需要、愿意付钱的成熟产品,往往还差得很远。但为什么明明很多人知道自己做的就是小板凳,却还是忍不住一张接一张地做呢?原因可能会有很多:一条新赛道的好奇感,一个新时代的压迫感,抑或是?做小板凳本身并没有什么不好,板凳和沙发之间也不是说相差十万八千里,做沙发的老师傅也是从做小板凳开始的。我希望团队里的人可以在做完十个小板凳之后去尝试做一个沙发,或者停下来了解下更底层的榫卯结构。

战略的制定者一定是从战术的执行者到战术的制定者再一步一步走过来的,掌控欲并非是要事必躬亲(Sometimes maybe),而是需要了解更多可以支持战略制定的信息。战略性的失误会比战术性的失误可怕的多,如果可以我也想对 AI 说你自己看着办吧,然后我就在旁悠闲的喝茶,甚至连监督都不想做。在此推荐一下宝玉的一篇文章:为什么我不“凭感觉编程”,权当是一个新的视角,任凭弱水三千,我只取一瓢饮。

伦理视角

我个人现在从事安全相关工作,日常处理的工作内容中包括很多“坏”事儿,这里的“坏”并不是代表我要去做坏事,而是事情的背景中充斥的一些敏感的内容。基于这种情况,在我使用 AI 的过程中会存在两类问题:

  1. AI 触发审查机制,尽管我的要求合法合规,但由于给定的上下文背景中存在敏感信息,AI 最终会拒绝我的要求。
  2. AI 在授权的场景下,为了实现要求会“不择手段”的尝试尽可能多的路径,但对于路径在物理世界的风险评估不够,有时会造成一些不好的结果。例如:因为现有系统存在 BUG,AI 执行了本不该执行的操作,最后导致原有系统发生崩溃。这锅你说是让 AI 背,还是你来背,还是现有系统背,还是各打五十大板?

两个问题存在一定的冲突,有时候我们需要更多的“自由”,有时候我们又不太想让它太过“自由”。这里我们有很多的技术方式可以去尝试解决,但除此之外我们更需要从伦理视角去重新审视 AI 之于我们的关系。

  1. 摆正思想,善(善良)用 AI:不为恶(Don’t be Evil)是 Google 提出的企业座右铭,真的很难做到,但我们又必须去做。我的底线可以低些,但不能没有。
  2. 摆正角色,善(善于)用 AI:当下我们需要为 AI 犯下的错误承当全部责任,不要以为你说的三两句指令无关痛痒,一切的后果及其引发的一连串问题你都难以想象。

你的 AI 不是你的 AI,这里回应多年前看的一部剧『你的孩子不是你的孩子』,对于 AI 的培养可以像培养孩子一样,两者是有很多共通之处的。

LLM Token 消耗节省计划

2026-04-25 08:00:00

模型价格

我在之前的文章「AI 时代的生产力和生产关系」中曾抛出过一个问题:如果由你自己承担龙虾的费用,你是否还会像当前这样使用龙虾?虽然之前的文章「本地部署大模型服务」介绍了如何通过本地部署实现 Token 自由,但想要你的智能体更聪明,往往还是需要一个参数规模远超你本地机器所能承受的模型才更靠谱些。当然也可以祭出你的多卡服务器,但无论以何种方式实现 Token 自由,终究都不免落入 ROI 计算的俗套,因为这背后的背后都是实打实的真金白银。统计了当前流行的部分国内外模型的价格,如下表所示:

模型 发布日期 参数 上下文长度 能力 输入价格 输出价格 缓存命中价格
Claude Opus 4.6 2026-02 未知 1M \$5 \$25 \$0.5
GPT-5.4 2026-03 未知 1.05M ≤272K \$2.5
>272K \$5
≤272K \$15
>272K \$22.5
≤272K \$0.25
>272K \$0.5
Grok 4.20 2026-03 未知 2M ≤200K \$2
>200K \$4
≤200K \$6
>200K \$12
≤200K \$0.2
>200K \$0.4
Gemma 4 31B 2026-04 31B 262.1K \$0.14 \$0.4 \$0.07
Gemma 4 26B A4B 2026-04 26B 262.1K \$0.13 \$0.4 \$0.05
Kimi K2.5 2026-02 1000B 262.1K \$0.6 \$3 \$0.1
MiniMax M2.7 2026-03 230B 204.8K \$0.3 \$1.2 \$0.06
GLM 5 Turbo 2026-04 744B 202.8K \$1.2 \$4 \$0.24
Qwen 3.5 27B 2026-02 27B 262.1K \$0.3 \$2.4 \$0.15
Qwen 3.5 35B A3B 2026-02 35B 262.1K \$0.25 \$2 \$0.12

上述模型在 OpenClaw 上的成功率和输入价格对比图如下所示:

大小表示模型参数规模(对数处理)
参考:https://pinchbench.com/?view=graphs
模型成功率 v.s. 输入价格

从上述图表中不难看出:模型越大、能力越丰富、支持的上下文越长价格也就越贵。同时部分模型针对超长的输入输出还会加价计费,这是因为随着输入输出的增加,模型的计算量并不是以线性的方式增长的,而是指数增长。

费用构成

那么除了选择一个高性价比的模型之外,可还有其他的省钱之道?接下来我们来聊聊你的钱都花在了哪些地方,从定价表来看包括三个部分:输入输出缓存命中,为了更好的理解三者价格的差异,我们需要先回答如下两个问题。

为什么输出比输入要贵?

大模型的推理分为两个阶段:预填充(Prefill)和解码(Decode),过程如下图所示:

模型在获取到用户的提示词后,会将提示词中的所有 Token 一次性读入到模型中,这个阶段是高度并行的。例如当提示词中包含 100 个 Token 时,模型可以同时处理这 100 个 Token,GPU 最擅长的就是此类并行计算。此时 GPU 的利用率很高,因此分摊到每个 Token 上的成本就比较小。

预填充结束后模型开始输出,输出的 Token 只能一个一个的计算。这是因为每生成一个 Token,模型都需要将其拼接到之前的序列中,用作输入来生成下一个 Token。这是自回归解码模型的运行原理,无法并行,此时 GPU 的利用率较低,性能瓶颈在于显存中的数据传输而非计算。假设模型的参数量为 $P$,提示词的 Token 长度为 $M$,已经输出的 Token 长度为 $n$,那么在计算输出第 $n + 1$ 个 Token 时,模型的计算量为 $\left(M + n\right) \times P$。假设输出的 Token 总长度为 $N$,则总计算量为 $\sum_{i=1}^{N} \left(M + i\right) \times P$。可以看出,计算量和 Token 输出数量之间并非线性关系,这就是为什么有些模型针对超长的输出会加价计费。

什么是缓存命中?

模型的输入除了用户的提示词以外,往往还会包含系统提示词等内容,这部分在每次模型运行的过程中都是相同的。通过提示词缓存技术可以将这段前缀提示词计算的结果保存在高速缓存中,在下次预填充的时候,如果前缀一样则直接可以把这部分结果从高速缓存中读取出来,而不需要重复计算。此时的成本仅包含缓存的存储和加载开销,对 GPU 算力几乎没有占用,因此这部分价格会很低。

需要注意的是,缓存是前缀匹配的,哪怕修改了一个字,后面的部分也都需要重新计算。缓存通常具有一定的有效期,一般几分钟到几小时就会失效。智能体往往会将系统提示词等不变的内容放在前面,将用户提示词等变化的内容放在后面,从而提升缓存命中率。

节省计划

你需要知道 LLM 本身是一个无状态的服务,也就是说当模型确定后,你给它什么样的输入,它就针对性地给到你什么样的输出。当你在和智能体对话的时候,每一次智能体接收的输入并不仅仅是你这轮与其对话的内容,而是整个会话中的全部。

所以想要节省 Token,核心就是做好上下文管理,管得太紧(缺少必要的信息)效果就会大打折扣,管得太松(无用的信息太多)不单单是费钱效果也可能会受到影响。结合上下文管理,如下给到不同视角的一些节省 Token 的技巧和建议:

记忆管理

OpenClaw 采用 Markdown 文件的方式管理记忆。除了定期和手动(/compact)的记忆压缩外,最新版本的 OpenClaw 还引入QMD 记忆引擎。个人理解 QMD 本质上属于 RAG,通过 QMD 可以将相关的记忆放入上下文,而非全部,此时此刻 LLM Wiki 和 RAG 不就又胜利会师了吗。

平台已经把心替你操了,你无须再做什么操作 🥳
明确需求

写 Prompt 和沟通一样,是一门艺术。有些场景需要模糊些,例如探索性分析,模型可能会给到你意想不到的结果。但当需求明确的时候,准确的需求描述可以让智能体少很多弯路。需求一次性说完整,比一轮一轮的挤牙膏式会少消耗不少 Token。

别学某些芯片厂,总是挤牙膏 😂
控制输出

输出比输入贵上个 5-10 倍,告诉 AI 你要什么,不要让它自由发挥。以及最后那一句“我真的太棒了!”的情绪价值属实大可不必。❌:帮我分析一下这篇文章。✅:分析一下这篇文章,用一百个字总结核心内容。

严重怀疑服务商在 LLM 里写死了一条指令:多说些,我好多赚点儿 🤑

以上是几点通用的技巧和建议。在更多细分的场景(例如:编码)会有更多的实用技巧,在此不再一一展开,可以参考如下文章:

  1. Token 节省 99% ?细数所有省 Token方法后我才明白:导致 AI 成本爆炸的核心,就是没做好上下文管理
  2. WorkBuddy 积分节省指南:5 个技巧让 Token 消耗降低 90%
  3. OpenClaw 省 Token 实战:控制输入 Token 长度的 6 个核心策略和精准检索代码块技巧
  4. OpenClaw 成本优化:完整 Token 管理指南,帮你节省 50-80% AI 费用
  5. 省 token 技巧,让你用 AI 更省钱!

智能体的角色定位和身份演化

2026-04-19 08:00:00

随着 OpenClaw 的爆火,智能体(Agent)一词已经成了大家每天都挂在嘴边儿上的话。从“智能体”成为 2025 年度科技热词以来,说这个词被滥用或许略显激进,但当一个词进入寻常百姓家时,或许我们应该重新审视一下到底什么是智能体,这个硅基生物之于我们碳基生物又是什么角色,“它”又是如何在改变着我们的生活呢?

智能体

我搜集了互联网上对于智能体的定义:

智能体(Agent)

智能体指一个可以观察周遭环境并作出行动以达到目标并且可以通过机器学习以及获取知识来提升自身性能的自主实体。 —— 维基百科

智能体是一种接收输入、解读输入,然后代表用户(无论是人类还是其他智能体)规划和执行操作的系统。 —— web.dev

AI 智能体是使用 AI 来实现目标并代表用户完成任务的软件系统。其表现出了推理、规划和记忆能力,并且具有一定的自主性,能够自主学习、适应和做出决定。 —— Google Cloud

智能体是一个系统,它利用人工智能模型与环境交互,以实现用户定义的目标。它结合推理、规划和动作执行(通常通过外部工具)来完成任务。 —— Hugging Face

如 ReAct 框架 1 所述,智能体的主要特点如下:

  • 推理:此核心认知过程涉及使用逻辑和可用信息来得出结论、进行推断及解决问题。具有强大推理能力的 AI 智能体可以分析数据、识别模式,并根据证据和上下文做出明智的决策。
  • 行动:根据决策、计划或外部输入采取行动或执行任务的能力对于 AI 智能体与其环境进行互动和实现目标至关重要。这可能包括具身 AI 的物理动作,或发送消息、更新数据或触发其他流程等数字操作。
  • 观察:通过感知或感应收集有关环境或情况的信息,对于 AI 智能体了解上下文并做出明智的决策至关重要。这可能涉及多种感知形式,例如计算机视觉、自然语言处理或传感器数据分析。
  • 规划:制定战略计划以实现目标,是智能行为的一个关键方面。具有规划能力的 AI 智能体可以确定必要的步骤、评估潜在行动,并根据可用信息和预期结果选择最佳行动方案。这通常需要预见未来的状态,并考量可能遇到的障碍。
  • 协作:在复杂且动态的环境中,与他人(无论是人类还是其他 AI 智能体)有效协作来实现共同目标变得越来越重要。协作离不开沟通、协调,以及理解并尊重他人观点的能力。
  • 自我完善:自我改进和自适应能力是高级 AI 系统的标志。具有自我完善能力的 AI 智能体可以从经验中学习,根据反馈调整行为,并随着时间的推移不断提升性能和能力。这可能涉及机器学习技术、优化算法或其他形式的自行修改。

角色定位

以 OpenClaw 为例的智能体,其能力足够丰富,在企业实践中不同场景需要不同类型的智能体以便更好(例如:更快速、更安全等)地服务其目标客户。从业务视角出发在此将智能体划分为个人助理、数字员工和数字分身三类,这三类的差异对比如下:

角色 个人助理 数字员工 数字分身
服务对象 个人 他人 个人
所有权 个人 多种 2 个人
身份 智能体自己 智能体自己 所有权人
定位 帮助所有权人处理个人需求 帮助所有权人处理他人需求 帮助所有权人以所有权人身份处理需求
示例 帮自己搜集信息 帮服务对象查询天气 帮自己去参加在线会议

结合 OpenClaw 的定义(OpenClaw is a self-hosted gateway …, and it becomes the bridge between your messaging apps and an always-available AI assistant. 3),其更符合个人助理的角色定位。数字分身相比另外两个角色最大的特点是其身份代表的是所有权人,除了技术实现难度外,更重要的是伦理问题。当数字员工出现问题时,是应该所有权人为其负责还是技术服务提供者为其负责呢?这个问题类似智能驾驶,当出现交通事故时,是应该由驾驶员承担责任还是自动驾驶服务提供商承担责任呢?目前来看,几乎全部责任仍是由驾驶人员承担。

从技术视角出发,个人助理和数字员工两个重要角色差异对比如下:

角色 个人助理 数字员工
知识 私有 + 共有 共有 + 权限管控
数据 私有 + 共有 共有 + 权限管控
技能 私有 + 共有 共有 + 权限管控
渠道 私有 共有 + 权限管控
定制化 程度高 程度低
核心目的 节省自己的资源(时间等) 节省组织的资源(人力等)

不难看出,个人助理和数字员工的一个核心差异在于权限。个人助理的权限管控并不在智能体内部实现,也就是说当你有某个权限的时候,只要你想个人助理就可以有,权限的边界在智能体之外。但数字员工的权限管控需要在智能体内部实现,数字员工使用同一个渠道对外提供服务,我们必须根据服务对象的不同采取不同的操作。个人助理是可以高度化定制的,只要你想怎么搞都是你自己的事。但数字员工受限就会很多,因为要面向多人服务,我们需要考虑响应的时效性、服务的稳定性、数据的安全性等等。

个人助理解决的是个人的长尾事务,只有将自己从重复繁琐的任务解放出来,我们才能够有更多的时间去思考更重要的事情。而数字员工解决更多的是通用类型的事务,这样才能够服务更多的用户,从而提高组织效能。

身份演化

其实我们也无需将个人助理和数字员工割裂来看,在个人助理上做一些适当的加减法就可以让其变成数字员工,同时数字员工之于个人助理也可以看作是一项技能而为其所用。我个人认为从个人助理进化到数字员工是一个先做减法再做加法的过程。

当前的个人助理已经是一个可以高度定制同时具有一定自主能力的智能体。在企业应用过程中,基于安全等因素的考虑我们必须在一定程度上限制其灵活性,才能够一方面高效的满足用户需求另一方面避免其成为一匹脱缰的野马。换句话说就是从个人助理的执行优先转变到数字员工的治理优先。这里感觉和当下的 Harness Engineering 有些许呼应,Harness 给到了系统运转的最佳范式,但同时也指定了相应的约束机制。约束的方式(代码层、Prompt 层、Skill 层)和约束的强度影响着任务执行的灵活程度。

图片来源:https://zhuanlan.zhihu.com/p/2020772553333941162

正如员工在进入组织前期,他首先要学习的就是组织的规章制度,什么可以做,什么不可以做。当员工对组织的要求清晰之后,才会被允许从事更加复杂的工作,才会被赋予更多的自主权。在这个过程中组织仍会定期观测,同时对必要的问题做出反馈并要求员工进行修正。在此也收集了智能体 4、数字员工 5 和自动驾驶 6 的分级对比:

级别 自动驾驶 智能体 数字员工
L1 辅助驾驶
车辆对方向盘和加减速中的一项操作提供驾驶,人类驾驶员负责其余的驾驶动作。
规则符号智能
意图 + 行动
功能级-辅助工具
作为工具被调用,人类执行并闭环任务。
L2 部分自动驾驶
车辆对方向盘和加减速中的多项操作提供驾驶,人类驾驶员负责其余的驾驶动作。
推理决策智能
意图 + 行动 + 推理和决策
任务级-任务执行
执行被分解的任务,人类拆解分配任务。
L3 条件自动驾驶
由车辆完成绝大部分驾驶操作,人类驾驶员需保持注意力集中以备不时之需。
记忆反思智能
意图 + 行动 + 推理和决策 + 记忆和反思
协作级-协作自治
自主拆解及分配任务、闭环执行,人和数字员工协作,人类监督。
L4 高度自动驾驶
由车辆完成所有驾驶操作,人类驾驶员无需保持注意力集中,但限定道路和环境条件。
自主学习智能
意图 + 行动 + 推理和决策 + 记忆和反思 + 自主学习 + 泛化
指导级-专业指导
提供达到人类专家水平的定制化服务,人类参与。
L5 完全自动驾驶
由车辆完成所有驾驶操作,人类驾驶员无需保持注意力集中。
个性群体智能
意图 + 行动 + 推理和决策 + 记忆和反思 + 自主学习 + 泛化 + 人格 + 协作
智慧级-自主智慧
超越人类专家水平的能力,全面自主,人类授权。

我认为我们目前正处于 L3 至 L4 之间的一个地带,我相信在不久的将来我们可以突破 L4 迈入 L5。我希望 AI 会一直是为人所用,而不希望如之前博客所描述的人类成为 AI 的奴隶。引用一下阿西莫夫机器人三定律,希望在生产力高速发展的同时我们也可以更多的关注一下 AI 可能引起的一系列社会和伦理问题。

机器人三定律
  1. 机器人不得伤害人类,或坐视人类受到伤害。
  2. 除非违背第一法则,机器人必须服从人类的命令。
  3. 在不违背第一及第二法则下,机器人必须保护自己。

  1. Yao, Shunyu, et al. “React: Synergizing reasoning and acting in language models.” The eleventh international conference on learning representations. 2022. ↩︎

  2. 在企业中往往所有权归属于一个组织而非个人。 ↩︎

  3. https://docs.openclaw.ai/ ↩︎

  4. 5 Levels Of AI Agents ↩︎

  5. 大模型驱动的数字员工3.0 建设应用白皮书 ↩︎

  6. https://zh.wikipedia.org/zh-cn/自动驾驶汽车 ↩︎

本地部署智能体

2026-04-18 08:00:00

环境信息

本教程将介绍在 macOS 环境下部署 OpenClaw,QwenPaw 和 Hermes Agent。如无特殊说明,macOS 系统下需在终端中执行命令,Windows 系统下需要在 PowerShell 中执行命令。本教程涉及到的软件信息如下:

软件 版本
Podman 5.8.2
OpenClaw 2026.4.16
QwenPaw 1.1.2
Hermes Agent 0.10.0

虚拟环境

为了更好的进行环境隔离,后续我们使用 Podman 安装不同的智能体框架。

提示
在 Windows 系统下,单击开始按钮,搜索 启用或关闭 Windows 功能,在打开的窗口中将 Hyper-V适用于 Linux 的 Windows 子系统 及其子项全部勾选,单击确定,待系统启用功能后重启电脑。

运行如下命令安装 Podman:

brew install podman

brew 安装请参见:https://brew.sh/

scoop install podman

scoop 安装请参见:https://scoop.sh/

为了方便观察 Podman 的运行情况,可选的运行如下命令安装 Podman Desktop:

brew install podman-desktop
scoop install podman-desktop

安装完毕后,运行如下命令初始化并启动 Podman:

podman machine init
podman machine start
podman machine init
podman machine start

运行如下命令查看 Podman 的安装和运行情况:

podman info
podman info

更多 Podman 使用方法请参考 Podman 文档。有关 Podman Desktop 的使用方法请参考 Podman Desktop 文档

OpenClaw

安装

克隆 OpenClaw 的源代码至本地:

git clone [email protected]:openclaw/openclaw.git
git clone git@github.com:openclaw/openclaw.git

运行如下命令安装 OpenClaw CLI:

curl -fsSL https://openclaw.ai/install-cli.sh | bash

命令会在 ~/.openclaw 目录下安装 Node 环境和相关依赖。进入 OpenClaw 源代码目录下,运行如下命令构建 Gateway 容器:

export OPENCLAW_DOCKER_APT_PACKAGES="chromium"
./scripts/podman/setup.sh

其中 OPENCLAW_DOCKER_APT_PACKAGES 表示构建 Gateway 容器时使用 apt 命令额外安装的软件包。运行如下命令启动 Gateway 容器:

./scripts/run-openclaw-podman.sh launch

运行如下命令进行配置:

./scripts/run-openclaw-podman.sh launch setup

在配置过程中根据实际情况对模型提供商等选项进行配置。配置如下环境变量来使用宿主机中的 OpenClaw CLI 管理 OpenClaw 容器:

export PATH="$PATH:/Users/leo/.openclaw/bin"
export OPENCLAW_CONTAINER=openclaw

在合适的目录创建如下文件夹:

mkdir /path/to/openclaw
mkdir /path/to/openclaw/workspace

进入 OpenClaw 源代码目录下,运行如下命令构建 Gateway 容器:

podman build -t openclaw:local -f Dockerfile . --build-arg OPENCLAW_DOCKER_APT_PACKAGES="chromium"

其中 OPENCLAW_DOCKER_APT_PACKAGES 表示构建 Gateway 容器时使用 apt 命令额外安装的软件包。运行如下命令配置并启动 Gateway 容器:

$env:OPENCLAW_CONFIG_DIR = "/path/to/openclaw"
$env:OPENCLAW_WORKSPACE_DIR = "/path/to/openclaw/workspace"

podman compose run --rm --no-deps --entrypoint node openclaw-gateway `
  dist/index.js onboard --mode local --no-install-daemon

podman compose run --rm --no-deps --entrypoint node openclaw-gateway `
  dist/index.js config set --batch-json '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]'

podman compose up -d openclaw-gateway

在配置中过程中根据实际情况对模型提供商等选项进行配置。

使用 Podman 安装 OpenClaw 后,重启 Gateway 的命令如下:

podman restart openclaw
podman restart openclaw-openclaw-gateway-1

使用浏览器打开 http://127.0.0.1:18789/ 即可进入 OpenClaw 管理页面。更多细节请参考 OpenClaw 文档

警告
OpenClaw 管理页面虽然支持权限校验,但为了安全起见,请勿将其暴露在公网。

消息频道

提示
在 Windows 系统下,podman compose 命令需要在 OpenClaw 源代码目录下运行。

飞书

运行如下命令配置飞书消息频道:

openclaw channels login --channel feishu
podman compose exec openclaw-gateway node dist/index.js channels login --channel feishu

使用飞书 APP 扫描生成的二维码进行后续配置即可。

Discord

首先在 Discord 中创建一个服务器,进入 Discord 开发者门户,单击 新 APP 按钮创建新的应用,并填写应用名称。

进入 概况 - 机器人 选项卡,启用 Presence IntentServer Members IntentMessage Content Intent

进入 概况 - 机器人 选项卡,单击 重置令牌 生成令牌,注意令牌仅显示一次,请妥善保管以便后续使用。

进入 概况 - OAuth2 选项卡,在 OAuth2 URL 生成器的 范围 中选中 botapplications.commands

机器人权限 中选中 查看频道发送消息阅读消息历史记录嵌入链接添加文件添加反应

已生成的 URL 中的 URL 复制到浏览器打开,按照提示安装应用并授权。

打开 Discord 应用,进入 用户设置 页面,在 开发者 菜单中启用 开发者模式。在频道图标上右键,单击 复制服务器 ID,在个人头像上左键,单击 复制用户 ID

运行如下命令配置 Discord 消息频道:

openclaw config set channels.discord.token "你的 TOKEN"
openclaw config set channels.discord.enabled true --strict-json
podman compose exec openclaw-gateway node dist/index.js config set channels.discord.token "你的 TOKEN"
podman compose exec openclaw-gateway node dist/index.js config set channels.discord.enabled true --strict-json

向机器人发送任意消息,根据机器人回复的消息运行如下命令进行授权:

openclaw pairing approve discord <CODE>
podman compose exec openclaw-gateway node dist/index.js pairing approve discord <CODE>

此时就可以通过 Discord 私信和机器人对话了。在配置文件中添加如下内容来支持在服务器中同机器人对话:

{
  "channels": {
    "discord": {
      "groupPolicy": "allowlist",
      "guilds": {
        "服务器 ID": {
          "requireMention": true,
          "users": ["用户 ID"]
        }
      }
    }
  }
}

默认情况下,机器人只有在被 @ 时才会响应,如果需要对每条消息都进行响应,可以将 requireMention 设置为 false

QwenPaw

安装

在合适的目录创建如下文件夹:

mkdir -p /path/to/qwenpaw/data
mkdir -p /path/to/qwenpaw/secrets
mkdir /path/to/qwenpaw/data
mkdir /path/to/qwenpaw/secrets

运行如下命令使用 Podman 安装 QwenPaw:

podman pull agentscope/qwenpaw:latest
podman run -d \
  --name qwenpaw \
  --restart always \
  -v /path/to/qwenpaw/data:/app/working \
  -v /path/to/qwenpaw/secrets:/app/working.secret \
  -p 8088:8088 \
  agentscope/qwenpaw:latest
podman pull agentscope/qwenpaw:latest
podman run -d `
  --name qwenpaw `
  --restart always `
  -v /path/to/qwenpaw/data:/app/working `
  -v /path/to/qwenpaw/secrets:/app/working.secret `
  -p 8088:8088 `
  agentscope/qwenpaw:latest

使用浏览器打开 http://127.0.0.1:8088/ 即可进入 QwenPaw 管理页面。

警告
QwenPaw 管理页面暂无权限校验,请勿将其暴露在公网。
注意
在 QwenPaw 中需要进入 智能体管理 中新建一个智能体,默认智能体 无法进行修改。

消息频道

飞书

参见:https://qwenpaw.agentscope.io/docs/channels/?lang=zh#飞书

Discord

参见:https://qwenpaw.agentscope.io/docs/channels/?lang=zh#Discord

Hermes Agent

安装

在合适的目录创建如下文件夹:

mkdir -p /path/to/hermes-agent
mkdir /path/to/hermes-agent

运行如下命令使用 Podman 配置 Hermes Agent:

podman pull nousresearch/hermes-agent:latest
podman run -it --rm \
  -v /path/to/hermes-agent:/opt/data \
  nousresearch/hermes-agent:latest setup
podman pull nousresearch/hermes-agent:latest
podman run -it --rm `
  -v /path/to/hermes-agent:/opt/data `
  nousresearch/hermes-agent:latest setup

在配置过程中根据实际情况对模型提供商等选项进行配置。运行如下代码启动 Gateway 容器:

podman run -d \
  --name hermes-agent-gateway \
  --restart unless-stopped \
  -v /path/to/hermes-agent:/opt/data \
  -p 8642:8642 \
  nousresearch/hermes-agent:latest gateway run
podman run -d `
  --name hermes-agent-gateway `
  --restart unless-stopped `
  -v /path/to/hermes-agent:/opt/data `
  -p 8642:8642 `
  nousresearch/hermes-agent:latest gateway run

运行如下代码启动 Dashboard 容器:

podman run -d \
  --name hermes-agent-dashboard \
  --restart unless-stopped \
  -v /path/to/hermes-agent:/opt/data \
  -p 9119:9119 \
  -e GATEWAY_HEALTH_URL=http://$HOST_IP:8642 \
  nousresearch/hermes-agent:latest dashboard --host 0.0.0.0 --insecure
podman run -d `
  --name hermes-agent-dashboard `
  --restart unless-stopped `
  -v /path/to/hermes-agent:/opt/data `
  -p 9119:9119 `
  -e GATEWAY_HEALTH_URL=http://$HOST_IP:8642 `
  nousresearch/hermes-agent:latest dashboard --host 0.0.0.0 --insecure

$HOST_IP 替换为运行 Gateway 容器机器的 IP 地址(注意:需使用宿主机的 IP 地址,而不是 127.0.0.1)。使用浏览器打开 http://127.0.0.1:9119/ 即可进入 Hermes Agent 管理页面。

警告
Hermes Agent 管理页面暂无权限校验,请勿将其暴露在公网。

消息频道

飞书

参见:https://hermes-agent.nousresearch.com/docs/user-guide/messaging/feishu

Discord

参见:https://hermes-agent.nousresearch.com/docs/user-guide/messaging/discord

部署 Matrix 服务器 Synapse

2026-04-11 08:00:00

环境信息

Matrix 是一种用于实时通讯的开放、去中心化协议,专注于安全、加密的文字、语音和视频聊天。它允许不同服务器上的用户互通,类似于邮件系统,并支持端到端加密,使用户能完全控制数据,不受单一实体限制。

Matrix 联邦服务器之间连接的客户端

Synapse 是一个使用 Python/Twisted 和 Rust 编写的开源 Matrix 服务器实现。本教程将介绍使用 Docker 容器部署 Matrix 服务器 Synapse。本教程涉及到的软件信息如下:

软件 Docker 镜像 版本
PostgreSQL mixdeve/postgres-zhparser:18 18
Redis redis:8 8
Synapse matrixdotorg/synapse:latest 1.151.0
注意
将后续命令中的 example.com 替换为实际域名。

准备工作

数据库

为了支持中文搜索,在此选择内置 zhparser 分词功能的 PostgreSQL 镜像。在适当位置创建 PostgreSQL 的存储目录,例如 postgresql。运行如下命令生成配置:

docker run -d \
  --name postgresql \
  --restart always \
  -v $(pwd)/postgresql:/var/lib/postgresql \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=<密码> \
  -e ALLOW_IP_RANGE=0.0.0.0/0 \
  -p 5432:5432 \
  mixdeve/postgres-zhparser:18

相关参数说明如下:

参数 说明
POSTGRES_USER 数据库用户名,默认 postgres
POSTGRES_PASSWORD 数据库密码
POSTGRES_DB 默认数据库名,默认 postgres
ALLOW_IP_RANGE 允许访问的 IP 范围

进入数据库执行如下 SQL 进行配置:

-- 创建用户
CREATE USER synapse WITH PASSWORD '<密码>';

-- 创建数据库
CREATE DATABASE synapse WITH OWNER = synapse ENCODING = 'UTF8' LC_COLLATE = 'C' LC_CTYPE = 'C' TEMPLATE = template0;

-- 授权
GRANT ALL PRIVILEGES ON DATABASE synapse TO synapse;

缓存

为了提升服务性能,在此开启 Redis 缓存。在适当位置创建 Redis 的存储目录,例如 redis。运行如下命令启动 Redis 容器:

docker run -d \
  --name redis \
  --restart always \
  -v $(pwd)/redis:/data \
  -p 6379:6379 \
  redis:8 \
  redis-server --save 60 1 --appendonly yes

配置文件

进入服务器在适当位置创建 Synapse 的存储目录,例如 synapse。运行如下命令生成配置:

docker run -it --rm \
  -v $(pwd)/synapse:/data \
  -e SYNAPSE_SERVER_NAME=example.com \
  -e SYNAPSE_REPORT_STATS=no \
  -e SYNAPSE_HTTP_PORT=8008 \
  -e UID=1000 \
  -e GID=1000 \
  matrixdotorg/synapse:latest generate

相关参数说明如下:

参数 说明
SYNAPSE_SERVER_NAME 服务器域名
SYNAPSE_REPORT_STATS 是否上报统计信息,默认 yes
SYNAPSE_HTTP_PORT HTTP 端口,默认 8008
SYNAPSE_CONFIG_DIR 配置目录,默认 /data
SYNAPSE_CONFIG_PATH 配置文件路径,默认 <SYNAPSE_CONFIG_DIR>/homeserver.yaml
SYNAPSE_DATA_DIR 数据目录,默认 /data
UID 用户 ID,默认 991
GID 组 ID,默认 991

修改配置文件服务部分如下:

public_baseurl: https://matrix-homeserver.example.com
serve_server_wellknown: true

修改配置文件数据库部分如下:

database:
  name: psycopg2
  txn_limit: 10000
  args:
    user: synapse
    password: <密码>
    dbname: synapse
    host: <数据库地址>
    port: 5432
    cp_min: 5
    cp_max: 10

修改配置文件缓存部分如下:

redis:
  enabled: true
  host: <数据库地址>
  port: 6379
  dbid: 0

启动服务

运行如下命令启动服务:

docker run -d \
  --name synapse \
  --restart always \
  -v $(pwd)/synapse:/data \
  -u 1000:1000 \
  -p 8008:8008 \
  matrixdotorg/synapse:latest

在服务商中配置 DNS 将 matrix-homeserver.example.com 解析至 Docker 服务器的 IP 地址。通过浏览器访问 http://matrix-homeserver.example.com:8008 即可查看 Synapse 服务是否启动成功。

中文搜索

提示
如果不需要中文搜索服务,可跳过本节。

在 PostgreSQL 数据中运行如下 SQL 安装 zhparser 扩展并配置中文搜索:

-- 创建 zhparser 扩展
CREATE EXTENSION IF NOT EXISTS zhparser;

-- 创建中文搜索配置
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;

-- 添加中文向量列
ALTER TABLE event_search ADD COLUMN IF NOT EXISTS chinese_vector tsvector;

-- 对已有数据进行中文分词处理
UPDATE event_search
SET chinese_vector =
  CASE
    WHEN event_search.key = 'content.body' AND TRIM(event_json.json::jsonb->'content'->>'body') != ''
      THEN to_tsvector('chinese', event_json.json::jsonb->'content'->>'body')
    WHEN event_search.key = 'content.name' AND TRIM(event_json.json::jsonb->'content'->>'name') != ''
      THEN to_tsvector('chinese', event_json.json::jsonb->'content'->>'name')
    WHEN event_search.key = 'content.topic' AND TRIM(event_json.json::jsonb->'content'->>'topic') != ''
      THEN to_tsvector('chinese', event_json.json::jsonb->'content'->>'topic')
    ELSE NULL
  END
FROM
  event_json
WHERE
  event_search.event_id = event_json.event_id
  AND (
    event_search.chinese_vector IS NULL
    OR event_search.chinese_vector::text = ''
  );

-- 创建中文索引
CREATE INDEX CONCURRENTLY event_search_chinese_vector_idx ON event_search USING GIN (chinese_vector);

将修改后的 search.py 文件映射至 Synapse 容器,删除之前的容器,运行如下命令重新创建容器:

docker run -d \
  --name synapse \
  --restart always \
  -v $(pwd)/synapse:/data \
  -v $(pwd)/synapse/search.py:/usr/local/lib/python3.13/site-packages/synapse/storage/databases/main/search.py \
  -u 1000:1000 \
  -p 8008:8008 \
  matrixdotorg/synapse:latest
注意
更新 Synapse 版本后,请注意原始 search.py 是否发生变化,如有则需要重新修改支持中文的 search.py。同时请注意 Dockerfile 中镜像基于的系统环境和 Python 版本是否发生变化,如有则需要对应调整将修改后 search.py 文件的映射路径。

发现服务

提示
如果希望使用主域名 example.com 成为 Matrix 服务域名(例如:@user:example.com),则需要配置发现服务。如果希望使用子域名 matrix-homeserver.example.com 成为 Matrix 服务域名(例如:@user:matrix-homeserver.example.com),则可以跳过本节。

发现服务是 Matrix 网络发现服务器位置的一种方式。因为实际服务运行在子域名 matrix-homeserver.example.com 上,需要让其他服务器和客户端知道我们使用主域名,因此需要提供 /.well-known/matrix 信息。因此需要将 https://example.com/.well-known/matrix 映射到 https://matrix-homeserver.example.com/.well-known/matrix,相关细节请参考官方文档

注册用户

Synapse 服务默认是禁止自助注册用户的,运行如下命令进入 Synapse 容器:

docker exec -it synapse /bin/bash

运行如下命令创建用户:

register_new_matrix_user http://localhost:8008 \
  -c /data/homeserver.yaml -a \
  -u "<用户名>" \
  -p "<密码>"

开始使用

在浏览器上打开 https://app.element.io,单击 Sign in 切换 Homeserver 到 example.com,输入用户名和密码即可登录。

部署 frp 内网穿透服务

2026-04-10 08:00:00

环境信息

frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转 1

frp 架构图

本教程将介绍在具有公网 IP 的服务器和内网路由器上部署 frp 内网穿透服务。本教程涉及到的环境信息如下:

环境 系统
服务端 外网服务器系统 Ubuntu 24.04
客户端 内网路由器系统 OpenWRT 24.10
注意
将后续命令中的 example.com 替换为实际域名。

证书申请

frp 证书

在本地创建 cert 目录,将 OpenSSL 配置文件复制到该目录。通常情况下 Linux 系统位于 /etc/pki/tls/openssl.cnf,macOS 系统位于 /System/Library/OpenSSL/openssl.cnf

运行如下命令生成 ca 证书:

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.com" -days 36500 -out ca.crt

运行如下命令生成服务端证书:

openssl genrsa -out server.key 2048
openssl req -new -sha256 -key server.key \
  -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=example.com" \
  -reqexts SAN \
  -config <(cat openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:*.example.com")) \
  -out server.csr
openssl x509 -req -days 36500 -sha256 \
  -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.com") \
  -out server.crt

运行如下命令生成客户端证书:

openssl genrsa -out client.key 2048
openssl req -new -sha256 -key client.key \
  -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=example.com" \
  -reqexts SAN \
  -config <(cat openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:*.example.com")) \
  -out client.csr
openssl x509 -req -days 36500 -sha256 \
  -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.com") \
  -out client.crt

由于 server.crtclient.crt 都是由 ca 签发的,因此他们对于 ca 来说都是合法的。

Nginx 证书

在服务器上运行如下命令安装 acme.sh:

curl https://get.acme.sh | sh -s email=[email protected]

安装脚本将执行如下动作:

  1. $HOME 目录创建 .acme.sh 目录并安装 acme.sh。
  2. 创建别名 acme.sh 指向 $HOME/.acme.sh/acme.sh
  3. 创建每日定时任务以便更新证书。

以阿里云域名管理为例,在 https://ram.console.aliyun.com/ 页面创建用户,并为用户赋予 DNS 相关管理权限。为用户创建 AccessKey,并设置如下环境变量:

export Ali_Key="xxx"
export Ali_Secret="xxx"

运行如下命令申请证书:

acme.sh --issue --dns dns_ali -d example.com -d *.example.com

frp 配置

注意
将后续命令中的 /path/to 替换为对应文件的实际路径,将 xxx 替换为实际内容。

服务端

在服务端创建 frp 目录,配置 frps.toml 文件参数如下,更多参数设置请参阅 frp 文档

bindAddr = "0.0.0.0"
bindPort = 7000
quicBindPort = 7000
vhostHTTPPort = 8080
vhostHTTPSPort = 8443
tcpmuxHTTPConnectPort = 5002

auth.method = "token"
auth.token = "xxx"

transport.tls.certFile = "/path/to/server.crt"
transport.tls.keyFile = "/path/to/server.key"
transport.tls.trustedCaFile = "/path/to/ca.crt"

webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "xxx"
webServer.password = "xxx"

log.to = "/path/to/frps.log"
log.level = "info"
log.maxDays = 3
注意
请确保将上述配置中的端口针对 0.0.0.0/0 关闭防火墙拦截。

/etc/systemd/system 路径创建 frps.service 服务,配置内容如下:

[Unit]
Description = frp server
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
ExecStart = /path/to/frps -c /path/to/frps.toml

[Install]
WantedBy = multi-user.target

运行如下命令管理 frps 服务:

# 自启动 frps
sudo systemctl enable frps

# 启动 frps
sudo systemctl start frps

# 停止 frps
sudo systemctl stop frps

# 重启 frps
sudo systemctl restart frps

# 查看 frps 状态
sudo systemctl status frps

添加如下内容至 Nginx 配置文件中:

server {
    listen 80;
    listen [::]:80;

    server_name *.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name *.example.com;

    ssl_certificate /path/to/example.com.cer;
    ssl_certificate_key /path/to/example.com.key;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_redirect off;
        proxy_ssl_server_name on;

        proxy_set_header Host $host:80;
        proxy_set_header Referer $http_referer;
        proxy_set_header Cookie $http_cookie;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

运行如下命令重启 Nginx:

sudo systemctl restart nginx

客户端

注意
将后续命令中的 x.x.x.x 替换为本地服务对应的 IP 地址。

在客户端创建 frp 目录,配置 frpc.toml 文件参数如下,更多参数设置请参阅 frp 文档

auth.method = "token"
auth.token = "xxx"

user = "xxx"

serverAddr = "frps.example.com"
serverPort = 7000

transport.protocol = "quic"
transport.proxyProtocolVersion = "v2"
transport.tls.certFile = "/path/to/client.crt"
transport.tls.keyFile = "/path/to/client.key"
transport.tls.trustedCaFile = "/path/to/ca.crt"

webServer.addr = "0.0.0.0"
webServer.port = 7400
webServer.user = "xxx"
webServer.password = "xxx"

log.to = "/path/to/frpc.log"
log.level = "info"
log.maxDays = 3

[[proxies]]
name = "example-http"
type = "http"
localIP = "x.x.x.x"
localPort = 80
customDomains = ["example-http.example.com"]

[[proxies]]
name = "example-ssh"
type = "tcpmux"
multiplexer = "httpconnect"
localIP = "x.x.x.x"
localPort = 22
customDomains = ["example-ssh.example.com"]

其中,example-http 采用了通过自定义域名的方式访问内网 Web 服务,更多示例请参考 frp 文档example-ssh 采用了多个 SSH 服务复用同一端口的方式连接内网 SSH 服务,更多示例请参考 frp 文档

/etc/init.d 路径下创建 frpc 服务,配置内容如下:

#!/bin/sh /etc/rc.common

# 使用 procd
USE_PROCD=1
# 启动顺序
START=95
# 停止顺序
STOP=15

# frpc
FRPC=/path/to/frpc
CONF=/path/to/frpc.toml

start_service() {
    procd_open_instance "frpc"
    procd_set_param command $FRPC -c $CONF
    procd_set_param respawn
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_set_param pidfile /var/run/frpc.pid
    procd_close_instance
}

service_triggers() {
    procd_add_reload_mount_trigger $CONF
}

运行如下命令管理 frpc 服务:

# 赋予执行权限
chmod +x /etc/init.d/frpc

# 自启动 frpc
/etc/init.d/frpc enable

# 启动 frpc
/etc/init.d/frpc start

# 停止 frpc
/etc/init.d/frpc stop

# 重启 frpc
/etc/init.d/frpc restart

# 查看 frpc 状态
/etc/init.d/frpc status

在服务商中配置 DNS 将 example-http.example.comexample-ssh.example.com 解析至 frp 服务器的 IP 地址。

连接

Web

此时,通过浏览器访问 https://example-http.example.com 即可实现访问内网 IP 地址 x.x.x.x 在端口 80 上的 Web 服务。

SSH

提示
请先在本地机器上安装 socat 工具。

此时,通过如下命令即可实现访问内网 IP 地址 x.x.x.x 在端口 22 上的 SSH 服务:

ssh -o 'proxycommand socat - PROXY:frps.example.com:%h:%p,proxyport=5002' [email protected]