
半夜收到做运维的老哥发来的一条消息他们厂里一台跑了好几年的 Nexus 3admin 密码白纸黑字写在交接文档上可就是登不进去。文档里的试了、admin123 试了、自己所有常用密码也试了全不行差点直接把机器重装。其实 Nexus 管理员账号密码找回这件事几乎所有接手老仓库的人迟早都会碰上一次麻烦的地方在于——不同版本、不同部署形态密码存放的位置和重置手法完全不一样网上流传的很多办法只对某一个版本有效照抄到另一个版本上不光没用还可能把仓库数据搞坏。这里说的 Nexus主要是 Sonatype 的制品仓库 Repository Manager日常拿来当 Maven、npm、Docker 镜像的私服。它有两大分支老的 Nexus 2 和现在的 Nexus 3Nexus 3 内部又因为存储引擎在 3.70 前后换了OrientDB 换成 H2再往后支持外部 PostgreSQL处理路径又分出几条岔路。所以找回密码这件事第一步从来不是动手改文件而是先把版本和数据目录确认清楚。下面按三种方法讲删初始密码文件让程序自己重发、直接替换密码哈希、不动 admin 而是新造一个管理员账号。每一种都说清楚适用于哪个版本、为什么这样能行、以及哪一步最容易翻车。1. 先确认版本与数据目录比急着改文件重要得多1.1 动手前必须回答的三个问题我见过太多人一上来就搜nexus 密码忘了怎么办然后照着某个帖子删文件、改配置折腾两小时发现版本对不上。省时间的做法是先花五分钟回答三个问题。第一版本号是多少。最省事的办法是直接敲接口curl -s http://localhost:8081/service/rest/v1/status返回的 JSON 里带version字段不需要登录。如果 Nexus 没起在 8081就看你部署时改的端口。裸机部署还能从安装目录名看出来比如/opt/nexus-3.68.1-01这种目录名里的数字就是版本。容器部署看镜像 tag或者进容器ls /opt/sonatype/nexus/lib找版本相关的 jar。第二用什么方式部署的。裸机 tar.gz、RPM/DEB 包、Docker、K8s这四种情况下数据在哪、怎么停服务完全不同。Docker 部署最大的坑是你以为改的是宿主机文件其实改的是容器内层或者反过来改了宿主机挂载点却忘了容器里跑的还是老进程。第三数据目录落在哪。Nexus 3 的数据目录叫nexus-data裸机默认在安装目录同级的sonatype-work/nexus3容器里固定是/nexus-data。可以用ps -ef | grep nexus看启动命令里有没有-Dnexus-work参数或者直接看bin/nexus.vmoptions里的配置。确认不了就find / -name admin.password 2/dev/null能搜到基本就定位了。1.2 密码在不同版本里到底存在哪这是整篇文章最核心的一张表建议先扫一眼再往下读。因为密码存在哪直接决定了你能用哪种方法。版本分支初始密码从哪来手工改过密码之后存在哪关键文件/位置Nexus 2.x固定值 admin/admin123配置文件里的用户节点数据目录conf/security.xmlNexus 3.0 - 3.69首次启动随机生成嵌入式 OrientDB 的用户记录admin.password文件 db/目录Nexus 3.70 及以上内置 H2首次启动随机生成H2 数据库的用户表admin.password文件 db/目录Nexus 3.71 及以上外接 PostgreSQL首次启动随机生成PostgreSQL 里的用户表admin.password文件 外部库有个规律你可以直接记住admin.password这个文件在说明密码还是系统发的那串随机值文件不在说明已经有人手动改过了。这个判断比什么都重要因为方法一只对文件还在的情况有效。注意Nexus 3 每个小版本的表结构和字段名都可能微调上面表格里写的是大类位置。真要动数据库务必先用只读的方式把结构查出来再改。1.3 动数据库之前必须做的三件备份改哈希、改数据库这类操作是不可逆的做之前请认真做完这三件事。停服务再备份。Nexus 跑着的时候数据库文件是打开的直接拷可能拷到一个不一致的中间状态。正确顺序是停服务、等进程完全退出、再把整个nexus-data目录打包。别只备份db子目录etc目录里的配置比如nexus.properties和blobs里的制品一样重要。整个目录打个 tar 包几百 G 的仓库也要这么做一次压缩选项可以不加速度优先。记下当前的部署参数。端口、JVM 参数、nexus-work路径、容器的卷映射关系全部抄一份出来。恢复的时候这些是刚需。留出回滚的窗口。生产仓库建议安排在业务低峰做。真正麻烦的不是密码而是你改坏了数据库之后CI 流水线全部拉不到依赖那时候压力就不是一般的大了。2. 删掉初始密码文件让 Nexus 3 自己重新生成2.1 这个文件为什么存在删了为什么管用Nexus 3 从设计上就不允许出厂弱口令。首次启动的时候它会随机生成一串密码写到数据目录下的admin.password文件里同时把这一行打印到log/nexus.log。你用这串密码登录、并在界面上把密码改成自己的之后Nexus 会主动把admin.password删掉表示初始密码已经作废。所以逻辑链很清楚文件是 Nexus 自己管理的删掉之后重启它会认为这个实例还没完成初始化于是重新随机生成一份再写回文件。整个过程不需要你知道任何旧信息也不用碰数据库。这是三种方法里风险最低、步骤最少的一种。2.2 裸机部署的完整操作链路假设你是 systemd 管理的裸机部署数据目录在/opt/sonatype-work/nexus3完整流程是这样# 1. 确认服务名和状态 systemctl status nexus ps -ef | grep -v grep | grep nexus | head # 2. 停服务确认进程真的没了 sudo systemctl stop nexus ps -ef | grep -v grep | grep nexus # 3. 看一眼文件在不在顺手备份一份 ls -l /opt/sonatype-work/nexus3/admin.password sudo cp /opt/sonatype-work/nexus3/admin.password /tmp/admin.password.$(date %s) # 4. 删掉它 sudo rm -f /opt/sonatype-work/nexus3/admin.password # 5. 起来然后盯日志 sudo systemctl start nexus tail -f /opt/sonatype-work/nexus3/log/nexus.log | grep -i password for user有一个细节很多人会踩有些版本重新生成的那一次只写文件、不往日志里打印。所以如果 grep 半天没输出别急着重启第二次直接去看admin.password文件有没有重新冒出来cat一下就是新密码。重启两三次反而可能让你分不清哪个密码是新的。2.3 Docker 部署下的差别在哪容器部署的时候admin.password在容器内的/nexus-data下而/nexus-data通常是挂载出来的卷。你需要先搞清楚它映射到宿主机的哪个目录。# 找到容器的挂载信息 docker inspect -f {{ range .Mounts }}{{ .Source }} {{ .Destination }}{{ \n }}{{ end }} nexus # 假设输出是 /data/nexus /nexus-data sudo rm -f /data/nexus/admin.password docker restart nexus docker logs -f --tail 200 nexus | grep -i password for user如果你不想在宿主机上操作也可以借一个临时容器把文件删掉关键是卷名要对写错卷名的话删的是另一个卷白忙一场。删完之后docker logs里没有输出同样别慌直接cat /data/nexus/admin.password。这里插一句权限的事。Nexus 官方镜像里跑进程的用户 UID 是 200宿主机上用 root 删文件没问题但千万别顺手对整个数据目录做chown root:root。属主一变容器里的 Nexus 用户就没权限写数据目录起来之后会直接报错退出日志里能看到 Permission denied 或者 Unable to create directory 之类的字样。2.4 什么情况下这个方法一定无效三种情况请直接跳到第三种方法别在这里浪费时间。admin.password本来就不存在。这几乎是最常见的情况——证明密码早被人改过Nexus 已经不认初始密码那套逻辑了删无可删。版本是 Nexus 2。Nexus 2 根本没有这个文件它出厂就是 admin/admin123改过的密码写在一个 XML 配置文件里处理方式见第 3 节和第 4 节。数据目录被挂成只读。看着文件删了、服务也重启了但就是没重新生成日志里往往有一行 IOException 或者 Read-only file system。这种情况多半是挂载参数或者文件系统层面的问题先修权限再谈重置。3. 替换密码哈希拿一台干净实例当密码生成器3.1 核心思路不要自己算哈希Nexus 存的从来不是明文密码而是加盐哈希。Nexus 3 里那串东西通常长得像$shiro1$SHA-256$...中间还有迭代次数和盐Nexus 2 用的是另一套算法。版本之间参数会变你想靠手算或者随便找个在线工具生成一串应该能对上的哈希失败概率非常高而且失败了也不报错你只会看到登录一直 401根本不知道问题出在哪。我用了很多次的办法是这样的在本地起一台和目标同版本的干净 Nexus用界面把它的 admin 密码改成你知道的一个值然后从它的存储里把那串哈希抄出来覆盖到目标实例上。同一个版本、同一套代码路径生成的哈希格式百分百兼容。具体操作下载对应版本的 tar.gz 包解压改一下端口避免和生产冲突启动用初始密码登录改成TmpPassw0rd这种你记得住的值。然后停掉这台干净实例去它的数据目录里把 admin 那条用户记录捞出来。整个过程十分钟出头。我在 3.29、3.68、3.70 这几个跨度很大的版本上都用过这一招没出过兼容问题。3.2 Nexus 3 三种存储后端的改法差异OrientDB3.70 之前。数据在db/目录下一堆文件里Nexus 自带 OrientDB 的命令行工具可以以嵌入式方式连上去。要点就两个必须先停掉 Nexus否则文件被锁住连不上用 Nexus 自带的那个 jar别用你自己下载的版本版本不匹配很容易读不出来。连上之后找到用户记录把 password 字段换成你抄来的哈希退出重启。内置 H23.70 及以后。db/下面能看到.mv.db后缀的文件用同版本 Nexus 自带的 H2 jar 打开# 先停掉 Nexus然后 java -cp /opt/nexus/lib/h2-*.jar org.h2.tools.Shell \ -url jdbc:h2:/opt/sonatype-work/nexus3/db/security \ -user sa -password 进去之后先别急着 UPDATE先SHOW TABLES把用户表和角色关联表的名字找出来再SELECT * FROM 用户表 WHERE ...看一眼 admin 那条记录长什么样。字段名和表名每个版本都可能不一样照着实际结构改不要照抄别人的 SQL。外部 PostgreSQL3.71 及以后。这种最舒服直接psql连上去就行。先确认连接串在etc/nexus.properties或者环境变量里然后同样先查结构、再改密码字段。唯一要注意的是如果数据库有主从确认你改的是主库改到只读从库上会直接报错或者更糟——改成功了但主库一同步就覆盖掉。3.3 Nexus 2 的 security.xml 怎么改Nexus 2 的用户和权限都写在一个 XML 文件里路径是数据目录下的conf/security.xml。停掉服务备份这个文件然后用编辑器找到 admin 那个user节点把里面的密码字段替换成干净实例生成的值。生成方式和方法二开头说的一样起一台同版本的干净 Nexus 2改密码抄哈希。同一个文件里还有角色绑定关系改密码只需要动密码字段别去碰角色那段除非你明确知道自己在干什么。有个更粗暴的兜底手段把整个security.xml改名或删掉重启后安全配置会回到出厂状态admin 密码回到默认值。但这招的代价是所有自定义用户、角色、权限分配全部清空仓库上的权限设计如果是精心配过的恢复起来非常痛苦。只有在仓库里根本没有细粒度权限、所有人都用 admin 的情况下我才建议用这个办法。3.4 改哈希时最容易翻车的四个细节属主问题。你用 root 编辑完文件、写完数据库文件的属主可能就变了。Nexus 进程用的是自己的用户读不到或者写不了就会出问题。改完之后chown -R回原来的属主容器场景要保证是 UID 200。运行中改库会被覆盖。这是导致改完重启又被打回原形的头号原因。Nexus 在运行期间会把内存里的安全状态定时刷回存储你在它跑着的时候改数据库过一会儿就被覆盖回去了。所有数据库级别的修改一律在停服状态下做。改错库文件。一个实例里可能有多个数据库文件配置库和组件库是分开的。改错了不会有任何报错只是完全没效果然后你会陷入明明改对了为什么没反应的自我怀疑。哈希抄串了。从干净实例里复制哈希的时候前后空格、换行、引号都很要命。复制完对比一下长度和前缀两个实例的哈希前缀应该是一模一样的。4. 绕开 admin 本身直接新造一个管理员账号4.1 什么时候新建比重置更聪明替换哈希这条路走不通的时候比如 admin 用户记录本身处于半残状态迁移过程中写坏了、字段缺失、角色绑定丢了或者你压根不确定原来那套哈希是不是被人改过算法这时候最稳的做法是别动 admin直接造一个新的管理员账号。好处有三个原记录一个字节都不碰失败了不会把事情弄得更糟新账号是你自己建的字段结构你完全清楚建好之后你可以用它登录再从容地把 admin 密码改回来。代价是要多理解一点数据模型——Nexus 3 里用户和角色之间是关联关系不像一张平表那么简单。4.2 Nexus 3 里补一条用户记录如果你用的是 H2 或 PostgreSQL这件事相对简单。先查结构-- 表名以实际查出来的为准 SELECT * FROM security_user WHERE user_id admin; SELECT * FROM security_user_role_mapping WHERE user_id admin;第一步看清楚 admin 记录里都有哪些字段、状态字段是什么值第二步把这条记录复制一份user_id改成recovery_admin、password换成干净实例生成的哈希、其他字段照抄第三步照着 admin 的角色绑定在角色关联表里给新账号插一条对应的记录。要是权限模型里有nx-admin这种内置角色绑它准没错。OrientDB 版本就麻烦一些它的用户是顶点、角色绑定是边。要先能连上嵌入式库然后照着 admin 的结构建顶点、建边。我个人的经验是OrientDB 场景下能用替换哈希解决就别走新建账号这条路图数据库的手工操作出错了排查起来很费劲。4.3 Nexus 2 里加用户更简单Nexus 2 是 XML直接照抄。停服、备份conf/security.xml、把 admin 那段user复制一份改 id 和密码字段然后在用户角色映射那段里照着 admin 的绑定加一份。改完重启用新账号登录。这个方法在 Nexus 2 上成功率很高因为结构是扁平的肉眼就能看懂谁绑了什么。唯一要留意的是 XML 的编码和转义别让编辑器改动了文件头。4.4 登进去之后必须马上做的几件事新账号能登进去只是第一步接下来这几件事没做等于白折腾。立刻改掉 admin 的密码用新账号登录后从界面上把 admin 重置成你知道的值。然后删掉临时账号别留在那里过年。如果中途动过security.xml回头把角色和权限重新对一遍尤其是匿名访问这个开关——出厂的默认配置不一定符合你的安全要求。再扫一遍系统任务和日志确认刚才那些操作没有留下奇怪的状态。最后把最终密码放进密码管理器或者配置中心别再一次写在纯文本的交接文档里。5. 改完之后仍然登不上几条排错链路5.1 服务起来了但一直 401先分清 401 和 403。401 是凭据不对403 是凭据对了但没权限。如果是 401第一个要怀疑的不是哈希算错了而是你改的是不是当前这台实例。多节点部署、测试环境和生产环境共用一套密码文档的情况太常见了。验证动作很简单curl -s 地址/service/rest/v1/status看返回的版本号跟你刚才操作的那台对不对得上再看数据目录里文件的时间戳是不是刚刚被改过。这两步能排掉一大半的乌龙。排除掉改错实例之后再回头核对哈希前后有没有多余空格、前缀跟干净实例的是不是一致、写的字段是不是密码字段而不是什么显示名字段。5.2 改完重启又被打回原形这个现象几乎只有一个原因你在 Nexus 运行中改了数据库被它的状态回写覆盖了。另一个变体是容器场景——你改的是容器内层的文件容器一重启卷挂载把改动盖掉了。K8s 里更明显你 exec 进 Pod 改了文件Pod 一旦重建改动全部消失。判断方法看文件修改时间如果数据文件的时间戳比你操作的时间晚那基本就是被覆盖了。解决办法只有一个老老实实停服、改文件、再启动。5.3 容器化部署里那些藏得很深的坑Docker 部署最容易出的事故是数据丢失而数据丢失往往不是密码操作导致的是卷本身就没配对。docker-compose.yml里忘了写volumes或者用了匿名卷容器一重建数据全没。所以在动手之前一定要用docker inspect把挂载关系打出来确认nexus-data映射到了一个真实的宿主机路径并且这个路径有备份。K8s 场景下确认 PVC 绑定的存储位置别只看 Pod 里的/nexus-data。现象优先怀疑验证动作文件删了没重新生成密码已被人改过 / 目录只读看数据目录写权限、看启动日志报错登录一直 401改错实例 / 哈希不兼容对比版本号、比对哈希前缀和长度重启后配置失效运行中改库被回写 / 卷被覆盖看数据文件时间戳、看容器挂载服务直接起不来文件属主被改 / 库文件损坏看日志开头报错、从备份恢复新账号登不上角色绑定没插 / 状态字段没设对对比 admin 记录的字段值5.4 一个我一直在用的排查顺序遇到密码改完登不上我自己的排查顺序固定是这五步第一看版本和数据目录有没有搞错第二看数据文件的修改时间对不对第三看日志里有没有权限和 IO 报错第四用干净实例的哈希重新覆盖一次第五还不行就从备份整体回滚再重做。这套顺序能覆盖我遇到过的绝大多数情况也能避免在错误的方向上越走越远。最后分享两个省时间的小技巧。一个是初始密码忘了但服务还能起的时候直接grep -i Password for user /nexus-data/log/nexus.log历史日志里很可能还留着那串密码。另一个是看不出 Nexus 版本的时候curl -s http://localhost:8081/service/rest/v1/status免登录就能拿到版本号比翻安装目录快得多。我个人更想强调的其实不是怎么找回密码而是找回之后怎么不再找第二次给每个人开独立账号、按角色授权、日常操作别用 admin仓库接上企业目录服务做统一认证admin 的密码放进密码管理系统而不是贴在交接文档里。真到了要靠删文件、改数据库才能进门的地步说明前期的账号管理已经欠了很久的账了。