
内网做构建这件事最容易被低估的就是依赖获取这一环。项目一多、语言一杂Maven 拉 jar、YUM 装 rpm、APT 装 deb、npm 装 node 模块四套东西各自连各自的公网源谁断了都得停下等。我这边的研发环境就是这么个情况十几条流水线混着 Java、Go 打包脚本、CentOS 基础镜像和 Ubuntu 构建机新人入职配一次环境要折腾大半天。后来用Nexus3在内网做了一套统一私库把maven、yum、apt、nodejs四类仓库全部收口到一台机器上配好之后客户端只需要改一个地址就能跑通全流程。这篇就把这套私库环境从选型、安装、建仓、客户端配置到排错按我实际落地的顺序完整拆一遍参数和命令都能直接抄也把我踩过的几个坑提前说出来。1. 方案先想清楚Nexus3 摆什么位置四类仓库怎么分工动手装之前先把这台机器到底承担什么角色想明白比装完再返工省事得多。私库这东西本质上是内网和外网之间的一个缓存加中转层它既要把公网的东西拉下来存住又要能收下团队自己产出的包还要在客户端眼里只暴露一个统一的入口地址。Nexus3 恰好把这三种能力做成了三种仓库类型proxy 负责代理外部源并缓存hosted 负责托管内部产物group 负责把前两者聚合成一个 URL。理解了这一层后面四类仓库的搭法其实是同一套逻辑换个协议而已。1.1 内网直连公网的三个现实痛点第一个痛点是速度和稳定性。公网源在国内访问经常抖动Maven 中央仓库拉一个稍大的依赖树就能拖到十几分钟npm 装一个前端工程动辄几百个包一旦中途超时整个npm install从头再来。私库把包缓存在本地磁盘第二次开始就是千兆内网速度差别非常直观。第二个痛点是安全和审计。开发机的构建脚本如果直接连公网源等于给每台机器都开了对外的下载权限一旦某个公网包被投毒内网很难察觉也没法追溯到底是谁在什么时候引入了哪个版本。私库把下载入口收敛成一台机器所有包的进出都有记录还能在 hosted 仓库里做白名单式的内部包发布。第三个痛点是离线可用。很多能力受限的机房、隔离网段、临时搭建的测试环境根本连不上公网这时候如果没有一套本地仓库整个编译流程直接卡死。私库里缓存过的依赖在断网状态下依然能完整安装这对做交付、做演示、给客户部署的场景尤其关键。把这三条想清楚你就知道这套东西不是锦上添花而是基础设施的一部分。1.2 proxy、hosted、group 三种仓库的定位差异很多人第一次打开 Nexus3 新建仓库的界面会懵类型太多不知道选哪个。其实抓住三种角色的分工就清楚了。proxy是代理加缓存你给它一个远端 URL它第一次请求时去远端拉拉到之后存在本地之后同样的请求直接命中缓存Maven 中央仓库、npm 官方源、各发行版的 yum/apt 源都属于这一类。hosted是托管内部产物团队自己编译出来的 jar、打好的 rpm、deb 包、私有 npm 模块都往这里发。它不连外网只接受上传和下载是内部交付的唯一可信来源。hosted 又分 Release 和 Snapshot 两种版本策略这个在 Maven 里尤其重要后面会细说。group是聚合入口它自己不存东西只是把若干个 proxy 和 hosted 按顺序拼在一起客户端访问 group 的地址时Nexus 依次去成员仓库里找找到就返回。对客户端来说永远只需要配一个 group 地址既拿到了公网缓存又拿到了内部包还省得在配置里写一堆 URL。我一般给每个协议都建一个 group命名统一成xxx-group客户端配置里只出现这一个地址。1.3 部署形态选型Docker 拉起还是裸机 installNexus3 官方提供两种主流部署方式。Docker 方式最省事拉个镜像挂个数据卷就能跑升级就是换个 tag回滚就是换回旧 tag对不熟悉 Java 服务的人特别友好。裸机安装是把官方 tar 包解压到某个目录再用 systemd 托管好处是不依赖容器运行时资源占用略低出问题时排查链路更短。我实际两套都跑过。开发测试环境用 Docker因为需要频繁重建生产性的私库用裸机因为这台机器上还挂着别的服务不想再引入一层容器网络。判断标准很简单你的机器上已经有成熟的容器运维体系就选 Docker如果是一台孤立的虚拟机、后续没人专门维护容器就裸机。两种方式的数据目录都是同一个结构迁移时把数据目录拷过去就行所以先选哪个都不算锁死。2. 部署前的资源估算与 Nexus3 落地安装资源这块不能拍脑袋给少了后面 OOM给多了浪费。我按自己的经验给一套估算方法然后分别给出 Docker 和裸机的完整落地步骤。2.1 JVM 堆、磁盘和内存的估算过程Nexus3 是个 Java 应用跑在 JVM 里默认的最大堆是 2703MB。这个数字不是随便定的官方给的经验是堆内存至少要能放下你最大单次请求涉及的对象而私库场景里最大的一块通常是首次代理一个大依赖树或者一个大镜像层时的临时缓冲。我的估算方式是基础堆 2GB 打底然后看你的仓库规模。如果只是给几十个项目做 Maven 加 npm 代理2GB 到 4GB 足够。如果还要缓存大量 rpm/deb 并且并发构建机器超过二十台建议给到 6GB 到 8GB物理内存留出堆的 1.5 到 2 倍因为 JVM 除了堆还有直接内存、元空间、线程栈和文件缓存。磁盘是另一个大头。Nexus3 的数据目录里blob store 会随着缓存不断增长。一个中等规模的 Java 团队一年下来 Maven 缓存吃掉 50GB 到 200GB 很正常如果还代理 npm 和系统包翻倍也不奇怪。我的做法是数据目录单独挂一块盘初始给 500GB配好清理策略并且提前把监控做上别等到磁盘写满才发现。提示Nexus3 官方镜像里 JVM 参数通过环境变量INSTALL4J_ADD_VM_PARAMS传入裸机安装则改bin/nexus.vmoptions。改完必须重启进程才生效在线改文件没用。场景建议堆内存建议磁盘说明个人或小团队只做 Maven 代理2GB100GB单机够用注意清理中型团队Maven npm4GB500GB并发十台以内比较稳多语言混合含 yum/apt6GB 到 8GB1TB需要配清理策略和监控2.2 Docker 方式十几分钟拉起一个可用的私库先建好数据目录并授权。Nexus3 容器内以 uid 200 运行宿主机目录权限不对会直接启动失败这一步很多人会漏。sudo mkdir -p /data/nexus-data sudo chown -R 200:200 /data/nexus-data sudo chmod -R 775 /data/nexus-data然后用官方镜像启动。注意把 JVM 参数和数据目录一起传进去顺便把 Java 的 preferences 目录也指到数据卷里避免容器重建后配置丢失。docker run -d \ --name nexus3 \ --restart always \ -p 8081:8081 \ -v /data/nexus-data:/nexus-data \ -e INSTALL4J_ADD_VM_PARAMS-Xms4g -Xmx4g -XX:MaxDirectMemorySize4g -Djava.util.prefs.userRoot/nexus-data/javaprefs \ sonatype/nexus3:3.70.1启动完成后docker logs -f nexus3观察日志出现Started Sonatype Nexus字样就说明起来了。第一次启动会初始化数据库通常要一到三分钟机器慢的话更久别急着判定失败。注意数据目录权限问题是 Nexus3 启动失败最常见的原因日志里一般会提示Permission denied或者直接卡住不输出。遇到先查目录属主再查 SELinux。2.3 裸机安装与 systemd 托管裸机安装的步骤是先准备 JDK再解压 tar 包最后写成 systemd 服务。Nexus3 各版本对 JDK 的要求不一样3.6x 之后的版本普遍要求 JDK 8 或 11动手前一定去确认对应版本的官方要求别随便装个新版 JDK 上去。# 以 JDK 11 为例路径按你实际安装位置调整 sudo mkdir -p /opt/nexus sudo tar -zxvf nexus-3.70.1-02-unix.tar.gz -C /opt/nexus --strip-components1 sudo useradd -r -s /sbin/nologin nexus sudo chown -R nexus:nexus /opt/nexus改bin/nexus.vmoptions把堆参数调成你估算的值-Xms4g -Xmx4g -XX:MaxDirectMemorySize4g -XX:UnlockDiagnosticVMOptions -XX:LogVMOutput -XX:LogFile../sonatype-work/nexus3/log/jvm.log接着写 systemd 单元让进程跟着系统启动崩溃也能自动拉起来[Unit] DescriptionNexus Repository Manager Afternetwork.target [Service] Typeforking LimitNOFILE65536 ExecStart/opt/nexus/bin/nexus start ExecStop/opt/nexus/bin/nexus stop Usernexus Restarton-abort [Install] WantedBymulti-user.target写完执行systemctl daemon-reload再systemctl enable --now nexus。这里有个容易忽略的点LimitNOFILE要给足私库并发高的时候文件句柄消耗很快默认 1024 会在压力上来后出现莫名其妙的连接失败。我给到 65536实测很稳。2.4 首次登录必须做的三件事新版本 Nexus3 的初始密码不再固定是admin/admin123而是随机生成后写在一个文件里Docker 方式在/nexus-data/admin.password裸机在sonatype-work/nexus3/admin.password。cat /data/nexus-data/admin.password拿到密码后用admin登录http://你的IP:8081系统会引导你改密码。改完密码只是第一步另外三件事我建议当天就做完第一关掉匿名访问或明确配置匿名可读范围第二删掉默认的 demo 仓库避免误用第三建一个专用的deploy用户只给上传权限CI 里用这个账号不要用 admin。这三件事看着琐碎但直接决定了后面私库是不是安全可控。我见过不少环境图省事一直用 admin 给所有客户端发凭据一旦泄露就是全库可写可删补救成本极高。3. Maven 私库搭建hosted、proxy、group 三件套怎么拼Maven 是这套私库里用得最多的部分也是最容易配错的部分。我的做法是固定建三个仓库一个 hosted 收内部包一个 proxy 代理中央仓库一个 group 把两者聚合客户端只认 group。3.1 建仓库的顺序和命名规范顺序上建议先 hosted再 proxy最后 group因为 group 的成员列表在创建时就要选前面的没建好后面选不到。命名我用固定的后缀区分maven-releases、maven-snapshots、maven-central、maven-public。这样一看名字就知道类型后期维护和交接都省心。hosted 仓库分两个是刻意的。Release 版本的包一旦发布就不应该被覆盖Snapshot 版本可以反复覆盖发布。把两者分开可以在组策略和清理策略上差异化处理比如给 Snapshot 配定期清理给 Release 配置为不可重复部署。这个区分在做正式交付的时候非常有用。3.2 proxy 代理中央仓库的几个关键参数新建 maven2(proxy) 时远端地址填https://repo1.maven.org/maven2/其余参数大部分可以用默认值但有两个地方我调整过。一个是版本策略proxy 的Version policy保持Mixed即可因为中央仓库里既有 release 也有 snapshot。另一个是缓存过期时间默认的Not Found Cache TTL是 1440 分钟意思是某个包如果确定不存在1440 分钟内不再去远端查询。这个值对内网体验影响很大遇到构建突然报找不到某个刚发布的版本先想想是不是被这个缓存挡了临时可以把值改小或者手动清理缓存。如果你的环境有稳定的国内镜像可用也可以再建一个 proxy 指向它然后在 group 里排到中央仓库前面命中率更高。但要记住无论后面挂几个 proxy客户端配置里永远只出现 group 地址这是这套设计能稳定运行的前提。3.3 settings.xml 与 pom.xml 可直接抄的配置客户端侧主要改两个文件。全局的settings.xml配镜像和凭据项目的pom.xml配发布地址。先看settings.xml把镜像指向 group同时在 servers 里放上传凭据settings mirrors mirror idnexus/id namenexus private maven/name urlhttp://192.168.1.100:8081/repository/maven-public//url mirrorOf*/mirrorOf /mirror /mirrors servers server idnexus-releases/id usernamedeploy/username password你的部署密码/password /server server idnexus-snapshots/id usernamedeploy/username password你的部署密码/password /server /servers /settings这里mirrorOf用*表示接管所有仓库请求。有人会担心这样连不上其他私有源解决办法是在 group 里把那些源也建成 proxy 成员而不是在客户端放开多个镜像。保持客户端配置单一后期换地址只需要改一处。pom.xml里加发布地址distributionManagement repository idnexus-releases/id urlhttp://192.168.1.100:8081/repository/maven-releases//url /repository snapshotRepository idnexus-snapshots/id urlhttp://192.168.1.100:8081/repository/maven-snapshots//url /snapshotRepository /distributionManagement配好之后mvn deploy就能把包推到私库其他项目通过mvn clean package自动从 group 拉取。3.4 快照版本与发布版本的策略区别这块是我踩坑最多的地方。Release 仓库默认策略是Disable redeploy也就是同一个版本号不允许重复发布这是为了保证金版本不可变。如果你调试时反复发同一个版本号会收到 400 错误报错信息里会提到 redeploy。解决办法是要么升版本号要么临时把仓库策略改成 Allow redeploy但正式环境千万别改否则版本就失去可信度了。Snapshot 仓库则相反允许覆盖每次发布自动带时间戳后缀。客户端拉 snapshot 时会检查远程的maven-metadata.xml所以如果你本地mvn -U还是拿到旧包很可能是 metadata 缓存没刷新可以手动触发一次更新或者等缓存过期。实操心得给 Snapshot 仓库单独配一条清理策略比如保留最近 30 天或者每个包最多保留 10 个快照。不做这件事快照目录会以肉眼可见的速度膨胀半年就能吃掉几百 GB。4. YUM 私库把 RPM 统一收口Java 团队之外只要涉及 CentOS、RHEL 一类的系统镜像构建就绕不开 YUM。私库里做 YUM 的价值在于内网机器不再需要各自配置一堆外网源所有 rpm 从一处下发离线环境也能装。4.1 yum hosted 与 yum proxy 的建法差异新建时选yum (proxy)或yum (hosted)。proxy 的远端地址填你要代理的发行版源比如某个稳定镜像站的centos/7/os/x86_64/路径hosted 不填远端只等着你上传 rpm。这里有个版本相关的细节必须提前确认Nexus3 对 yum hosted 的支持在较新版本才完善早期版本上传 rpm 后不会自动生成 repodata客户端会直接报找不到元数据。如果你用的是老版本要么升级要么用createrepo在仓库目录里手动生成后上传。我建议直接升到较新的 3.x 版本能省掉大量手工维护元数据的工作。4.2 客户端 repo 文件怎么写客户端只改一个.repo文件指向 yum group[nexus-yum] nameNexus YUM Repository baseurlhttp://192.168.1.100:8081/repository/yum-group/ enabled1 gpgcheck0gpgcheck0只是内网图省事的写法正式环境应该把公钥下发到/etc/pki/rpm-gpg/并把gpgcheck打开。改完文件执行yum clean all再yum makecache缓存建起来之后再装包就是内网速度。注意改了源之后一定要先yum clean all否则老缓存还在会继续走旧地址让人误以为配置没生效。4.3 批量上传 RPM 的三种姿势第一种是界面手动上传适合零散几个包缺点是包多了效率极低。第二种是curl PUT 上传适合脚本化curl -v -u deploy:你的密码 \ --upload-file ./nginx-1.24.0-1.el7.x86_64.rpm \ http://192.168.1.100:8081/repository/yum-hosted/Packages/n/nginx-1.24.0-1.el7.x86_64.rpm路径里的Packages/n/只是目录惯例方便按首字母归类不影响功能Nexus 会自动识别 rpm 内容并更新元数据。第三种是从 proxy 缓存里提升到 hosted如果你已经通过 proxy 拉过某个包可以直接在界面上把它移动到 hosted 仓库省一次下载。批量场景我一般写个循环脚本把本地一个目录里的 rpm 全部推上去几百个包几分钟就能跑完。4.4 元数据刷新与校验上传完成后去 hosted 仓库的 Browse 里看是否出现repodata目录里面应该有repomd.xml和若干primary文件。有就说明元数据生成成功。客户端这边如果yum install报Cannot retrieve repository metadata按三个方向查网络能不能通、baseurl 路径对不对、group 的成员顺序对不对。group 成员顺序这件事容易被忽略。如果你的 hosted 里有一个包、proxy 里也有同名不同版本的包group 会按成员列表顺序去找先命中谁就用谁。想让内部包优先就把 hosted 放到成员列表最前面。5. APT 私库给 Debian、Ubuntu 做内网源APT 这套的逻辑和 YUM 类似但多了签名密钥这一环配置不当会一直卡在apt update报签名错误上所以单独拎出来讲清楚。5.1 apt hosted 与 apt proxy 的建立创建时选apt (hosted)或apt (proxy)。hosted 需要填两个关键项Distribution比如bionic、focal、jammy这类发行版代号和Signing Key。签名密钥是 APT 体系和 YUM 最大的区别客户端默认会校验包和索引的签名没有正确的公钥就会直接拒绝更新。我的建议是单独生成一对专用密钥导出私钥粘贴到 Nexus 的 Signing Key 配置里把公钥保存好下发给客户端。用现成的通用密钥虽然省事但一旦密钥轮换就是全量客户端重配不如一开始就规划清楚。5.2 sources.list 与公钥落地客户端配置写在/etc/apt/sources.list或/etc/apt/sources.list.d/下的独立文件里deb http://192.168.1.100:8081/repository/apt-group/ focal main然后是公钥。把 Nexus 上导出的公钥复制到客户端后执行导入sudo gpg --dearmor -o /usr/share/keyrings/nexus-apt.gpg nexus-public.key再回到 sources 文件里加上签名引用形如[signed-by/usr/share/keyrings/nexus-apt.gpg]。这样做的目的是把信任范围限定到这一个仓库不影响系统其他源的校验逻辑比直接把 key 加进全局 trusted 列表干净得多。改完执行sudo apt update看到仓库地址被正常读取、没有签名报错就说明通了。5.3 上传 deb 包与 dists 目录结构deb 包上传同样支持 curlcurl -v -u deploy:你的密码 \ --upload-file ./mytool_1.0.0_amd64.deb \ http://192.168.1.100:8081/repository/apt-hosted/上传后 Nexus 会在仓库里维护dists/Distribution/和pool/结构apt update读取的就是dists下的Release和Packages索引。如果你上传后客户端报404八成是 Distribution 名字和 sources 里写的对不上比如仓库建的是jammy客户端写的却是focal这种错看起来是网络问题其实是配置不一致。5.4 apt update 报错的定位方法APT 的报错信息其实很直白按关键字对号入座就行。看到NO_PUBKEY或者signature verification failed说明公钥没导入或者signed-by路径写错看到404 Not Found先核对 baseurl、Distribution、组件名三者是否和仓库配置一致看到Could not resolve或者超时那是网络层的问题先curl一下仓库地址看能不能通。我遇到过一次特别隐蔽的情况客户端报签名错误但公钥明明导入了。最后发现是密钥过期时间设置得太短半年后就失效了。所以生成密钥时有效期至少给几年并且把轮换计划写进运维文档别让它在你忘记的时候突然爆掉。6. Node.js 私库npm 代理加私有包前端工程对私库的依赖程度可能是四类里最高的因为npm install一次要拉几百个包公网速度直接决定构建时长。6.1 npm 三仓库的建立与 group 顺序和 Maven 一样建三个npm-hosted放私有包npm-proxy代理官方源远端地址https://registry.npmjs.orgnpm-group聚合两者。group 成员顺序建议 hosted 在前这样私有包名和公网包名冲突时优先命中内部版本避免装错包。有个细节值得强调Nexus3 的 npm 代理在部分版本上对npm audit和某些元数据接口的支持不完整如果团队重度依赖npm audit可能需要额外配一个直连场景或者关掉相关检查。这属于版本特性差异遇到不要硬杠先确认你用的 Nexus 版本对 npm 的支持清单。6.2 .npmrc 的工程级配置客户端配置分两层。全局的~/.npmrc影响所有项目工程级的.npmrc只影响当前项目。我一般把源地址写进工程级配置并提交到代码库让团队成员克隆下来就能用registryhttp://192.168.1.100:8081/repository/npm-group/ strict-sslfalse如果私库上了 HTTPS 并用了自签证书strict-ssl的处理要谨慎稳妥做法是把 CA 证书装到系统信任链里而不是一律关校验。上传私有包时还需要认证可以用npm login或者直接在.npmrc里配_auth字段。6.3 发布私有包与 scope 绑定私有包建议统一用 scope比如mycompany/utils并在.npmrc里把 scope 和仓库绑定mycompany:registryhttp://192.168.1.100:8081/repository/npm-hosted/这样npm publish时带 scope 的包会自动发到 hosted不带 scope 的走默认 registry。绑定 scope 的好处是避免了发布方向的歧义也方便在 group 里做路由控制。实操心得发布前一定在.npmrc里把认证信息配好否则npm publish会返回 401 或 403。CI 环境里用环境变量注入凭据不要把 token 硬编码进仓库。6.4 缓存、离线与 CI 场景npm 私库最直接的收益体现在 CI 上。同一条流水线第二次构建时所有依赖都命中内网缓存npm ci的时间能从几分钟压到几十秒。如果再配合把node_modules或者 npm 缓存目录做持久化效果更明显。为了控制磁盘我给 npm proxy 配了缓存清理策略把长期没人访问的包定期删掉。但要注意清理策略删的是缓存不是内部包hosted 仓库的包不会受影响。配置时看清楚作用范围别把 hosted 也扫进去那会把团队发布的私有包误删。7. 常见问题速查与排查手法这套环境跑起来之后日常遇到的问题集中在几个固定方向我把它们整理成速查形式遇到直接对号入座。7.1 上传类错误怎么读上传失败最常见的三个状态码401是认证没通过检查用户名密码或者 token403是认证过了但没有写权限检查这个用户有没有对应仓库的nx-repository-view-*-*-add权限400多见于 Maven 重复发布 release 版本或者路径不符合仓库约定。有一个特别容易误判的情况Maven 上传时报 400 并提到redeploy很多人以为是权限问题去改用户其实是版本策略挡的。看到这个关键字直接去改策略或者升版本号。7.2 客户端拉取超时和 404 的定位顺序遇到客户端拉不到包我固定按这个顺序查第一步确认仓库地址能通用 curl 访问 group 的根路径返回 200 说明服务正常第二步确认包在不在直接在界面 Browse 里搜包名看它在哪个成员仓库里第三步确认 group 成员配置有没有漏加或者顺序错了第四步查缓存过期404 被缓存住的情况在老版本里很常见清理一下对应仓库的缓存就好。这个顺序的好处是从大到小逐层收敛不用一上来就翻日志。真到第四步还解决不了再去翻nexus.log里面会有到远端请求的详细记录。7.3 磁盘告警与清理策略磁盘是私库最现实的瓶颈。我的做法是每个仓库单独配清理策略而不是全局一把抓。Maven snapshot 保留最近 30 天npm proxy 只保留最近 90 天被访问过的包系统包缓存保留版本数上限。同时给数据目录做磁盘水位监控超过 80% 就告警。需要提醒的是清理策略是定期任务不是实时执行配置完要手动跑一次或者等调度周期到才会生效。别配完就以为空间立刻回来了我见过有人等了半天以为策略没生效其实是任务还没跑。7.4 备份、迁移和扩容备份的黄金法则是备份数据目录而不是备份容器。Nexus3 的所有配置、仓库内容、用户信息都落在数据目录下的 blob store 和数据库里把整个目录 rsync 出来就是完整备份。Docker 环境把/nexus-data备份走裸机把sonatype-work/nexus3备份走。迁移时新机器装好同版本 Nexus把数据目录拷过去权限改成对应用户启动即可。这里有个大坑目标机器的 Nexus 版本不能低于源机器否则数据结构不兼容会启动失败。升级路径永远是先升程序再迁数据别反过来。扩容主要针对 blob store。Nexus3 支持把 blob store 放到独立磁盘甚至共享存储上数据量大了之后可以直接把 blob store 目录换到更大的盘改配置重启即可不需要重建仓库。8. 我在实际搭建中踩过的坑和积累的小技巧前面讲了标准流程这一节说点文档里不太会写、但实际会绊人的细节。8.1 权限别只给能上传一开始我给 CI 用的deploy用户只加了上传权限结果发布 npm 包时一直 403排查半天才发现 npm 发布除了写权限还需要对仓库的读取权限因为它发布前要先检查包是否存在。后来给这个用户补上了read和browse问题就没了。所以配权限时别只盯着写读取和浏览通常也得给。8.2 反向代理和上下文路径的配合把 Nexus 放到反向代理后面时最容易出问题的是上下文路径。如果对外暴露的路径前缀不是根路径需要在 Nexus 里配置Base URL或者在代理层做路径重写否则界面里的资源链接会指向错误的地址表现为页面加载一半就失效。最省事的做法是让 Nexus 的 Base URL 和代理对外地址完全一致不要做多余的路径变换。8.3 关于密码和密钥的几条经验初始密码要第一时间改改完把文件删掉CI 凭据走环境变量注入不要提交到代码库APT 的签名密钥有效期给足并且记录轮换计划Maven 的部署密码和登录密码不要用同一个。这些都是小事但每一条出问题都会变成大事。8.4 一次版本不匹配引发的连锁反应有一次我在测试机上升级了 Nexus把数据目录直接拷到旧版本的机器上想回滚结果启动直接失败日志里报数据结构版本不兼容。后来才知道 Nexus 的数据库有 schema 版本号只能向前不能向后。从那以后我给自己定了一条规矩升级前一定做完整的数据目录快照回滚用快照而不是降级程序。这条比什么优化技巧都重要。另一个小技巧是关于首次缓存的预热。新搭好的私库第一次给团队用大家同时拉依赖会很慢因为都在等代理去远端拉。我一般挑几个大项目的构建先跑一遍把热门依赖提前缓存进私库等团队切过来的时候命中率已经很高了体验会好很多。这个操作不复杂但对推广私库很有帮助毕竟大家最在意的就是切过去之后是不是真的更快了。最后再补一个小细节关于客户端配置的下发。人一多最麻烦的不是搭私库而是让所有人把客户端配置改对。我的做法是写一段几行的初始化脚本Maven 用settings.xml模板覆盖npm 用工程级.npmrc提交到代码库yum 和 apt 的源文件用配置管理工具统一下发。这样新人进来跑一个脚本就配好了也不会有人漏改某一条导致构建行为不一致。搭私库这件事真正的成本从来不在服务端而在让整个团队用得整齐。