前阵子在公司电脑上折腾 OpenClaw,原本以为就是一个普通的 npm install,结果卡在 libsignal-node 这个原生依赖上整整半天。报错信息刷了好几屏,全是 GitHub 下载超时、403。后来我把思路从“怎么把下载加速”换成了“干脆不走这条下载通道”,用 git 源码安装的方式彻底绕开了问题。这篇就把我当时的分析过程、踩坑记录和最终可用方案完整写下来,给同样在受限网络环境里装 OpenClaw 的朋友一个参考。文章会有点长,但每一步都是实际操作过的,照着走基本能一次跑通。你需要有一点 npm 和 git 基础,纯小白也能按命令执行,我会把每一步的目的也讲清楚。
1. 问题现场:npm install 卡死在 libsignal-node 上
1.1 这个报错到底长什么样
我在公司一台 Windows 11 电脑上执行 npm install,一开始进度条走得很顺畅,到了某个包的时候突然停住,然后抛出这么一段:
code复制> @signalapp/libsignal-node@0.50.3 install
> node-pre-gyp install --fallback-to-build
node-pre-gyp http GET https://github.com/signalapp/libsignal-node/releases/download/v0.50.3/...
node-pre-gyp http GET https://github.com/signalapp/libsignal-node/releases/download/v0.50.3/...: 403
node-pre-gyp ERR! ...
有些环境下会换成 ETIMEDOUT,有些是 ECONNRESET,还有的是 unable to verify the first certificate。不管哪一款,本质都一样:安装脚本尝试从 GitHub Releases 下载一个预编译好的二进制文件,结果网络请求被公司出口策略拦截了。
你可能会疑惑:网页能打开 GitHub 啊?这里有个关键细节:网页访问和 Releases 附件下载走的根本不是同一个域名。GitHub 的 release 附件实际存储在 objects.githubusercontent.com,很多公司的防火墙会对这个域名单独做限制。于是就会出现“网页能开、下载附件却超时”的诡异情况。
1.2 为什么公司电脑最容易中招
家用网络下装 OpenClaw 基本不会遇到这个问题,因为默认链路不会有人拦你。但公司电脑处于企业防火墙后面,有几个特点叠加起来,让安装过程特别容易翻车:
- 出口网络有统一管控,所有外部请求都要过白名单或审计系统;
- 很多公司对国外域名的连接做了限速或阻断,尤其是文件下载类请求;
- 安全终端软件(EDR/HIPS)会对安装脚本里的外联行为做拦截;
- 公司电脑通常没有管理员权限,想临时装编译工具链都费劲;
- HTTPS 流量可能会被 SSL 解密再重新加密,导致证书校验失败。
所以你会看到两种典型结局:第一种是下载阶段直接失败,npm install 终止;第二种是下载虽然失败但 npm 回退到本地编译,结果电脑上没装 Visual Studio Build Tools 或 Python,编译再次失败。两条路都走不通,安装就卡死了。
这个阶段最容易犯的错误是反复重试同一套流程,然后怀疑网络是不是又抽风了。其实问题的根源不在“网络不稳定”,而在网络边界策略与安装脚本行为不匹配。想明白这一点,后面方案就清晰了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 拆解 libsignal-node 的下载机制:为什么换镜像源也救不了
2.1 prebuild-install 和 node-gyp 的关系
要解决问题,先得搞清楚 npm install 到底做了什么。libsignal-node 不是纯 JavaScript 模块,它底层是对 Signal 协议库的 Node.js 绑定,属于“原生模块”。原生模块要能在目标平台上运行,必须编译成对应操作系统和 CPU 架构的二进制文件,在 Windows 上就是 .dll 配合 .node,在 Linux/macOS 上就是 .so 和 .node。
这类模块的安装脚本通常采用“先下载预编译产物,下载不到再本地编译”的策略。负责下载预编译产物的工具叫 prebuild-install,负责本地编译的工具链是 node-gyp。可以类比成:能直接买组装好的电脑就买组装好的,买不到才给你一堆零件自己装。--fallback-to-build 这个参数就是告诉它“下载失败就转入本地编译模式”。
问题在于,prebuild-install 默认会去 GitHub Releases 页面找匹配的二进制包。它会把下载地址写死成类似 https://github.com/{owner}/{repo}/releases/download/{version}/... 的形式。这个下载动作发生在 npm 包的 install 脚本阶段,也就是 npm install 拿到包之后、把包放进 node_modules 之后的事。
2.2 为什么改 npm 镜像源解决不了
很多同学第一反应是:“npm 下载慢?那就把 registry 换成国内镜像源。”这个操作本身没错,它确实能解决 npm 包本体从 registry.npmjs.org 下载慢的问题。但对于 libsignal-node 这类原生模块,镜像源能帮你的很有限。
因为 npm registry 镜像源只负责托管 npm 包本身,而 prebuild-install 的下载请求是直接发给 GitHub Releases 的。这条链路完全绕过了 registry。说白了,npm 包是一堆源码和一个安装脚本,真正的二进制是安装脚本在执行时才去外部拉取的。你把包下载得再快,安装脚本照样会去访问 GitHub Releases,照样被防火墙卡住。
我见过有人在 .npmrc 里把很多地址都改成镜像,结果安装脚本里的 URL 是编译进代码里的,改配置根本覆盖不到。所以如果你只做了 registry 镜像替换,大概率还是会在同一个地方失败。这不是操作不对,而是没打中要害。
2.3 什么情况下才需要走源码编译
那是不是只能放弃在公司电脑装 OpenClaw?不是。绕开 GitHub Releases 下载的路子其实有两条:一是让安装脚本“不要下载,直接本地编译”,二是把源码 clone 下来自己手动编译。两者本质一样,都是走源码安装路线。
源码编译不依赖 GitHub Releases,只要源码能拿到,比如通过 git clone 或 npm 包内自带的源码目录,就能在本地生成二进制文件。这样一来,网络边界只涉及两个环节:git clone 源码、npm 从 registry 拉取依赖。这两个通道相对更容易在公司网络里放行,尤其是 npm registry 我们还能配置成合规的内部镜像。
当然,本地编译也不是什么代价都没有。它需要完整的编译工具链,Windows 上必须装 Visual Studio Build Tools + Python,Linux 上需要 build-essential,macOS 需要 Xcode Command Line Tools。如果 libsignal-node 的构建依赖 Rust,那还得把 Rust 工具链也装上。公司电脑权限受限的话,这会成为新的门槛。但这些问题都属于“一次性投入”,装好之后以后编译任何原生模块都能用。
3. 彻底解决:git 源码安装 OpenClaw 完整实操
3.1 安装前的环境三件套
动手之前,先把环境基础打好。我按 Windows 为例,Linux/macOS 命令有所不同但思路一致。
第一件:Node.js LTS 版本。建议装 18 或 20,具体看 OpenClaw 的 engine 要求。在公司电脑上如果已经有 nvm 或 fnm 这类版本管理工具会更方便,没有的话直接安装系统版本也行。
第二件:Git。一般开发机都会有,没有就去 Git 官网下载安装包。安装时注意勾选“Add to PATH”,后面所有命令都要用。
第三件:编译工具链。Windows 上最省事的方式是安装 Visual Studio Build Tools,在安装器里勾选“使用 C++ 的桌面开发”工作负载。注意不需要装整个 Visual Studio IDE,Build Tools 单独安装器就够了。然后再装一个 Python 3.x,node-gyp 编译时依赖 Python,建议勾选安装时加入 PATH。
如果公司电脑没有管理员权限,装不了这些系统级软件,有几个变通方向:优先看公司软件中心有没有提供这些工具,很多企业有统一软件分发平台;或者尝试用户级安装,Visual Studio Build Tools 部分组件支持用户级,但体验会差一些;实在不行就得和 IT 申请,把这几个工具加入白名单。这一步不要硬抗,我在没有管理员权限的机器上手动折腾过,最后大概率会卡在某个权限点上。
3.2 克隆 OpenClaw 主项目源码
环境准备好之后,第一步不是 npm install,而是用 git 把 OpenClaw 主项目源码 clone 下来。这里有个前提:确认公司网络允许 git 协议访问目标仓库。判断方法很简单,直接执行:
bash复制git clone https://github.com/<你的OpenClaw仓库地址>/openclaw.git
cd openclaw
如果 clone 成功,说明 git 出网通道是通的。如果 git clone 也失败,比如卡在 remote: Enumerating objects 之后不动,那说明公司网络对 github.com 本身也做了限制。这时候需要先解决 git 通道问题,优先找公司内部是否已经做了代码镜像,或者咨询网络管理员放行对应域名。我这里不建议你自己去尝试各种绕过手段,一是企业安全审计大概率会拦,二是即便通了,后续所有安装行为都可能触发告警,反而得不偿失。
clone 完成后,用你自己的账号或者通过 internal 分支继续后面的操作。如果公司内网有 OpenClaw 的镜像仓库,直接把 clone 地址换成内网地址,后面的步骤没有任何区别。
3.3 配置 npm registry 和确认依赖版本
进入项目目录后,先把 npm registry 配置成国内可正常访问的镜像,这里我用的是 npmmirror:
bash复制npm config set registry https://registry.npmmirror.com
npm config get registry
注意,这个配置只影响 npm 包从 registry 的下载,解决的是 npm install 阶段主依赖包的获取速度。它不会改变 prebuild-install 的 GitHub Releases 下载行为,所以后面还得有别的动作。
接下来确认 libsignal-node 在 OpenClaw 依赖树里的版本号。不同版本编译方式和产物结构可能有差别,先查清楚才不会白编译:
bash复制cat package-lock.json | grep -A 5 "libsignal-node"
或者用 npm 命令直接查:
bash复制npm ls libsignal-node
记下精确版本号,比如 0.50.3,后面 clone 源码时要按这个版本切 tag。
3.4 分步安装:先跳过脚本,再单独处理原生模块
这是整个方案的关键一步。正常执行 npm install 会在 libsignal-node 的 install 阶段触发 prebuild-install,然后卡死。所以我们换个策略:先跳过所有安装脚本,把纯 JS 依赖完整铺到 node_modules 里,再单独处理 libsignal-node。
执行:
bash复制npm install --ignore-scripts
--ignore-scripts 的意思是“执行安装,但不跑任何 install 阶段的脚本”。这样 prebuild-install 不会被触发,GitHub Releases 的下载请求自然也就不会出现。这一步会正常拉取 OpenClaw 的所有依赖包,包括 libsignal-node 的 JS 入口文件,只是不会生成最终的 .node 二进制。
执行完你会看到 node_modules 里已经有 libsignal-node 的目录了,但里面没有编译产物,正常现象,不用慌。缺的就是最后一块拼图。
3.5 手动编译 libsignal-node 源码
现在进入核心环节:把 libsignal-node 的源码 clone 下来,在本地编译出二进制文件。
bash复制git clone --branch v0.50.3 https://github.com/signalapp/libsignal-node.git
cd libsignal-node
注意把分支名换成你刚才查到的版本号。如果仓库有子模块,clone 时加 --recurse-submodules,免得后面缺文件:
bash复制git clone --branch v0.50.3 --recurse-submodules https://github.com/signalapp/libsignal-node.git
cd libsignal-node
然后执行源码安装,强制从源码构建:
bash复制npm_config_build_from_source=true npm install
如果这个项目底层涉及 Rust 绑定,npm install 过程中可能会自动调用 cargo build,所以提前确认 Rust 工具链已安装:
bash复制rustc --version
cargo --version
没有装的话,用 rustup 装一份,默认 stable 通道即可。公司电脑如果禁止网络安装 rustup,那就得走离线安装包,或者再联系 IT。
编译过程可能会持续几分钟,期间会有大量编译日志输出。看到类似这样一段,说明编译成功:
code复制> libsignal-node@0.50.3 install
> node-pre-gyp install --build-from-source
... build/Release/libsignal_node.node created
编译完成后,确认产物文件存在:
bash复制ls build/Release/
正常情况下能看到 .node 结尾的原生模块文件。如果名字不叫 libsignal_node.node,以实际打包名称为准,后续复制时保持一致即可。
3.6 把编译产物接回 OpenClaw 项目
编译好的二进制要回到 OpenClaw 的 node_modules 里,才能被运行时加载。复制操作很简单,Windows 下用:
bash复制copy build\Release\libsignal_node.node ..\openclaw\node_modules\@signalapp\libsignal-node\build\Release\
Linux/macOS 下用:
bash复制cp build/Release/libsignal_node.node ../openclaw/node_modules/@signalapp/libsignal-node/build/Release/
路径里的 @signalapp 是 npm scope 目录,如果你的版本包名不同,进去看实际目录结构就行。复制完毕后,验证一下模块能不能被 Node 正常加载:
bash复制cd ../openclaw
node -e "const s = require('@signalapp/libsignal-node'); console.log('libsignal-node loaded ok')"
如果输出 loaded ok,说明原生模块已经就位。如果报错,看是不是路径不对,或者编译产物与当前 Node 版本 ABI 不匹配。ABI 不匹配的话,最直接的办法是保证编译时用的 Node 版本与运行时一致,重新编译一遍。
3.7 后续 npm install 的固话处理
这一步做完,OpenClaw 主体依赖已经齐了。但有个隐患:以后如果重新跑 npm install,脚本会再次尝试下载 libsignal-node 的预编译二进制,大概率还会失败。所以要固化方案。
比较省事的做法是在项目根目录添加 .npmrc,写入:
code复制build-from-source=true
这样以后 npm install 默认就走源码构建,不会再尝试下载 release。配合 --ignore-scripts 的话,需要每次都手动带上这个参数。更好的做法是把 libsignal-node 编译用的源码和命令写成一个 shell 脚本,放进项目 scripts 目录,团队内部其他同事遇到同样问题也能一键重建。
如果你有权限维护内部 npm 私服,还可以把编译好的二进制或整个包发布到私服,其他人直接从私服安装。这个属于团队基建,工作量不小,但对长期使用价值很大。
4. 踩坑排查:企业网络下 OpenClaw 安装高频问题速查
4.1 问题速查表
整个安装过程我前后踩了不少坑,整理成一张速查表,按症状查原因和解决方案,遇到类似问题可以直接对照:
| 症状 | 可能原因 | 解决思路 |
|---|---|---|
| npm install 卡在 libsignal-node | prebuild-install 下载 GitHub Releases 被拦截 | 用 --ignore-scripts 跳过脚本,再手动编译 |
报错 403 或 ETIMEDOUT |
github.com 或 objects.githubusercontent.com 不可达 | 不走 Releases 下载,改用 git 源码编译 |
报错 unable to verify the first certificate |
公司 SSL 解密导致证书链不被 Node 信任 | 将内部 CA 证书加入系统信任库,或配置 NODE_EXTRA_CA_CERTS 指向内部证书文件 |
node-gyp 报 gyp ERR! find Python |
没有安装 Python,或未加入 PATH | 安装 Python 3.x,勾选 Add to PATH |
node-gyp 报 MSBuild 相关错误 |
Windows 缺少 C++ 编译工具链 | 安装 Visual Studio Build Tools,勾选“使用 C++ 的桌面开发” |
编译产物加载时报 NODE_MODULE_VERSION 不匹配 |
编译时 Node 版本与运行时不同 | 用与 OpenClaw 运行时相同的 Node 版本重新编译 |
| clone 某些仓库时卡在子模块 | 子模块递归拉取失败 | clone 时加 --recurse-submodules |
安装完成后启动报 unknown model: deepseek |
模型标识符配置写法不对 | 检查配置文件里的模型名,确认和当前接入的模型服务一致 |
| 启动后 Control UI 不出现 | 端口被占用,或浏览器安全策略拦截 | 检查 3000/8080 等端口占用情况,换浏览器或明确本机访问地址 |
以上每条都是我在实际安装过程中遇到过或验证过的对应解法。其中“证书不信任”那条在公司电脑上特别常见,因为不少企业会做 HTTPS 解密审计,Node 默认的 CA 列表里没有公司内部根证书,就会报证书链错误。
4.2 三个最容易误判的地方
第一个误判是把所有问题都归结为“网络不稳定”。我在一开始也反复重试 npm install,每次都卡在同一个位置,其实这不是运气问题,是结构性限制。反复重试除了浪费时间,还有可能触发安全软件的频率告警。正确做法是先定位是哪个请求被拦截,再决定绕行方案。
第二个误判是以为操作系统配了网络的某些设置就能解决问题。在公司电脑上,这类操作很容易被安全策略阻断,而且会留下审计记录。比起折腾系统层面的网络设置,不如直接改变安装策略,让它根本不依赖那条被限制的下载链路。
第三个误判是认为手动编译一次就一劳永逸。如果你后面更新了 Node 版本、切换了 npm 缓存目录、或者同事在同一台电脑上重新装了环境,都需要重新走一遍编译流程。所以我建议把方案固化成脚本,放进项目里,别让整个过程依赖人肉记忆。
4.3 公司电脑权限受限时的替代思路
如果公司电脑完全不给装编译工具链,但你又确实需要跑 OpenClaw,可选的路径还有两条。
第一条是找一台不受限制的机器做离线构建,把编译好的 node_modules 目录整个打包,拷贝到公司电脑解压使用。需要保证 Node 版本一致,否则原生模块 ABI 不兼容,依然加载不了。这种方式适合临时验证,不适合长期开发,因为依赖更新会很痛苦。
第二条是询问公司内部是否有统一的 Node 开发环境镜像,有些企业会有内部 Docker registry 或开发环境模板,把 OpenClaw 相关的依赖全部打进镜像里,作为内部标准环境。这个需要和基础设施团队沟通,但一旦有了,后续所有同事都能受益。
5. 最后分享一点个人体会
这次折腾下来,我最大的感受是:在公司网络下安装开源项目,第一反应不应该是“怎么把下载搞得再快一点”,而是先梳理清楚“安装过程中到底有哪些请求会走到公司边界之外”。能绕开就绕开,绕不开就找公司 IT 要合规通道。用 git 源码编译的方式解决 libsignal-node 下载问题,本质就是让安装过程从“依赖一个被限制的外部资源”变成“在本地完整构建”。虽然前期准备工具链花了一点时间,但跑通一次之后,后面重建 OpenClaw 环境都会非常顺。
还有一个很务实的小建议:如果你的团队不止一个人用 OpenClaw,建议把你编译好的二进制、源码 clone 地址和整个安装脚本归档到一个团队可见的位置,比如内网 Wiki 或代码仓库里的 docs 目录。下次同事遇到同样的报错,直接把文档丢过去,按步骤操作就行。省下的时间,远比你在那一个小时一个小时帮别人排查要多。
