feat: first-run claim wizard (no default admin, claim code from the backend log); owner list shows account and passkey; container install first [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful

This commit is contained in:
justme committed 2026-10-08 06:47:10 +08:00
1 parent 2ae63653c4
commit f22fdf8b68
31 files changed
+799 -49

No files matched your search

+7 -1
View File
@@ -42,12 +42,18 @@ Backend 使用 OCI 标准镜像,通过 `registry.oeo.one/moshiro/moshiro-backe
**前端内嵌在 Backend 里**:CI 构建 Backend 前先构建 `web/display` 和 `web/admin`,`Backend.Api` 把两个 `dist` 嵌进程序,展示端在 `/`,管理端在 `/admin/`,所以面板的域名(如 `https://mo.oeo.one/admin/`)打开就是管理端,passkey 才能绑定在这个域名上(浏览器只允许页面的来源与 RP 域名一致,本机 `localhost` 上的页面注册不了绑定 `mo.oeo.one` 的 passkey)。本地没有构建前端时不嵌入,Backend 只提供 API。文件是启动时读进内存的白名单,请求时不访问文件系统;带 `..`、反斜杠、`%`、控制字符或空段的路径一律 404,缺失的文件(带扩展名)404,只有无扩展名的路径回退到入口页;`/api`、`/openapi`、`/install`、`/healthz` 下没有匹配到的路径仍是后端的 JSON 404。页面带 CSP(脚本只许同源)、`nosniff`、`X-Frame-Options: DENY`,入口页 `no-cache`,哈希文件名的资源 `immutable`,不嵌入 source map。部署时设置 `MoShiro__PublicUrl=https://<面板域名>`(`deploy-node.sh backend --public-url …`),WebAuthn 的域名和允许的来源由它派生。
在部署目录保存此仓库的 `compose.yaml`,先通过部署平台的环境变量或密钥管理设置 `MOSHIRO_ADMIN_PASSWORD`(可选设置 `MOSHIRO_ADMIN_USER`、`MOSHIRO_VERSION`),然后启动:
在部署目录保存此仓库的 `compose.yaml`,可选设置 `MOSHIRO_CLAIM_CODE`(认领码,不设置就随机生成并写进后端日志)和 `MOSHIRO_VERSION`,然后启动:
```sh
docker compose up -d
```
**首次认领(没有默认管理员)**:面板里还没有任何用户时,打开 `/admin/` 会进入认领向导:
1. 填认领码(首次启动时随机生成并写进后端日志,`journalctl -u moshiro-backend` 或 `docker logs`;也可以用 `MoShiro__ClaimCode` / `MOSHIRO_CLAIM_CODE` 指定)、管理员的用户名和密码;
2. 注册你的第一把 passkey;
3. 用它给操作员集合签名,建立信任根。
谁先打开页面谁就能当管理员,所以认领码只有能看到后端日志的人拿得到;创建完第一个管理员,码作废、入口关闭(再提交返回 409)。认领码比较不分大小写、忽略分隔符;失败按来源地址限流。向导可以中途离开,passkey 和信任根之后随时在「用户 → 我的 Passkey」和「系统 → 信任」里补;没有 passkey 也能用密码登录管理。
Compose 将容器端口只绑定到宿主机 `127.0.0.1:8080`,适合由同机 HTTPS 反向代理转发;数据保存在命名卷 `moshiro-backend-data`(Docker 和 Podman 通用,`podman compose` 也可以用同一份文件)。首次启动成功创建管理员后,改密应在管理端完成。
Backend 的 NativeAOT 发布默认启用 `SqliteStaticLink`,支持 Linux glibc/musl、macOS、Windows 的 x64/arm64 RID;跨平台构建使用 `-p:UseAotAnywhere=true`。SQLite 源码版本、下载年份和 SHA-256 统一配置在根目录 `Directory.Packages.props`,构建会校验下载文件并按 RID 缓存原生对象。普通 JIT 开发构建仍使用 NuGet 原生库。发布 Backend 时设置 `-p:OpenApiGenerateDocuments=false`,API 文档在普通开发构建中生成。