Skip to content

fix(install): 应急密码不再依赖 journal,新增 --reset-password - #16

Merged
stqfdyr merged 5 commits into
mainfrom
fix/reset-password
Sep 19, 2026
Merged

stqfdyr merged 5 commits into
mainfrom
fix/reset-password

Conversation

@stqfdyr

@stqfdyr stqfdyr commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

问题

首次启动的应急密码只打印到 stdout,由 systemd 转进 journal,安装器在服务启动 3 秒后查一次 journal 取密码。journald 不保存日志的主机上(例如 Storage=none):

  • 安装器读不到,只显示 journalctl -u monitor-hub | grep Emergency
  • 这条命令也查不到,而密码只生成一次,只能删库重装

有用户在 GCP 的 Ubuntu 24.04 上遇到:服务正常运行,journalctl -u monitor-hub 返回 -- No entries --。

在面板里改过密码又忘了的(#22),journal 里只有最初那个,同样找不回。

修改

hub

  • 新增 --reset-password:设置新的随机 24 位密码、登出所有会话、打印 Emergency password: … 后退出,不监听端口。数据库文件不存在时报错退出,不会因为路径写错新建空库、打印一个无效的密码
  • 运行中的 hub 每次请求都从数据库读取密码哈希与会话,重置无需重启;实时推送流每 2 秒校验一次会话,随之断开
  • 新增 Db::replace_password,写哈希与清空会话在同一事务里:先写哈希、清会话失败时,旧密码已失效而新密码没打印出来。first_run、重置与面板改密码三处共用
  • 面板拒绝添加节点时的提示原来指向「README 的反代配置」,README 没有这一节,改为文档地址

install-hub.sh

  • 首次安装在服务启动前建好属主为 monitor 的空库文件,执行 --reset-password,直接从输出取得密码;hub 启动时密码已存在,不会再生成第二个
  • 首次安装时服务没能启动:不回滚,disable --now 并删掉这个库,重跑仍按首次安装显示密码。只停不禁用不够:下次开机旧版会在空库上生成一个只打进 journal 的密码,再跑安装器又被当成升级。旧二进制的备份留给下一次运行
  • --reset-password 失败(二进制早于这个参数)时,服务首次启动仍会生成密码并打印到 journal,改为从那里取,屏幕上不出现 unknown argument。只读这次 restart 之后的日志,两分钟内重跑时不会拿到上一次失败尝试的密码
  • 以 root 调用即可:SQLite 以 root 运行时会把新建的 -wal / -shm 交给数据库文件的属主(robustFchown)
  • 两处都取不到才提示重跑安装器选「重置密码」;改密码的位置更正为「安全」页
  • 菜单新增 5 重置密码,非交互用 --reset-password --yes。二进制不存在(例如 --uninstall 之后)时提示未安装;失败时提示 unknown argument 即版本过旧,需先升级

附带:装完不再打印反向代理配置

  • 删掉 caddy、nginx、cloudflare 隧道三份配置与「见 README 的「反向代理」一节」,改为在「还差一步」下给出 https://monitor-document.pages.dev/install/reverse-proxy
  • 文档里的配置按默认端口 28080 写,端口不是 28080 时多提示一行替换成实际端口
  • --help 里的「装完会打印具体怎么配」改为指向文档地址

测试

cargo fmt --check、cargo clippy --all-targets(无警告)、cargo test(99 个)通过。first_run 的测试补上重置:哈希轮换、已有会话失效。

Ubuntu 24.04 + systemd 容器,journald 配 Storage=none,发布下载替换为本地二进制:

  • 旧脚本 + v1.1.0:显示 journalctl -u monitor-hub | grep Emergency,复现上述问题
  • 全新安装:直接显示密码,登录 200
  • 服务运行中 root 执行 --reset-password --yes:旧密码 401、旧会话 401、新密码 200
  • 服务停止时 root 重置:数据目录下文件属主均为 monitor,服务启动后新密码 200
  • 重跑升级:不显示密码,原密码仍可登录
  • 首次安装时服务起不来(drop-in ExecStartPre=/bin/false):数据目录清空、服务停止;去掉 drop-in 重跑显示「安装完成」和密码,登录 200
  • --db 指向不存在的路径、或不带 --db:报 no database at …,退出码 1,不建文件
  • 非交互不带 --yes:拒绝;--uninstall 保留数据后重置:提示未安装;菜单选 5:确认后显示新密码
  • 装着 v1.1.0 时重置:报 unknown argument 并提示先升级;升级后重置,登录 200
  • 反代提示:默认端口时只显示文档地址,--port 29000 时多一行端口替换提示

补充一轮(Ubuntu 24.04 + systemd 容器,下载的是 GitHub 上的 v1.1.0 发布):

  • 新脚本首次安装:v1.1.0 不认 --reset-password,从 journal 取到密码并显示,登录 200,错误密码 401
  • 停服务、删库,加 drop-in ExecStartPre=/bin/false 后重跑:报「服务启动失败」,unit 为 disabled、inactive,数据目录下没有库,旧二进制的备份还在;去掉 drop-in 两分钟内重跑:显示「安装完成」和一个新密码(不是第一次那个),登录 200,unit 重新 enabled

未实测:Docker 镜像内 docker exec monitor /monitor-hub --db /data/monitor.db --reset-password。

兼容与发布

无 schema、接口、agent 协议变化。

脚本从 main 取,二进制从 latest release 取。合并到发版完成之间,新脚本配 v1.1.0 首次安装会从 journal 取密码,和现在一样;菜单里的「重置密码」要等新版本二进制,会提示先升级。journal 不存日志的主机仍要等发版,所以合并后仍应尽快发版,但两者之间不再有「首次安装拿不到密码」的窗口。

Closes #22

首次启动的应急密码只打印到 stdout,安装器从 journal 里读取。journald 不保存
日志的主机上(例如 Storage=none)安装器读不到,事后也无从找回,只能删库重装。
GCP 上的 Ubuntu 24.04 有用户遇到:journalctl -u monitor-hub 没有任何记录。

hub 新增 --reset-password:设置新的随机密码、登出所有会话、打印后退出。运行中
的 hub 每次请求都从数据库读取密码哈希与会话,无需重启。

install-hub.sh 首次安装时在服务启动前以 monitor 用户调用它,直接从输出取得
密码;菜单新增「重置密码」,也可用 --reset-password 非交互调用。
- --reset-password 在数据库不存在时报错退出,不再新建空库并打印一个无效的密码
- 写入密码哈希与清空会话合入同一事务,面板改密码共用 Db::replace_password
- 首次安装先建属主为 monitor 的空库文件再重置;服务没能启动时停掉服务并删除
  该库,重跑仍按首次安装显示密码
- SQLite 以 root 运行时会把新建的 -wal / -shm 交给数据库文件的属主,安装器
  不再经 runuser 调用
- 重置前检查二进制是否存在;失败时提示版本过旧需先升级
- 提示里改密码的位置更正为「安全」页
caddy、nginx、cloudflare 隧道三份配置与文档重复维护,改为在「还差一步」下给出
反向代理文档的地址。文档里的配置按默认端口 28080 写,端口不同时多提示一行
替换。--help 同步改为指向文档。
- --reset-password 失败(二进制早于这个参数)时,服务首次启动仍会生成密码并打印到 journal,
  改为从那里取。新脚本配旧发布首次安装也能拿到密码,脚本与发版之间不再有先后依赖。
  首装那一次调用不再把 unknown argument 打到屏幕上。
- 首次安装失败而回滚到旧二进制时(例如删了数据库重装),不再启动旧版:空库上它会生成一个
  只打印进 journal 的密码,下次重跑又被当成升级而不显示。
- 面板拒绝添加节点时的提示原来指向 README 的反代配置,README 没有这一节,改为文档地址。
- drop_all_sessions 的文档注释被 replace_password 挤走了,放回原处,用途更正为恢复备份之后。
- 首次安装没有要保住的服务,失败时不再回滚到旧二进制,改为 disable --now 并删掉新库。
  只是不重启旧版还不够:unit 仍开机自启,下次开机旧版照样在空库上生成一个只打印进 journal 的
  密码,再跑安装器又被当成升级。备份留给下一次运行。
- 回退读 journal 时只看这次 restart 之后的日志。两分钟内重跑时,上一次失败尝试打印过的
  密码(对应的库已删掉)不会被当成这次的。
@stqfdyr
stqfdyr merged commit e6762b0 into main Sep 19, 2026
1 check passed
@stqfdyr
stqfdyr deleted the fix/reset-password branch September 19, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

应急密码重设假如忘记后,重新打印的密码似乎是初始密码

1 participant