Margrop
Articles216
Tags391
Categories23
1password AC AI AP API AppDaemon Aqara Caddy Cookie 认证 Cron Date Diagrams.net Docker HA HADashboard HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax MySQL NAS Nginx Node.js OpenAI OpenClaw OpenResty PPPoE PostgreSQL ProcessOn Prometheus Proxmox VE SOCKS5 SSL Shell TTS TimeMachine UML Uptime Kuma VPN VPS Web Windows activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit container crontab ctyun ddsm demo dependency deploy developer devtools dll dns docker domain download draw drawio dsm dump dylib edge exception export fail2ban feign firewall-cmd flow frp frpc frps fuckgfw function gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https idea image img img2kvm import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live low-code lvm lxc m3u8 mac macos mariadb markdown maven md5 microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas network nfs node node-red nodejs nohup notepad++ npm nssm ntp oop openfeign openssl os otp ovz packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp server slmgr so socks source spk spring springboot springfox ssh ssl stash string supernode svg svn swagger sync synology systemctl tap tap-windows tapwindows telecom template terminal tls token totp tvbox txt ubuntu udisk ui undertow uninstall unlocker upgrade url v2ray vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 中国电信 云电脑 交换机 代理 健康检查 光猫 公网IP 内存 内网IP 升级 反向代理 启动 夏令时 天猫精灵 天翼云 安全 安装 定时任务 容器 导入 小米 常用软件 广告屏蔽 序列号 应用市场 异常 打工 技术 抓包 描述文件 效率工具 日记 时区 显卡虚拟化 智能家居 智能音箱 梯子 模块 流程 流程图 浏览器 漫游 激活 火绒 玄学 电信 画图 监控 直播源 端口扫描 续期 网关 网络 网络风暴 群晖 脚本 腾讯 自动化 虚拟机 认证 证书 语雀 超时 路由 路由器 软件管家 软路由 运维 运维监控 部署 配置 钉钉 镜像 镜像源 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客

Hitokoto

Archive

当 npm install 遇到网络隔离:离线部署 Node.js 包实战指南

当 npm install 遇到网络隔离:离线部署 Node.js 包实战指南

当 npm install 遇到网络隔离:离线部署 Node.js 包实战指南

企业内网、生产环境、防火墙策略严格的服务器——这些场景下 npm install 经常遇到网络不通的问题。今天记录一次真实的离线部署案例,目标是 OpenClaw,但方法适用于任何 npm 包。

问题场景

目标服务器:内网 VM,Ubuntu 24.04,Node.js 24 已安装。

执行 npm install -g openclaw@latest 时报错:

1
2
3
4
npm error code 128
npm error An unknown git error occurred
npm error command git --no-replace-objects ls-remote ssh://[email protected]/whiskeysockets/libsignal-node.git
npm error fatal: Could not read from remote repository.

网络诊断结果:

目标 状态
api.github.com ✅ 可访问
github.com (HTTPS) ❌ TCP 443 超时
github.com (SSH) ❌ TCP 22 超时

API 可通但 TCP 握手失败——这说明防火墙放行了部分 GitHub 流量,但不是全部。

常规解法逐一尝试

方法 1:Git URL 重写

1
git config --global url.'https://github.com/'.insteadOf ssh://[email protected]/

结果:HTTPS 本身就在 TCP 层被拦截,此路不通。

方法 2:代理

内网有 SOCKS5/HTTP 代理,但配置繁琐且不稳定。

方法 3:Gitee 镜像

libsignal-node 不在 Gitee 上,镜像方案不适用。

最终方案:npm pack + SCP 离线安装

核心思路:在网络正常的机器上下载完整包,传到目标机器本地安装

Step 1:本地打包

在任意一台能访问 npm registry 的机器上(不需要是 Linux):

1
npm pack openclaw@latest

这会下载一个 tarball,而不是安装。如果包有 native 依赖需要编译,可能还需要连同 node_modules 一起打包:

1
2
3
4
5
6
# 在本地创建完整安装目录
mkdir openclaw-install && cd openclaw-install
npm install openclaw@latest --registry https://registry.npmjs.org/

# 打包
tar -czf openclaw-node_modules.tar.gz node_modules/

--ignore-scripts 适用于跳过 postinstall,但需要确保 node_modules 完整。

Step 2:传到目标机器

1
2
scp openclaw-*.tgz root@目标服务器:/tmp/
scp openclaw-node_modules.tar.gz root@目标服务器:/tmp/

内网 SCP 不受互联网防火墙影响,速度也很快。

Step 3:目标机器本地安装

1
2
3
4
5
6
# 先安装主包
npm install -g /tmp/openclaw-2026.3.13.tgz

# 如果遇到 dist/entry.(m)js missing 错误,说明 node_modules 不完整
# 解压完整的 node_modules
tar -xzf /tmp/openclaw-node_modules.tar.gz -C /usr/lib/node_modules/

验证

1
2
openclaw --version
# OpenClaw 2026.3.13 (61d171a)

常见坑

坑 1:postinstall 脚本被跳过导致缺少构建产物

1
Error: missing dist/entry.(m)js (build output)

原因:npm install --ignore-scripts 跳过了部分构建步骤。解决:完整打包 node_modules 后再传。

坑 2:native 模块版本不匹配

如果目标机器 Node.js 版本与打包机器不同,native 模块(如 sharplibsignal)可能无法运行。需要:

  • 确保 Node.js 大版本一致(建议使用 nodesource 安装相同版本)
  • 或在目标机器上单独编译 native 依赖

坑 3:可选依赖被跳过

npm install --ignore-scripts 也会跳过可选依赖。如果业务需要这些依赖,需要手动安装:

1
2
npm install -g /tmp/openclaw-*.tgz
npm install --prefix=/usr/lib/node_modules/openclaw <缺失的包>

总结

步骤 命令
本地打包 npm pack openclaw@latest
传文件 scp *.tgz root@target:/tmp/
安装 npm install -g /tmp/openclaw-*.tggz
补全 node_modules tar -xzf node_modules.tar.gz -C /usr/lib/node_modules/
验证 openclaw --version

这个方法比 npm ci --offline 更可靠,因为是完整的 tarball 而非 lockfile 驱动。

Author:Margrop
Link:http://blog.margrop.com/post/2026-03-22-npm-offline-deployment-guide/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可