
简介nexus-3.45.0-01-win64 是面向 Java 开发团队与 Maven 项目维护者的 Windows 64 位 Nexus 私服安装包用于在内网集中管理内部组件、第三方依赖及公共仓库缓存缓解直连中央仓库的延迟与安全问题。压缩包共 690 个文件约 240.62MB以 420 个 jar、82 个 dll、29 个 xml、22 个 exe 及 properties、cfg、脚本等配置和运行文件为主涵盖程序主体、依赖库与运行参数目录中同时保留 sonatype-work 运行时数据与 Nexus 程序文件。已有 417 人学习或下载。读者可借助它搭建受控的 Maven 仓库服务理解仓库分组、代理缓存、发布部署、权限控制与索引搜索等核心能力并据此维护本地私服的目录结构和运行配置。1. 为什么在 Windows 上折腾 maven 私服从一次二十分钟的构建说起团队里有人抱怨构建一次要等二十分钟多数时候问题出在每个开发者都在对着公网仓库重复下载同一批构件网络本身并不是主因。nexus windows版本之所以被反复搜索是因为很多中小团队的内网机器本来就是 Windows Server 或者一台闲置工作站装个 maven 私服最省事的路径就是拿nexus-3.45.0-01-win64这个包解压跑起来。它干的事很朴素把中央仓库的构件缓存到本地把团队自己的 release 和 snapshot 收进来再用一个 group 仓库对客户端只暴露一个地址。手上一到几十个 Java 项目、构建频繁、又不想在 Linux 运维栈上耗时间的团队最吃这套。下面按装、划仓库、接客户端、踩坑的顺序走一遍。2. 拆包到能跑nexus.vmoptions 的关键参数与首次启动的验证路径2.1 包解开之后先认目录压缩包解压出来是两层结构nexus-3.45.0-01是程序本体sonatype-work是运行时生成的数据目录默认跟它同级。我一般固定成这个布局D:\nexus\ ├── nexus-3.45.0-01\ │ ├── bin\ # nexus.exe 与 nexus.vmoptions │ ├── etc\ # nexus-default.properties、karaf 配置 │ ├── lib\ │ ├── public\ │ └── system\ └── sonatype-work\ └── nexus3\ # blob 库、日志、临时文件、admin.password路径作用要不要单独备份bin/nexus.exe服务安装/启停的唯一入口随安装目录整体备份bin/nexus.vmoptions堆内存、数据目录、日志路径要etc/nexus-default.properties端口、监听地址、context path要lib/、system/程序自带 bundle不要手改不用sonatype-work/nexus3/全部业务数据必须安装目录这一条要注意路径里不要带空格、中文和括号。nexus.vmoptions里大量使用相对路径启动器在解析带空格的参数时容易出问题日志里报的错还往往指向别处排查起来很费劲。2.2 用 nexus.vmoptions 固定堆内存和数据落盘位置bin/nexus.vmoptions是启动时真正生效的 JVM 参数集合改这里比改别的地方更直接# 位置D:\nexus\nexus-3.45.0-01\bin\nexus.vmoptions # 初始堆和最大堆设成一样避免运行期反复扩容造成停顿 -Xms2703m -Xmx2703m # 直接内存上限大体积构件的上传/下载走 NIO 通道时用得到 -XX:MaxDirectMemorySize2703m -XX:UnlockDiagnosticVMOptions -XX:LogVMOutput -XX:LogFile../sonatype-work/nexus3/log/jvm.log -XX:-OmitStackTraceInFastThrow # 容器根目录固定为程序目录所以安装目录别随便改名 -Dkaraf.home. -Dkaraf.base. -Dkaraf.etcetc/karaf -Djava.util.logging.config.fileetc/karaf/java.util.logging.properties # 数据真正存的地方换盘就改这三行 -Dkaraf.data../sonatype-work/nexus3 -Dkaraf.log../sonatype-work/nexus3/log -Djava.io.tmpdir../sonatype-work/nexus3/tmp -Dkaraf.startLocalConsolefalse几个参数的含义值得说清楚。-Xms和-Xmx设成相等是常规做法Nexus 启动后很快会吃满大部分堆让 JVM 早期就把内存要到手比运行期反复扩容稳。-XX:MaxDirectMemorySize是很多人漏掉的一项只调-Xmx不调它传几百兆的大包照样会在 NIO 层报内存不足这类报错在nexus.log里往往只写一句 OOM容易误判成磁盘问题。-Dkaraf.data是数据目录的唯一依据想迁到独立盘这三行一起改改完重启服务然后把老的sonatype-work整个目录搬到新位置。注意-Dkaraf.data改动前先停服务再搬目录搬完用nexus.exe /run前台跑一次确认新目录下生成了db、blobs、log三个子目录再装回服务。端口和监听地址不在nexus.vmoptions里而是在etc/nexus-default.properties# 位置D:\nexus\nexus-3.45.0-01\etc\nexus-default.properties application-port8081 application-host0.0.0.0 nexus-context-path/ nexus-work${bundleBasedir}/../sonatype-work/nexus3application-host0.0.0.0是让同网段的其他机器能连进来默认值在很多版本里只绑本机回环地址装完发现只有本机能开、同事一律超时八成是这里没改。nexus-work要跟-Dkaraf.data指向同一处两个地方不一致时会看到服务起来了但仓库列表是空的。2.3 前台跑通再装服务报错才有地方看装成 Windows 服务之前先用前台模式跑一遍。这一步省不了直接/install再/start进程一起来就退日志还没刷完就断了反而难查。管理员身份打开 CMD先确认 Java 环境cd /d D:\nexus\nexus-3.45.0-01\bin # 启动器读的是 JAVA_HOME不是 PATH 里那个 java echo %JAVA_HOME% java -versionJAVA_HOME指向 JDK 而不是 JRE版本上 3.45 这一代用 JDK 8 最省心手上只有更高版本就先别急先用 JDK 8 把链路跑通再考虑升级。确认无误后前台启动nexus.exe /run控制台刷到Started Sonatype Nexus一类字样就说明起来了。浏览器开http://127.0.0.1:8081/能出登录页即通。接着从数据目录取初始密码# 首次启动后生成登录后台改掉后这个文件会被删除 type D:\nexus\sonatype-work\nexus3\admin.password前台验证通过再装服务nexus.exe /install nexus.exe /start nexus.exe /status/status输出Running再去做后续配置。日志两处业务日志sonatype-work\nexus3\log\nexus.logJVM 日志sonatype-work\nexus3\log\jvm.log前者看业务异常后者看内存和启动参数是否被正确读到。# 非本机验证一下监听是否真的对外 curl -s -o NUL -w %{http_code}\n http://本机内网IP:8081/返回200或302都算正常返回000基本是防火墙或者监听地址的问题这个放到后面避坑章节细说。3. 仓库怎么划proxy / hosted / group 的职责边界与 REST 建库脚本3.1 四类仓库各管一段别混着来新手最容易犯的错是直接把构件推到maven-central或者在maven-public上开写入。Nexus 3 的仓库分工很明确按用途划开之后权限、清理、备份都能独立做仓库名类型关键参数用途maven-centralproxyremoteUrlhttps://repo1.maven.org/maven2/versionPolicyRELEASE缓存公网构件只读maven-releaseshostedversionPolicyRELEASEwritePolicyALLOW_ONCE团队正式版本防重复覆盖maven-snapshotshostedversionPolicySNAPSHOTwritePolicyALLOW开发中的快照允许反复推maven-publicgroupmemberNames按顺序排对客户端只暴露这一个地址maven-releases的ALLOW_ONCE是刻意选的。正式版本被覆盖是事故级的一旦有人mvn deploy推重了下游拉到的 jar 和昨天不一致问题能查一整天。snapshots反过来开发阶段就该允许覆盖所以写策略设为ALLOW。Blob store 这一层十几人的团队用默认的default就够。项目多到几百 GB 之后我一般按 release 和 snapshot 拆两个 blob store理由是清理策略和 compact 任务能分开跑备份也能只备 release。这个小决定到后期能省不少事。3.2 用 REST 建库别在界面里点二十遍Nexus 3 的仓库管理有完整 REST 接口路径是/service/rest/v1/repositories/maven/{proxy|hosted|group}。JSON 直接塞命令行在 CMD 里转义很折磨写成文件用--data-binary 文件名最干净。先建代理仓库maven-central.json{ name: maven-central, online: true, storage: { blobStoreName: default, strictContentTypeValidation: true, writePolicy: ALLOW }, proxy: { remoteUrl: https://repo1.maven.org/maven2/, contentMaxAge: 1440, metadataMaxAge: 1440 }, negativeCache: { enabled: true, timeToLive: 1440 }, httpClient: { blocked: false, autoBlock: true, connection: { retries: 3, timeout: 60 } }, maven: { versionPolicy: RELEASE, layoutPolicy: PERMISSIVE, contentDisposition: ATTACHMENT } }这里四个参数值得单独拎出来。contentMaxAge是构件缓存的保鲜期单位分钟1440意味着一天内同一个包不会再去公网问一遍内网带宽就是这么省下来的。metadataMaxAge控制maven-metadata.xml的刷新频率它跟contentMaxAge是两回事调小了会频繁回源调大了会发现公网新出的版本好几天都看不到。negativeCache.timeToLive是失败结果的记忆时间公网抖动拉不到包时会记一笔一小时内重复请求直接返回失败这个机制能挡住雪崩但也会让人误以为私服坏了。autoBlock打开后远端连续失败会临时把仓库置为不可用防止拖垮整个 group 的响应。再建maven-releases.json{ name: maven-releases, online: true, storage: { blobStoreName: default, strictContentTypeValidation: true, writePolicy: ALLOW_ONCE }, maven: { versionPolicy: RELEASE, layoutPolicy: PERMISSIVE, contentDisposition: ATTACHMENT } }maven-snapshots.json只改两处name换成maven-snapshotswritePolicy改成ALLOWversionPolicy改成SNAPSHOT。最后建maven-public.json{ name: maven-public, online: true, storage: { blobStoreName: default, strictContentTypeValidation: true }, group: { memberNames: [maven-releases, maven-snapshots, maven-central] } }三条命令依次执行# Windows 下要写 curl.exePowerShell 里 curl 是 Invoke-WebRequest 的别名 curl.exe -u admin:你的密码 ^ -X POST http://127.0.0.1:8081/service/rest/v1/repositories/maven/proxy ^ -H Content-Type: application/json ^ --data-binary maven-central.json curl.exe -u admin:你的密码 ^ -X POST http://127.0.0.1:8081/service/rest/v1/repositories/maven/hosted ^ -H Content-Type: application/json ^ --data-binary maven-releases.json curl.exe -u admin:你的密码 ^ -X POST http://127.0.0.1:8081/service/rest/v1/repositories/maven/group ^ -H Content-Type: application/json ^ --data-binary maven-public.json返回 HTTP201就是建成功了。想确认建了哪些查一遍curl.exe -s -u admin:你的密码 http://127.0.0.1:8081/service/rest/v1/repositories | findstr /C:\name\注意curl.exe必须带后缀。Windows 的 PowerShell 把curl映射成了Invoke-WebRequest参数语法完全不一样直接敲curl会看到一堆莫名其妙的参数错误。3.3 group 的成员顺序不是随便排的memberNames的数组顺序决定查找优先级Nexus 按顺序问先命中先返回。把maven-releases和maven-snapshots排在maven-central前面是为了让内部构件优先命中避免同坐标的内部包被远端缓存抢先返回。实际踩过一次某内部库跟公网某个包 groupId 撞了central 排前面的时候构建拉到的永远是公网那个老版本本地代码改了半天不生效翻车翻得莫名其妙。另外两个可以提前想好的点。一是routing rule和content selector能按包名前缀把请求分流到不同仓库比如内部包统一用某个私有前缀就只让它命中 hosted 仓库公网请求一律走代理这套在仓库多起来之后很省心。二是 cookie 和重定向httpClient里那两个开关默认关着遇到某些镜像站需要跟随重定向时才打开平时别动。4. 客户端接进来settings.xml、distributionManagement 与 CI 凭据的三段式配置4.1 settings.xml镜像拦 central别一刀切用通配客户端侧第一份文件是~/.m2/settings.xml。核心是三段servers存发布凭据mirrors把 central 指到私服profiles把仓库地址注册进去。?xml version1.0 encodingUTF-8? settings xmlnshttp://maven.apache.org/SETTINGS/1.2.0 servers !-- id 必须跟 pom 里 distributionManagement 的 repository id 一模一样 -- server idnexus-releases/id usernamedeployer/username password{加密后的密码}/password /server server idnexus-snapshots/id usernamedeployer/username password{加密后的密码}/password /server /servers mirrors !-- 只拦 central别写 * -- mirror idnexus-public/id mirrorOfcentral/mirrorOf urlhttp://192.168.1.20:8081/repository/maven-public//url /mirror /mirrors profiles profile idnexus/id repositories repository idnexus-public/id urlhttp://192.168.1.20:8081/repository/maven-public//url releasesenabledtrue/enabled/releases snapshotsenabledtrue/enabled/snapshots /repository /repositories pluginRepositories pluginRepository idnexus-public/id urlhttp://192.168.1.20:8081/repository/maven-public//url releasesenabledtrue/enabled/releases snapshotsenabledfalse/enabled/snapshots /pluginRepository /pluginRepositories /profile /profiles activeProfiles activeProfilenexus/activeProfile /activeProfiles /settingsmirrorOf写central而不是*这个选择有代价也有收益。写*看起来一劳永逸实际会把构建里所有显式声明的仓库全部劫持到 group 上一旦某个第三方仓库没有加进 group 成员构建就报找不到构件而报错信息只说在私服上没找到不会告诉你是被镜像拦掉的。写central覆盖了绝大多数场景特殊情况还能直连出问题时排查范围小很多。团队规模大了要求全部走私服再把成员补全后改成*。这里还有个常见误解要说清楚mirror 不影响 deploy。mvn deploy的推送地址来自 pom 里的distributionManagement不走镜像。想改发布目标只能改 pom 或者用命令行参数覆盖改 settings 的镜像没用。4.2 pom.xml 里的 distributionManagement 与 id 对应关系发布方要在 pom 里声明目标仓库distributionManagement repository idnexus-releases/id urlhttp://192.168.1.20:8081/repository/maven-releases//url /repository snapshotRepository idnexus-snapshots/id urlhttp://192.168.1.20:8081/repository/maven-snapshots//url /snapshotRepository /distributionManagementid是整条链路的钥匙。Maven 推包时按这个 id 去settings.xml的servers里找凭据找不到就用匿名身份请求Nexus 返回401。这是发布失败里出现频率最高的原因账号密码完全正确也没用因为根本没被读进去。不想改 pom 的项目比如第三方维护的模块用命令行覆盖mvn deploy \ -DaltDeploymentRepositorynexus-releases::default::http://192.168.1.20:8081/repository/maven-releases/格式是id::layout::url中间那个default是布局类型别漏。这里的id同样要在settings.xml的servers里存在否则一样401。4.3 CI 环境下的凭据注入本地开发用加密密码没问题CI runner 是干净环境没有settings-security.xml加密串解不开构建会卡在解析凭据这一步。这时候用环境变量更实际server idnexus-releases/id username${env.NEXUS_USER}/username password${env.NEXUS_PASS}/password /server流水线里注入NEXUS_USER和NEXUS_PASS两个变量构建脚本用-s指定一份专用 settingsmvn -s ci-settings.xml clean deploy -DskipTests本地想用加密方案的话# 生成主密码结果写进 ~/.m2/settings-security.xml mvn --encrypt-master-password 你的主密码串 # 用主密码加密仓库密码输出放到 settings.xml 的 password 节点里 mvn --encrypt-password 仓库实际密码注意加密密码只有在settings-security.xml存在时才解得开。CI 里要么把这个文件用安全变量还原出来要么老老实实用环境变量两条路选一条别混着用。5. 避坑排查Windows 上 Nexus 3 的五个高频翻车现场5.1 本机能打开 8081同事一律超时现象浏览器在本机访问http://127.0.0.1:8081/正常换成内网 IP 就转圈telnet也不通。原因etc/nexus-default.properties里的application-host还是默认的127.0.0.1只绑了回环地址或者 Windows 防火墙没有放行入站端口。解决把application-host改成0.0.0.0重启服务。防火墙加一条入站规则New-NetFirewallRule -DisplayName Nexus 8081 -Direction Inbound -Protocol TCP -LocalPort 8081 -Action Allow改完用netstat -ano | findstr :8081确认监听是0.0.0.0:8081而不是127.0.0.1:8081。5.2/start之后进程秒退日志里找不到 Java现象nexus.exe /start返回成功/status一看没在跑nexus.log里只有一行Unable to find java之类。原因nexus.exe启动子进程时读的是JAVA_HOMEPATH 里那个java它不认。装过 JRE 之后JAVA_HOME没设或者设成了C:\Program Files\Java\jre...。解决把JAVA_HOME指到 JDK 根目录路径里别带空格setx JAVA_HOME D:\jdk\jdk8 /M设置完新开一个管理员 CMD老的窗口环境变量不会刷新。然后先用nexus.exe /run前台确认能起来再/install装服务。5.3 部署返回 401账号密码反复确认没输错现象mvn deploy报401 Unauthorized浏览器用同一个账号能登录后台。原因pom 里distributionManagement的repository id跟settings.xml里servers/server/id对不上Maven 找不到凭据就发匿名请求。第二种可能是账号没有nx-repository-view-maven2-maven-releases-*这组权限。解决两边 id 逐字符对齐大小写和连字符都算。用-X看 Maven 到底带了什么mvn -X deploy 21 | findstr /C:nexus-releases /C:401确认是权限问题的话在 Nexus 后台建个角色给nx-repository-view-maven2-maven-releases-add和nx-repository-view-maven2-maven-releases-read两条别直接给nx-admin。5.4 上传 release 报 400提示仓库不允许更新构件现象mvn deploy到maven-releases返回400 Bad Request报文里带Repository does not allow updating assets。原因maven-releases的writePolicy是ALLOW_ONCE同一个groupId:artifactId:version已经存在再推一次就被拒。这是刻意设计的防覆盖机制。解决正规做法是升版本号正式版本本来就不该覆盖。真到了需要强制覆盖的场合比如某个内部包第一次推错了在后台把maven-releases的写策略临时改成ALLOW重新推完再改回ALLOW_ONCE。千万别长期留着ALLOW下游构建的确定性就没了。5.5 代理仓库一直卡在 Downloading最后超时现象构建日志反复刷Downloading from maven-central几十秒后失败改动配置后重试还是同样的包失败。原因两种。一是remoteUrl在内网根本不通DNS 解析不了或者出网策略拦了二是上一次失败被negativeCache记下来了timeToLive内直接返回失败压根没重试。解决先绕开 Nexus 直接测远端连通性curl.exe -I -m 10 https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.pom返回200说明出网没问题那多半是 DNS 或者代理策略。通的话去看nexus.log里带Proxy关键字的行。要快速清缓存把negativeCache.timeToLive改小比如1或者直接重启服务让缓存失效验证完再调回1440。6. 上线前的一次快速验证清理策略、备份口径与四条验收命令装完不等于能用交出去之前我会跑一遍固定动作。先给 snapshot 仓库挂清理策略通过 REST 建{ name: snapshot-30d, format: maven2, notes: 保留最近 30 天的 snapshot, criteria: { lastBlobUpdated: 30, lastDownloaded: 90 } }curl.exe -u admin:你的密码 -X POST http://127.0.0.1:8081/service/rest/v1/cleanup-policies ^ -H Content-Type: application/json --data-binary snapshot-30d.jsonlastBlobUpdated是按最后写入时间算天数lastDownloaded是按最后被拉取时间算两个条件同时满足才删。挂完策略再去建一个Admin - Compact blob store的定时任务跟清理任务错开时间跑否则删掉的 blob 空间不会立刻还给磁盘会看到目录体积一直涨。四条验收命令按顺序走# 1. 匿名拉一个已知构件前提是开了匿名访问 curl.exe -s -o NUL -w %{http_code}\n ^ http://192.168.1.20:8081/repository/maven-public/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.pom # 2. 用一个干净本地仓库跑一次拉取验证不走公网 mvn -B -Dmaven.repo.localD:\tmp\m2test dependency:resolve -f 某个示例pom.xml # 3. 推一个 SNAPSHOT 上去确认写权限链路通 mvn -B deploy -DskipTests # 4. 查清理任务是否注册成功 curl.exe -s -u admin:你的密码 http://127.0.0.1:8081/service/rest/v1/tasks | findstr /C:cleanup第 2 条最容易被跳过但它的价值最高——用独立本地仓库跑一遍能暴露出所有「本机缓存掩盖掉的配置错误」。我见过太多次开发者本机~/.m2里早就有一堆包构建从来不走私服等到换机器或者上 CI 才炸。备份这块口径就一句话sonatype-work\nexus3整个目录加上etc\nexus-default.properties和bin\nexus.vmoptions两个文件。停服务、复制、启服务简单粗暴但不会错。热备份要用 blob store 的备份任务前提是数据量足够大、停服窗口拿不出来小团队没必要上。从那以后我每次装完 Nexus 都强制走一遍这四条命令哪怕只是换台机器重装。有一次图省事跳过了第 2 步结果上线当天才发现 group 里漏了一个成员仓库所有用到某个内部工具包的模块全部构建失败回滚加补配置折腾到半夜。私服这种基础设施出问题的时候是全团队一起等验收环节多花二十分钟比事后救火便宜太多。希望帮到你。本文还有配套的精品资源点击获取