新闻详情

新闻详情

首页 / 资讯中心 / 详情

Nexus3内网私库搭建:Maven、Yum、Apt、Nodejs统一私有源

发布时间:2026/10/1 16:19:16来源:尧图网络
Nexus3内网私库搭建:Maven、Yum、Apt、Nodejs统一私有源
内网交付做久了你会发现真正消耗工时的环节往往不在业务代码本身而卡在“把依赖搬进去”这一步。Maven 拉不到 jar、yum 装不上编译工具链、apt 卡在下载一半、nodejs 的 npm 包反复超时重试——外网环境里一条命令的事进了隔离网就得折腾一整天。Nexus3 私库环境搭建maven、yum、apt、nodejs这件事本质上就是把四种包管理器的分发中心收敛到同一台内网服务器上让所有开发机和构建机只认一个地址从此不再依赖公网、不再靠“谁去外面下载再拷U盘”这种原始手段。它的价值不只是省流量更重要的是构建结果可复现今天能编过的版本半年后重装环境还能编过因为依赖包一直躺在你自己的磁盘上。这篇文章面向的是需要在企业内网、实验室隔离网、客户现场落地一套统一私有源的运维和开发同学。不管你是第一次接触 Nexus3还是已经装过但被 yum 的 repodata、apt 的签名、npm 的认证折腾过这里都会把“为什么这么做”讲清楚。我会按 maven、yum、apt、nodejs 四条线从仓库类型选择、目录结构、客户端配置到踩坑排查一路走完中间涉及参数的地方都会给出具体的计算和取舍理由你照着抄基本能一次跑通。1. 先想清楚为什么是 Nexus3以及它能覆盖到什么程度1.1 四个包管理器的共同痛点和各自的脾气maven、yum、apt、npm 这四样东西表面上都是“下载依赖”但协议和元数据格式完全不同混在一起讲最容易糊涂。Maven 走的是 HTTP 上的标准目录结构加 XML 元数据靠 pom 文件描述依赖关系仓库地址写死在settings.xml或pom.xml里yum 走的是repodata/repomd.xml这个入口通过它索引所有 rpm 及其依赖关系apt 走的是Packages和Release两层元数据靠 GPG 签名保证来源可信npm 则是 JSON 描述加 tarball 下载认证方式比前三个都灵活也更容易配错。理解了这四套机制的差异你就能明白为什么 Nexus3 不能对它们一视同仁。Nexus3 原生支持 maven 和 npm 的完整语义包括 hosted、proxy、group 三种角色对 yum 的支持在早期版本里只有 proxy 一种形态对 apt 则完全没有原生仓库类型必须借助 raw原始文件仓库自己拼目录。这不是 Nexus3 的缺陷而是 apt 那套“由发行版维护者签名”的模型本来就不适合由第三方托管平台直接代劳。所以本文的路线是maven 和 npm 用原生仓库类型走标准流程yum 和 apt 用 raw 仓库加本地元数据生成工具补齐这是目前内网落地最普遍、也最容易维护的做法。另一个必须提前想清楚的问题是代理层。内网服务器能不能访问公网直接决定了你是只搭 hosted本地托管还是同时搭 proxy代理上游。如果机房只有一台机器能出网那就让 Nexus 这台机器出网其他所有开发机构建机都指向它由它统一去公网拉包并缓存下来。这个设计的好处是缓冲区集中、出口只有一个、审计也方便。如果整网全封闭那就只能靠外部机器下载好再导入这条路后面会专门讲。提示在动手之前先确认三件事——服务器能不能出网、要服务多少台客户端、有没有国产发行版需要兼容。这三件事决定了仓库类型的组合方式等装完再改会返工。1.2 部署形态的取舍tar 包、容器还是系统包Nexus3 官方提供三种部署形态。第一种是 tar.gz 免安装包解压后配置bin/nexus.vmoptions和etc/nexus-default.properties用自带脚本启动最直观出问题排查也最简单我一般推荐现场首次部署用这个。第二种是 Docker 镜像优点是环境隔离干净、升级只需换 tag缺点是数据目录要挂载出来而且容器的 JVM 内存限制和文件句柄数需要额外处理不熟悉容器的话反而多一层坑。第三种是系统包管理安装把 Nexus 注册成系统服务升级方便但对系统环境有侵入而且国内镜像源里未必有最新版本。我选 tar 包的核心理由是可控性。Nexus 是个吃内存的 Java 应用默认nexus.vmoptions里堆内存给到了 2703MB堆外直接内存也是 2703MB加起来光 JVM 就要预留 5GB 以上再加上文件缓存实际至少要给 8GB 内存、4 核 CPU 才跑得舒服。用 tar 包我可以直接改这个文件把参数调整到和机器规格匹配用容器就得在启动参数里覆盖多一次转译。如果你是在只有 4GB 内存的测试机上试水把-Xms和-Xmx都改到 1200MB 左右、MaxDirectMemorySize改到 1200MB也能跑起来只是大仓库索引时会慢一点。磁盘规划同样要在部署前定好。Nexus 的数据目录默认是安装目录下的sonatype-work/nexus3里面包含 blob store实际的文件存储和数据库。这个目录会随着包数量持续增长一个中等规模的 maven 私库加上几个 yum 源一年下来几十 GB 很常见。所以建议单独挂一块数据盘把sonatype-work软链或者通过配置指到数据盘上系统盘只放程序。这样将来磁盘满了或者要迁移机器直接搬盘或者整目录打包就行不用碰程序。2. 从零把 Nexus3 跑起来2.1 环境准备与安装包获取服务器基线建议是 4 核 8GB 起步操作系统用你团队最熟的那个发行版就行没有强制要求。需要提前确认的是 JDK 版本Nexus 3.x 的不同小版本对 JDK 要求不一样早期版本用 JDK 8较新的版本已经要求 JDK 8 或 JDK 11再往后的版本甚至要求 JDK 17。最稳妥的方式是直接看你要装的版本对应的官方说明或者干脆用安装包自带的 JVM 检测逻辑——Nexus 启动脚本会去找JAVA_HOME找不到就报错。如果服务器本身没网就需要在一台有网的机器上把安装包下好再传进去。这时候你其实已经需要一套临时的分发手段了U盘、内部文件服务器、SCP 都行先把包搬进去后续 yum 和 apt 的私库搭好之后这类传输就能彻底告别。# 在能出网的机器上准备 mkdir -p /opt/nexus-install cd /opt/nexus-install # 下载完成后记录校验值传输后核对避免半包 sha256sum nexus-3.x.x-01-unix.tar.gz nexus.sha256传输到目标机之后先核对哈希再解压这一步不要省。我遇到过不止一次因为传输中断导致解压出来的 jar 包损坏Nexus 启动到一半报类找不到排查方向完全跑偏。核对完解压到/opt下目录名带版本号方便以后并存升级。2.2 关键配置调整与开机自启解压完成后先别急着启动有两处配置值得改。第一处是bin/nexus.vmoptions把内存参数按实际机器规格调整。第二处是etc/nexus-default.properties这里定义了监听地址和端口默认是0.0.0.0:8081如果你的机器有多张网卡建议绑定到内网那张网卡的 IP避免意外暴露。上下文路径默认是/如果你希望所有仓库地址都带一个统一前缀比如/nexus也可以在这里改但改了之后所有客户端配置的 URL 都要跟着加前缀中途改会很痛苦建议一开始就定下来。用 systemd 托管比用nohup起脚本可靠得多尤其是服务器重启后能自动拉起。下面是我常用的 unit 文件写法注意LimitNOFILE必须调大Nexus 在高并发拉包时会打开大量文件句柄默认的 1024 完全不够会报 too many open files 然后拒绝服务。# /etc/systemd/system/nexus.service [Unit] DescriptionNexus Repository Manager Afternetwork.target [Service] Typeforking LimitNOFILE65536 ExecStart/opt/nexus-3.x.x/bin/nexus start ExecStop/opt/nexus-3.x.x/bin/nexus stop Usernexus Restarton-abort TimeoutSec600 [Install] WantedBymulti-user.target这里有个细节建议单独创建一个nexus用户来跑服务而不是用 root。原因不只是安全还因为如果将来要调整数据目录权限明确的服务账号会让权限问题好定位得多。创建用户之后记得把程序目录和数据目录的属主都改过去否则启动时会因为写不了日志而失败。启动完成后用systemctl status nexus确认状态再用curl -I http://内网IP:8081看看有没有返回 200两步都通过说明服务本身没问题。首次登录需要拿到初始密码它不在日志里而是写在数据目录下的一个文件里路径大概长这样sonatype-work/nexus3/admin.password。用cat读出来登录登录后第一件事就是改密码并关掉匿名访问的写权限。很多人图省事不改结果内网里任何人都能往你的私库上传包这种污染在后期几乎无法清理因为分不清哪个 jar 是可信的。注意不要在同一个数据目录上跑两个 Nexus 实例即使端口不同也不行。数据目录里有锁文件强行启动会导致 blob store 索引损坏修复成本远高于重新搭一套。2.3 仓库规划先画好地图再开仓库在 UI 里点“新建仓库”之前先在纸上把命名规范定下来这一步能省掉后面无数次返工。我的命名习惯是“包类型-用途-角色”比如maven-releases、maven-snapshots、maven-central、npm-group、yum-raw、apt-raw。名字一旦被客户端写进配置文件改名的成本就是全量机器改配置所以命名要一次到位。另一个提前要定的是“对外暴露哪个地址”。Nexus 的 group 仓库可以把多个仓库聚合成一个入口客户端只需要配一个 URL 就能同时访问本地包和上游代理包。这种设计是内网私库的核心价值之一开发同学不用关心包是从哪来的配一个地址就能用。所以我建议每种包类型都建一个 group 作为统一入口hosted 和 proxy 都挂到 group 下面客户端永远只连 group。仓库名类型作用是否对客户端暴露maven-releaseshosted内部正式版本构件通过 group 间接暴露maven-snapshotshosted内部快照版本构件通过 group 间接暴露maven-centralproxy代理公共中央仓库通过 group 间接暴露maven-publicgroup统一入口是npm-hostedhosted内部私有 npm 包通过 group 间接暴露npm-proxyproxy代理公共 npm 源通过 group 间接暴露npm-groupgroup统一入口是yum-rawraw存放自建 rpm 仓库文件是apt-rawraw存放自建 deb 仓库文件是binary-rawraw存放 nodejs 等二进制发行包是这张表就是我实际落地时的骨架后面所有配置都围绕它展开。你会注意到 yum 和 apt 直接暴露 raw 仓库没有 group 层原因是它们各自只需要一个源地址加一层聚合反而增加理解成本。3. Maven 私库三种仓库角色的完整闭环3.1 hosted、proxy、group 到底该怎么分工很多人第一次配 Maven 私库时会想当然地只建一个 hosted 仓库然后往里传包结果发现团队要用的第三方依赖根本传不完。这就是没搞清楚三种角色的分工。hosted 是“我自己的东西”用于存放公司内部开发的构件包括正式版和快照版proxy 是“别人的东西的镜像”用于代理公共中央仓库第一次请求时去上游拉取并缓存到本地之后再请求就直接命中缓存group 是“把上面两类聚合成一个入口”客户端只配它即可。Maven 的 hosted 仓库有一个容易被忽略的细节正式版和快照版必须分仓库。原因是 Nexus 对 hosted 仓库有一个Version policy属性取值为 Release 或 Snapshot它决定了这个仓库接不接受带-SNAPSHOT后缀的构件。如果你把两者混在一个仓库里要么快照传不上去要么正式版被快照覆盖两种情况都是灾难。所以老老实实建两个maven-releases选 Release 策略maven-snapshots选 Snapshot 策略。proxy 仓库的配置重点是Remote storage这个上游地址以及缓存策略。公共中央仓库地址填官方那个即可。如果内网访问上游不稳定可以在HTTP配置里把连接超时和读取超时调大一点默认值在内网环境偶尔会因为延迟抖动导致拉取失败并缓存一个失败标记。这个失败标记有个坑就是它的默认存活时间比较长导致你明明网络已经好了重新拉还是报错必须手动清缓存或者加-U参数强制更新。3.2 创建仓库的具体动作顺序顺序很重要因为 group 在创建时需要选择成员仓库如果成员还不存在就没法勾选。所以正确的顺序是先建两个 hosted再建 proxy最后建 group。group 里的成员顺序也有讲究Maven 会按顺序查找本地 hosted 排在前面意味着如果内部构件的 groupId 和公共仓库里的某个包重名优先命中内部版本这正是我们想要的效果。创建 hosted 时几个关键字段这样填Layout选maven2Version policy分别选Release和SnapshotStorage用默认的 blob store 即可Deployment policy选Allow redeploy是很多人的习惯但我建议正式版仓库把它设成Disallow redeploy这样可以避免同一个版本号被反复覆盖导致构建结果不可复现。快照仓库则可以放开因为快照本来就是可变的。proxy 仓库创建时Remote storage填公共仓库地址Version policy选Mixed因为它里面既有正式版也有快照。Storage里的Blob store和Strict content type validation保持默认即可。有一个选项叫Maximum component age指的是缓存多久后重新去上游检查更新正式版构件通常不会变可以设长一点比如几天快照则要短否则你拉到的永远是旧快照。group 仓库创建时把上面三个都勾上顺序是 releases、snapshots、central。这里有个小坑group 的Version policy也要选Mixed否则客户端拉快照时会报找不到。创建完成后Nexus 会给出每个仓库的访问地址形如http://内网IP:8081/repository/maven-public/这个地址待会儿要写进客户端的配置文件。3.3 客户端配置settings.xml 与 pom.xml 各管什么客户端这边有两个文件要改职责不同很多人会搞混。settings.xml是全局的管镜像地址和认证信息pom.xml是项目级的管这个项目发布到哪个仓库。镜像配置的作用是把所有对外部仓库的请求重定向到你的私库写法如下。!-- ~/.m2/settings.xml -- settings mirrors mirror idnexus-public/id nameinternal nexus/name urlhttp://192.168.10.20:8081/repository/maven-public//url mirrorOf*/mirrorOf /mirror /mirrors servers server idnexus-releases/id usernamedeployer/username password你的密码/password /server server idnexus-snapshots/id usernamedeployer/username password你的密码/password /server /servers /settings这里的mirrorOf取值是个容易踩的坑。用*表示拦截所有仓库请求包括你在 pom 里自己声明的其他仓库这在内网里是最省心的做法因为所有依赖都必须经过 Nexus 这一道。但如果团队里有人需要访问某个 Nexus 里没有代理的特殊仓库*就会把它也拦掉这时候要用external:*或者显式排除。我的建议是起步阶段用*等确实出现特殊需求再单独放行。pom.xml这边要加的是发布地址也就是distributionManagement节点把正式版和快照版分别指向对应仓库。注意这里的id必须和settings.xml里server的id完全一致这是 Maven 匹配认证信息的方式不一致就会出现 401而且报错信息往往很含糊让人以为是密码错了。distributionManagement repository idnexus-releases/id urlhttp://192.168.10.20:8081/repository/maven-releases//url /repository snapshotRepository idnexus-snapshots/id urlhttp://192.168.10.20:8081/repository/maven-snapshots//url /snapshotRepository /distributionManagement配置完成后mvn deploy就会把构件推到私库mvn clean install则会从私库拉依赖。判断是否真的走通了不要看有没有报错要看私库的浏览界面里有没有出现你刚部署的构件以及构建日志里下载地址是不是指向你的内网 IP。两者都对才算闭环。实操心得如果团队里有人用的是公司统一分发的 settings.xml改完记得确认一下镜像是否生效。最简单的验证方式是随便删掉本地仓库里的一个 jar然后mvn -U clean compile看日志里的下载 URL 是不是你的 Nexus 地址。4. yum 私库把 rpm 和 repodata 一起管起来4.1 yum 仓库的本质是 repodata 而不是 rpm搭 yum 私库前必须理解一件事客户端拉取时第一个请求的不是某个 rpm 包而是repodata/repomd.xml。这个文件是整个仓库的索引里面记录了所有包的文件列表、依赖关系、校验值。所以一个目录里就算堆满了 rpm 文件只要没有 repodatayum 也完全不认。这解释了很多人的困惑——明明包都放进去了客户端的yum makecache还是报“无法下载仓库元数据”。明白了这一点搭建思路就清晰了先在本地建一个目录放 rpm用createrepo_c生成元数据然后把整个目录结构通过某种方式暴露给客户端。暴露方式有两种一种是用 Nexus 的新版 yum hosted 仓库类型较新版本才提供能自动处理元数据另一种是用 raw 仓库直接托管生成好的目录。我两种都用过raw 方案更通用不受 Nexus 版本限制下面以 raw 为主讲。rpm 的来源可以是三种自研软件打包出来的、从上游仓库下载的、以及系统安装镜像里的。第一种不用多说第二种要注意依赖闭包问题因为你下载某个包时它的依赖可能不在同一个仓库里客户端装的时候会报依赖缺失。稳妥做法是先把一批包下载下来用一个干净的最小系统去试装把报缺的依赖逐个补进来直到能装上为止。这个过程可以用yumdownloader配合--resolve参数自动化把依赖一起拉下来。# 在有网的机器上把包和依赖一起下载到本地目录 mkdir -p /data/rpm-repo/base/x86_64 cd /data/rpm-repo/base/x86_64 yumdownloader --resolve --destdir. 你的包名 # 安装元数据生成工具 yum install -y createrepo_c # 生成元数据-d 表示生成 sqlite 索引老版本 yum 需要 createrepo_c -d .生成完之后你会看到一个repodata目录里面有repomd.xml和若干压缩的索引文件。整个base/x86_64目录连同 repodata 一起上传到 Nexus 的 raw 仓库上传路径要和客户端配置的 baseurl 严格对应一个字符都不能差。4.2 raw 仓库的严格内容校验是个拦路虎Nexus 的 raw 仓库在创建时有一个Strict Content Type Validation选项默认是开启的。开启状态下通过 HTTP PUT 上传文件时必须带上正确的Content-Type头否则会被拒绝。repodata 目录下的文件扩展名五花八门有.xml、.gz、.bz2、.sqlite还有完全没扩展名的primary、filelists等用脚本上传时如果没逐个设置 Content-Type会失败得很零碎。我一般直接把这个选项关掉因为 raw 仓库本来存的就是各种二进制文件严格校验只会增加麻烦。关掉之后上传用curl -T或者 UI 的“上传”按钮都能成功。这里还有个细节通过 UI 手动上传几十个文件效率太低建议写个循环脚本批量推同时记录每个文件的响应码失败的单独挑出来重传。#!/bin/bash NEXUS_URLhttp://192.168.10.20:8081/repository/yum-raw USERdeployer PASS你的密码 SRC_DIR/data/rpm-repo cd $SRC_DIR find . -type f | while read -r f; do # 去掉开头的 ./ target${f#./} code$(curl -s -o /dev/null -w %{http_code} \ -u $USER:$PASS --upload-file $f \ $NEXUS_URL/$target) if [ $code ! 201 ] [ $code ! 204 ]; then echo FAIL $code $target fi done上传完成后在 Nexus 的浏览界面里点进 raw 仓库确认repodata/repomd.xml能正常打开内容不是乱码也不是 404。这一步看起来简单但它能提前发现 90% 的路径问题。4.3 客户端 .repo 文件与缓存清理客户端这边新建一个.repo文件放到/etc/yum.repos.d/下内容如下。注意baseurl的结尾斜杠要和实际目录结构一致gpgcheck的取舍后面单独说。[inner-base] nameinternal base repo baseurlhttp://192.168.10.20:8081/repository/yum-raw/base/x86_64/ enabled1 gpgcheck0配好之后执行yum clean all再yum makecache这两个命令的顺序不能反。clean all会清掉旧的元数据缓存如果先makecache再clean等于白做。如果makecache报错先看错误信息里提到的 URL把它复制到浏览器或者用 curl 直接访问看看返回的是 404 还是超时。404 基本都是路径写错超时则多半是防火墙或者 Nexus 服务本身的问题。关于gpgcheck正式环境建议打开。做法是在构建 rpm 时用 GPG 密钥签名客户端导入公钥后在 repo 文件里配置gpgkey指向 key 的地址gpgcheck1。内网自己维护的仓库如果所有包都是自己打的签名能有效防止包被替换。如果只是临时用、包里还混着从各处下载的第三方 rpm那先关掉校验把流程跑通之后再逐步补齐签名。4.4 yum 元数据的更新与日常维护往仓库里加新包之后必须重新执行createrepo_c更新元数据否则客户端永远看不到新包。这一点不同于 MavenMaven 的 hosted 仓库加文件是即时的yum 有个“生成索引”的显式步骤。如果包的数量很多每次都全量重建会比较慢可以用--update参数做增量但增量更新的前提是旧元数据还在如果你把 repodata 删了再做增量结果会不完整。上传新元数据有一个原子性问题客户端在拉取元数据的过程中如果你正好在上传新文件可能拉到一半新一半旧导致校验失败。稳妥做法是先把新内容上传到一个临时目录全部传完后再一次性覆盖。Nexus 的 raw 仓库支持覆盖上传覆盖是瞬时的只有几个文件的切换时间风险窗口很小。另外客户端偶尔会遇到“元数据校验和不匹配”的报错这通常是因为本地缓存里存着旧版本的元数据文件。执行yum clean metadata清掉元数据缓存即可不用clean all那么彻底。这个报错在多台机器共用一个仓库、又频繁更新仓库时比较常见属于正常现象不用紧张。5. apt 私库没有原生仓库类型时怎么自己造5.1 apt 的元数据结构比 yum 复杂在哪apt 的元数据分两层。第一层是Packages文件它是一个纯文本索引每个包一段记录了包名、版本、架构、依赖以及最重要的Filename字段即 deb 文件的实际路径。第二层是Release文件它记录了这个仓库包含哪些组件、哪些架构以及各个索引文件的哈希值。客户端拿到 Release 后会用它里面的哈希去校验 Packages 文件有没有被篡改这就是 apt 的安全模型。正因为有这层签名和哈希校验apt 仓库不能像 yum 那样随便放几个文件就行。你可以选择完整实现这套结构用 GPG 签名客户端配置正常校验也可以走简化路线用[trustedyes]让客户端跳过校验。两种方式我都用过内网自建、包来源可控的场景下简化路线完全够用配置量小很多如果是多团队共用、包来源复杂那就老实签名。Nexus3 没有 apt 仓库类型所以只能建一个 raw 仓库来放这些文件。目录结构有两种选择一种是平铺把Packages.gz和所有 deb 包放在同一层客户端配置用deb [trustedyes] 地址 ./另一种是标准的dists/发行版/组件/binary-架构/三层结构。平铺的好处是简单缺点是一个仓库只能对应一个发行版一个架构多发行版就得建多个仓库。标准结构可以一个仓库容纳多发行版多架构适合规模大一点的场景。5.2 用 dpkg-scanpackages 生成索引生成 Packages 文件用的是dpkg-scanpackages命令它包含在dpkg-dev包里。基本用法是指定 deb 文件所在目录和一个 override 文件没有就写/dev/null输出重定向到 Packages 文件。目录参数有个讲究用.表示相对当前目录生成的Filename字段就是相对路径用绝对路径则会生成绝对路径这两个都不能直接用于 HTTP 仓库必须保证 Filename 是相对于仓库根目录的路径。# 准备目录 mkdir -p /data/deb-repo cd /data/deb-repo # 把 deb 包拷进来 # cp /path/to/*.deb . # 生成 Packages 索引-m 表示允许多版本共存 dpkg-scanpackages -m . /dev/null Packages # 压缩apt 默认优先读 .gz gzip -k -9 Packages # 查看索引内容确认 Filename 字段是相对路径 head -30 Packages-m参数要不要加取决于你的场景。默认情况下dpkg-scanpackages遇到同一个包的多个版本会报错退出原因是一个仓库里同一个包名同一架构只允许一个版本。加了-m就允许多版本共存适合你需要保留多个版本供不同机器选择的场景。但如果你的仓库只放一个版本不加-m更安全因为它能帮你发现重复包。生成完Packages和Packages.gz之后把它们和 deb 包一起上传到 Nexus 的 raw 仓库。同样要注意 strict content type validation 的问题Packages这个文件没有扩展名如果校验开着会传不上去所以要提前关掉。上传路径要和客户端 baseurl 对齐平铺结构下所有文件都在同一层。5.3 客户端 sources.list 的三种写法客户端配置写在/etc/apt/sources.list或者/etc/apt/sources.list.d/下的独立文件里。最简写法是平铺加跳过校验# /etc/apt/sources.list.d/inner.list deb [trustedyes] http://192.168.10.20:8081/repository/apt-raw/ ./这里末尾的./表示 Packages 文件位于仓库根目录。如果你用的是标准三层结构写法就变成deb [trustedyes] http://192.168.10.20:8081/repository/apt-raw/ focal main对应到服务端的目录就是dists/focal/main/binary-amd64/Packages.gz。注意客户端不需要写binary-amd64apt 会根据本机架构自动拼接这段路径。很多人配置失败就是因为把这段写进了 sources.list 里导致拼出来的路径多了一层。第三种是完整签名方式[trustedyes]换成[signed-by/etc/apt/keyrings/inner.gpg]服务端要在dists/focal/下提供Release、Release.gpg和InRelease三个文件。生成 Release 需要写一个描述文件把组件、架构、哈希都列出来然后用 GPG 签名。这套流程比较繁琐如果非必要内网场景我一般建议直接用[trustedyes]把精力花在控制包来源上更划算。注意apt-key这个命令在新版本 apt 里已经废弃并会打印警告网上很多老教程还在用它导入公钥。新写法是把公钥文件放到/etc/apt/keyrings/目录下然后在 sources.list 里用signed-by指定这样不会污染全局信任链。5.4 多架构与国产发行版的适配思路如果内网里既有 x86 服务器又有 ARM 服务器仓库就要支持多架构。平铺结构做不到必须用标准三层结构把binary-amd64和binary-arm64分别建好dpkg-scanpackages在生成索引时也要用不同的目录。注意不同架构的 Packages 文件里Architecture字段必须正确否则 apt 会认为这个包不适用于本机而跳过。部分国产发行版在 Debian 系基础上做了改动仓库配置的位置可能不是标准的/etc/apt/sources.list而是放在别的地方或者提供了图形化的源管理工具。遇到这种情况先用apt-cache policy看看当前的源配置生效情况再决定改哪个文件。加内网源的思路和标准 Debian 完全一样只是文件位置需要现场找一下不要想当然地以为一定是那个路径。6. Nodejs 与 npm 私库二进制分发和包托管两条线6.1 nodejs 本身的离线分发方案nodejs 在内网落地其实是两件事一件是 nodejs 运行时的分发另一件才是 npm 包的托管。很多时候大家只关注后者结果新机器上连 node 都装不上因为官网下载走的是公网。解决方案是把 nodejs 的发行包也放进 Nexus。官方提供的 Linux 发行包是免安装的 tar.xz 压缩包解压后配置一下 PATH 就能用这正是“免安装环境配置”这个说法的来源。做法是在 Nexus 里建一个 raw 仓库专门放二进制发行包把你要用的几个版本都传上去然后写个安装脚本给新机器用。#!/bin/bash # install-node.sh 用法: ./install-node.sh 18.20.4 VERSION${1:-18.20.4} NEXUShttp://192.168.10.20:8081/repository/binary-raw PREFIX/usr/local cd /tmp curl -fLO $NEXUS/nodejs/node-v${VERSION}-linux-x64.tar.xz tar -xJf node-v${VERSION}-linux-x64.tar.xz -C $PREFIX mv $PREFIX/node-v${VERSION}-linux-x64 $PREFIX/nodejs # 配置环境变量写到 profile.d 里全局生效 cat /etc/profile.d/nodejs.sh EOF export NODE_HOME/usr/local/nodejs export PATH$NODE_HOME/bin:$PATH EOF source /etc/profile.d/nodejs.sh node -v npm -v这个脚本的关键点是-f参数它让 curl 在遇到 404 时直接失败退出而不是把错误页面写进文件里。我见过因为没有-f下载下来一个 HTML 错误页解压时报“不是有效的压缩文件”排查半天才发现是路径写错。Windows 开发机同理把 zip 包传上去写个 PowerShell 脚本下载解压然后手动加到系统 PATH。这里就引出了那个特别常见的报错。6.2 npm 原生仓库的三种角色配置npm 在 Nexus 里的配置方式和 Maven 类似也是 hosted、proxy、group 三角色。proxy 指向公共 npm 源用来缓存外部的公共包hosted 存放公司内部的私有包group 作为统一入口。创建时的关键点是 npm 仓库有自己的端口映射逻辑你可以在仓库配置里看到一个http端口设置早期做法是给 npm 单独开一个端口比如 8082然后用http://内网IP:8082/作为 registry。现在的做法更推荐不单独开端口直接用仓库的完整路径作为 registry 地址也就是http://内网IP:8081/repository/npm-group/。这样所有包类型共用 8081 端口防火墙只开一个口管理起来简单。缺点是这个地址比短地址长容易在配置文件里写错建议写成文档发给团队不要口头传达。npm 仓库还有一个配置项叫Negative cache指的是当一个包在 proxy 里找不到时把这个“找不到”的结果缓存多久。如果设得太长当你上传了内部包之后短时间内还是会被缓存挡住报 404让人以为上传失败。内网环境建议把这个值调小一点半小时到一小时比较合适。6.3 客户端 .npmrc 配置与发布认证项目的.npmrc或者全局的~/.npmrc里要写三样东西registry 地址、发布地址的认证信息、以及作用域包的去向。写法如下注意认证信息这部分不同版本的 npm 有差异。registryhttp://192.168.10.20:8081/repository/npm-group/ //192.168.10.20:8081/repository/npm-hosted/:_auth你的base64认证串 //192.168.10.20:8081/repository/npm-hosted/:always-authtrue 公司作用域名:registryhttp://192.168.10.20:8081/repository/npm-hosted/这里的_auth值是用户名:密码拼接后用 base64 编码的结果可以用命令行生成。always-authtrue表示访问这个地址时始终带认证信息npm 9 之后这个字段的作用有所变化有些版本会提示废弃但加上通常不会有副作用。如果你用的是较新的 npm更推荐用_authToken配合 Nexus 生成的 token不过 Nexus 的 npm 认证还是以 Basic Auth 为主基础写法能跑通就行。生成认证串的方式printf deployer:你的密码 | base64把输出结果填到_auth后面即可。注意这里不能有换行printf比echo更安全因为echo有时会附加换行符导致编码结果多出字符认证就失败了。验证配置是否生效用npm config get registry看一眼再npm install lodash --verbose观察请求地址。如果日志里出现的是你的内网 IP说明 proxy 配置生效了如果出现的是公共源地址说明registry没被正确读取检查一下是否有别处的.npmrc覆盖了它。npm 的配置优先级是项目级高于用户级高于全局级排查时要逐层看。发布内部包用npm publish它会把包推到公司作用域名对应的那个 hosted 仓库。发布前记得先在package.json里把publishConfig或name设置好包名带作用域前缀否则会默认往公共源推直接失败。6.4 Windows 上的 npm.ps1 执行策略问题这是 Windows 开发机上出现频率最高的一个问题报错信息大意是“无法加载文件 npm.ps1因为在此系统上禁止运行脚本”。原因不是 npm 坏了而是 PowerShell 的执行策略默认限制运行脚本而 npm 在 Windows 上是通过一个.ps1包装脚本调用的策略一挡就全废了。解决办法是把当前用户的执行策略改成允许本地脚本运行命令如下。注意要在 PowerShell 里执行改的是当前用户级别不需要管理员权限也不会影响系统其他用户的策略。# 查看当前策略 Get-ExecutionPolicy -List # 改为允许本地脚本远程签名脚本 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned # 如果上面命令提示被组策略覆盖就需要联系域管理员改完之后关闭并重新打开终端npm -v应该就能正常输出了。如果提示被组策略强制覆盖说明公司域控统一下发了策略这种情况下就不要硬改让 IT 在域策略里放行或者改用 CMD 而不是 PowerShell 来执行 npm 命令。这个坑的特点是报错信息看起来像文件损坏很多人第一反应是重装 nodejs白折腾。7. 权限、容量与日常运维7.1 用角色控制谁能上传谁能下载Nexus3 默认有匿名访问这个设置在生产环境必须关掉至少要把写权限关掉。正确的做法是建几个角色把权限粒度控制在仓库级别。我一般分三个角色只读角色只能浏览和下载所有仓库开发角色能往 hosts 的 releases 和 snapshots 上传管理角色能改仓库配置。然后把角色分配给用户按人分配而不是共用一个账号这样出问题能追溯到人。具体配置路径在安全设置里的角色管理创建角色时可以选择具体的权限项比如nx-repository-view-maven2-maven-releases-add这种细粒度权限。建议不要图省事直接用内置的nx-admin给所有人权限一旦放开就收不回来了。另外认证信息不要写死在项目文件里提交到代码库settings.xml和.npmrc都应该加进.gitignore用环境变量或者 CI 的密钥管理来注入。7.2 清理策略和磁盘容量规划私库跑一段时间后磁盘会持续增长需要设置清理策略。Nexus 提供 Cleanup Policies可以按“多久没被下载过”来删组件。对于 Maven 的快照仓库建议设置成 30 天未使用就清理因为快照本来就是临时的。对于正式版仓库则要谨慎正式版构件可能很久才被引用一次删掉之后老构建就复现不了了这类仓库建议不设自动清理靠人工评估。容量估算有个粗略方法Maven 中央仓库的完整镜像非常大但你实际只会缓存用到的部分一般团队一年累积在几十 GB 量级。yum 和 apt 的 rpm/deb 包体积大一个完整的发行版仓库可能有十几 GB建议只放你真正需要的包不要整镜像同步。nodejs 的二进制包每个版本大约 30-50MB存十个版本也就几百 MB压力不大。定期任务也是必须的Nexus 里可以配置两类定时任务一类是压缩 blob store把碎片整理掉一类是清理未使用的组件。压缩任务建议放在业务低峰期因为它会占用一定 IO。如果你很久不压缩blob store 的目录会越来越碎最终影响性能。7.3 备份与迁移的正确姿势Nexus 的备份最简单也最可靠的方式就是冷备停掉服务把整个sonatype-work/nexus3目录打包拿走。这个目录包含了所有配置、仓库定义、包文件、用户和权限属于完整快照。恢复到新机器上只需要把这个目录放回对应位置再启动服务即可注意程序版本要一致跨大版本直接替换数据目录可能不兼容。热备的方式是导出配置加单独备份 blob store但这种方式容易漏掉用户和权限数据恢复时可能出现仓库在但账号没了的尴尬情况。如果不是 7x24 不能停服的场景我建议就停服冷备简单可靠。备份频率看更新频率一般一周一次加上重大变更前手动备份一次就够。迁移机器时还有一个细节如果客户端配置里用的是 IP 地址换机器后 IP 变了就要改所有客户端配置。所以一开始就建议用域名或者统一的内网域名解析迁移时只改 DNS 记录客户端完全无感。这个建议越早采纳越好等到几百台机器都配了 IP 再改成本会非常高。8. 踩坑实录与排查速查表8.1 高频报错对照表下面这张表是我这几年在多个现场攒下来的覆盖了八成以上的常见问题。遇到报错先从这张表里找能省下大量搜索时间。报错现象可能原因排查动作maven 拉取报 401settings.xml 的 server id 与 pom 不一致核对两处 id 字符串是否完全相同maven 报找不到快照group 的 Version policy 选了 Release改为 Mixed 并刷新缓存yum makecache 报无法下载元数据baseurl 路径不对或 repodata 未上传用 curl 直接访问 repomd.xml 看返回码yum 报元数据校验和不匹配客户端缓存了旧元数据执行 yum clean metadataapt update 报 404sources.list 里多写了 binary-amd64只保留发行版代号和组件名apt update 报签名错误未加 trustedyes 且无有效签名加上 trustedyes 或补齐 Release 签名npm 发布报 403账号没有 hosted 仓库的写权限在角色里补 add 权限npm 装包仍走公网.npmrc 被上层配置覆盖用 npm config get registry 逐层确认Windows 下 npm 无法加载 ps1PowerShell 执行策略限制Set-ExecutionPolicy 改 CurrentUserNexus 启动后无法访问监听地址绑定错误或防火墙未放行检查端口监听和防火墙规则8.2 几个卡了很久的真实问题第一个是 raw 仓库上传无扩展名文件被拒的问题。前面提过严格内容校验但实际遇到时的表现是上传返回 400 而且提示信息很含糊只说内容类型不被接受。当时排查方向一度跑到了认证上浪费了不少时间。后来才发现是Packages这个文件没有扩展名Nexus 判断不出类型就拒绝。关掉严格校验之后立刻正常。这个坑在 apt 场景下几乎必踩因为 apt 的核心索引文件就是无扩展名的。第二个是 yum 仓库的路径大小写和斜杠问题。Linux 文件系统区分大小写repodata写成repodata/或者Repodata都会导致客户端找不到。另外 baseurl 结尾如果有斜杠会和后面拼接的部分产生双斜杠某些场景下 Nexus 会把它当成不同路径处理。这类问题没有技术含量但特别耗时间建议配置完成后第一件事就是用 curl 把拼接出来的完整 URL 敲一遍确认能拿到文件。第三个是 npm 的负缓存。当时上传了一个内部包客户端死活装不上报 404。检查了权限、路径、包名全都对最后才想到是之前请求过这个包名、当时不存在被负缓存记住了。清掉缓存或者等缓存过期之后就正常了。所以内网环境把这个缓存时间调短很有必要否则新人上传包之后会以为失败反复重传。实操心得所有客户端配置文件的地址都不要靠手敲直接从 Nexus 仓库详情页复制那个 URL。手敲出错的概率远高于你的想象而这类错误排查起来最费劲因为你会下意识觉得地址是对的。8.3 日常巡检建议清单最后给一份可以贴在工位上的巡检清单每周花十分钟过一遍能避免绝大多数突发故障。第一项看磁盘剩余空间低于 20% 就要开始规划清理或者扩容Nexus 在磁盘满的情况下会拒绝写入表现为所有上传都失败但下载正常很容易误判。第二项看服务进程和端口监听是否正常可以写个简单的健康检查脚本配合定时任务跑。第三项看最近有没有大量 401 或 403 的访问日志可能是有人在暴力猜密码也可能是某台机器配置写错了在疯狂重试。第四项看定时任务有没有正常执行压缩和清理任务如果失败通常是权限或者磁盘问题。这套东西搭完之后最大的感受是内网环境终于不用再靠“人肉搬运”了。新机器上架跑一个初始化脚本配上源地址几分钟就能装完开发环境不用再翻找 U盘里那个不知道哪个版本的安装包。构建结果也变得可信同样的代码在任何一台机器上编出来的依赖树是一模一样的出了问题能定位到具体的包版本而不是“在我机器上是好的”。如果你们现在还处在每台机器各自连公网的阶段真的值得花两天时间把这件事做完后面省下的时间远超投入。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

WorkBuddy 光伏方案入门:别只看装机容量,把阴影、负载与回本假设讲明白 2026/10/1 17:02:10

WorkBuddy 光伏方案入门:别只看装机容量,把阴影、负载与回本假设讲明白

WorkBuddy 光伏方案入门:别只看装机容量,把阴影、负载与回本假设讲明白 [!NOTE] 用屋顶面积乘组件功率就得出收益,是常见的过度简化。方案至少要区分资源、朝向、遮挡、系统损耗、负载和电价情景。 本课不会用“AI 一键完成”制造错觉,而是把 WorkBuddy、Python 3.11、pand…

阅读更多 →
UE5地编必会:烘焙光照原理与Lumen差异及实操指南 2026/10/1 17:02:10

UE5地编必会:烘焙光照原理与Lumen差异及实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
前端精读:深入 JavaScript 事件循环(Event Loop)与异步编程原理 2026/10/1 17:02:10

前端精读:深入 JavaScript 事件循环(Event Loop)与异步编程原理

文档技术博客教程 【免费下载链接】weekly 前端精读周刊。帮你理解最前沿、实用的技术。 项目地址: https://gitcode.com/GitHub_Trending/we/weekly 点击查看 免费下载 事件循环(Event Loop)是 JavaScript 运行机制的核心"内科"&…

阅读更多 →
自治数据平台实战:自动化运维与性能调优的架构设计 2026/10/1 17:02:10

自治数据平台实战:自动化运维与性能调优的架构设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
图片像素、分辨率与文件体积怎么算?一文厘清概念与实战 2026/10/1 17:02:09

图片像素、分辨率与文件体积怎么算?一文厘清概念与实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
精读《Excel JS API》:从 Range 抽象到 context.sync 的开放 API 设计 2026/10/1 17:02:03

精读《Excel JS API》:从 Range 抽象到 context.sync 的开放 API 设计

文档技术博客教程 【免费下载链接】weekly 前端精读周刊。帮你理解最前沿、实用的技术。 项目地址: https://gitcode.com/GitHub_Trending/we/weekly 点击查看 免费下载 Excel 如今可以利用 JavaScript 根据单元格数据生成图表、表格,或通过 JS 拓展自定…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉