跳转到内容

首次启动、离线配置与认领设备

Mica OS 设备必须在零外部输入的情况下抵达完全可用状态——没有 DHCP 服务器、没有 DNS,甚至可能没有网线。这个性质是设计出来的,不是碰巧。本页讲首次启动自己 做了什么、完全没有网络的设备走哪条离线路径,以及设备如何从“未认领”变成 你的。

从空 DATA/state 的首次启动,管理守护进程会在任何东西消费它之前,一次性、原子地 播下设备配置:

  • 设备 id——从系统 CSPRNG 抽取的 32 个十六进制字符;
  • 主机名——mica- 加设备 id 的前八个十六进制字符。它派生自身份而不是 网络,因此跨子网、跨租约续期、换网卡都稳定,也短到可以印在标签上;
  • 每设备密钥,在设备上生成——绝不烤进镜像,镜像在同一发布版的每台设备 上是逐字节相同的;
  • SSH 关闭,两个镜像 profile 都是;
  • 没有有线网络配置——这是故意的。镜像自带一条针对有线 eth* 接口的静态 DHCP 匹配,因此新设备能在任何 DHCP 网络上拿到地址,而 micad 不必去猜接口 名字;
  • 在带 WiFi 的产品上,出厂接入点打开、WiFi station 关闭,除非配置文档声明了 网络(第 2 节)。

持久化回滚记录覆盖 DATA 上的配置文档与 DATA/state 上的身份记录;未完成的恢复必须在 下一次启动读取设置前完成(../../integrate/provisioning.md)。 播种失败会大声中止,下一次启动从头重试;一台看起来配置好了、其实只配了 一半的设备正是这个设计要拒绝的失败。SSH 主机密钥在设备上于首次启动时生成, DATA 也在此时扩展到占满磁盘(见 install.md)。

status: shipped — evidence: docs/integrate/provisioning.md, mica-system-base:payload/usr/lib/mica/mica-seed-state

所有当前目标均由原生 init 在服务启动前将 machine id 建立并保存在 DATA/state, 再只读绑定到 /etc/machine-id。它跨重启和组件更新保持稳定;格式错误或不可用的 身份会被拒绝,不会静默生成临时替代身份。

status: shipped — evidence: mica-core:crates/mica-deploy/src/bin/mica-runkit/init.rs, mica-build:src/verify/checks-file-root.ts

  • 在 DHCP 网络上:设备在有线接口上请求地址,并把 mica-xxxxxxxx 主机名 通告给 DHCP 服务器。不论 DNS 如何,这个名字在设备本地总能解析。
  • 管理接口是设备地址上的 apid:出厂时是 8080 端口上的明文 HTTP。在控制台的 访问页面(或 PUT /api/v1/web)开启 HTTPS 后,它在 8443 端口用每设备生成的证书提供 服务,8080 只做重定向;第一次 HTTPS 访问会看到自签名证书警告——这是预期行为,值得向 操作者解释清楚,而不是训练他们对所有警告视而不见。操作者也可以上传设备自己的证书。

status: shipped — evidence: mica-core:crates/mica-apid, docs/reference/remote.md

  • 通过出厂接入点,在带 WiFi 的产品上(cx3576.full、s905x5m.sd-full、 s905x5m.emmc-full):设备标签上印着设备码(形如 DFN4-L34C-T8N)、 接入点名称(mica- 加四个字符)和密钥,另有一个二维码。连上该网络,打开 http://192.168.4.1:8080。在 core 0.0.3 上,标签上的密钥只在设备未认领时 有效:认领会把它换成你选择的密钥,或设备生成并只显示一次的密钥(第 4 节)。 从 core 0.0.4 起,认领后它仍然有效,直到你在控制台的 Wi-Fi 页面设置自己的 密钥。恢复出厂设置会让标签密钥重新生效。设备上 micad device-code 打印设备码, 从 core 0.0.4 起设备自己的控制台也在登录提示处显示它;设备上没有任何东西会打印 密钥。
  • 标签密钥是首次接触凭据,不是秘密:产品的每个镜像都带着推导它的产品密钥, 因此拿到镜像又看到标签的人都能算出它 (../security/overview.md 第 3 节)。

status: board-dependent — evidence: mica-core:docs/factory-ap-key.md, mica-build:boards/products.md

在 cx3576 上,两个以太网口都没有硬件 MAC 地址,因此设备会用 eMMC 芯片标识 与该网口在板上的挂接位置为每个口推导一个地址。这样得到的地址在重启、重新 烧录和镜像升级之后都保持不变。

地址依据 eMMC CID 和物理拓扑计算,不依赖接口探测顺序。当前开发验收全部使用 完整最新版系统;请记录实际读到的板卡接口及地址。

status: board-dependent — evidence: mica-build:boards/cx3576/package/hwinit/hwinit-mac, mica-build:boards/cx3576/package/init/mac.conf, mica-build:make os-mac-test

对于没有可控网络的设备,或必须开箱即配好的设备,配置手段是配置文档: 一个名为 mica-provisioning.toml 的 TOML 文件,放在介质文件系统的根目录, 在首次启动过程中被读取一次,并在其他一切之前应用。

**先读这一段,因为这里最常被误判为“功能坏了”:配置文档只在设备还没有 管理员凭据时才被采纳。**设备一旦被认领——通过 setup,或通过更早的一份 文档——介质上提供的文档就会以 already-claimed 被拒绝,上面的内容一样都 不会应用。**已经上线的设备不能用 U 盘重新配置。**正是这条规则让一个不带 签名的传输通道是安全的,它不是一个需要绕过去的缺陷:重新配置已认领的设备 走的是带认证的 API。往运行中的设备里插卡却什么都没发生的操作者,看到的是 这条规则,不是一次失败。

通道 文件放哪 何时被读
boot 当前 UEFI ESP,GPT 标签为 esp;cx3576 没有 ESP,使用可移动介质 优先;可以把介质取出后用任意读卡器写入
media 已连接的可移动块设备——先看它的各个分区,再看裸盘 仅当引导分区上什么都没有时

两者都只在启动时读一次,在任何东西开始监听之前。这里故意没有 udev 触发,也没有任何 HTTP 路由能应用一份文档:之后才插上的 U 盘是下一次启动的 文档,永远不是重新配置运行中设备的途径。设备启动所用的内置 eMMC 或 NVMe 永远不会成为 media 的候选。挂载不上的介质根本不会变成一份文档,因此 journalctl -u mica-provisioning-import 才是“插了 U 盘却没反应”时第一个要 看的地方——而不是状态路由。

status: board-dependent — evidence: mica-system-base:payload/usr/lib/mica/mica-provisioning-import, mica-build:boards/cx3576/board.env, mica-build:boards/uefi-x64/board.env

它能带什么,以及它点名拒绝什么

Section titled “它能带什么,以及它点名拒绝什么”

一份文档可以设置设备身份、第一个管理员密码和授权 SSH 公钥、有线网络设置、 WiFi 客户端网络,以及时间设置。每个键都映射到一个已经存在的设置,并且经过 与 API 写入完全相同的校验器。

有两样东西是被点名拒绝的,要求它们是错误而不是遗漏:证书段和 主机名。两者都没有对应的设置路径——设备上唯一的证书是 apid 自己的 自签名 TLS 密钥对,那是 DATA/state 上的文件而不是设置;而设备的名字是从文档 注入的身份派生出来的。携带其中任何一项的文档都会被拒绝,并点出违规的键。

还有两条操作者必须据以规划的性质:

  • 整份文档在应用任何一部分之前先被完整校验。一个字段有问题,就一个字段 都不应用;拒绝信息给出键路径而绝不给出取值——所以格式错误的文件不会 把它携带的密码泄进日志,也不会留下一台配了一半的设备。被拒绝不等于变砖: 设备会以未认领、可配置的状态启动。
  • **两条通道都不校验签名。**这句话要直说,因为靠推断的读者可能推错:文档 不会被拿去和任何密钥比对。它唯一的授权就是对介质的物理占有,边界是上面 那条“已认领即拒绝”的规则。

文件会原样留在介质上——不删除、不改写。请把配置介质当作凭据材料对待, 因为一份文档可能携带管理员密码和 WPA2 预共享密钥,而同一份文档可能被写进 一整批卡。

GET /api/v1/provisioning/status 向已认证的调用方报告最后应用的文档版本与 摘要,以及最后一次导入尝试做了什么。它不返回文档携带的任何取值。

status: shipped — evidence: mica-core:crates/micad/src/provisioning_doc.rs, mica-core:crates/mica-apid/src/provisioning_api.rs, docs/integrate/provisioning.md

**哪些从未在硬件上执行过。**文档解析器、它的校验器和状态路由都有测试覆盖。 传输通道没有:没有任何测试、没有任何台架运行把真实的引导分区或真实的 U 盘送进一次真实启动,其中引导分区通道尤其从未在物理板卡上跑过。机制发布 了;流程没有被证明,而记录一次真实运行的地方是板卡页 (../../hardware/qualification.md)。

status: shipped — evidence: mica-system-base:payload/usr/lib/mica/mica-provisioning-import, docs/integrate/provisioning.md

认领就是“未认领 → 已认领”的那次转变,判定设备在哪一侧的唯一事实是管理员 凭据是否存在。能创建第一个凭据的通道正好三条:

  1. Setup——第一次访问 /_ui/,API 客户端则是 POST /api/v1/setup。 管理员密码由你选择;该路由建立浏览器会话,不铸出 API token。 对已认领的设备再调一次 setup 会以 already_configured 被拒绝,且不写入任何东西。从 core 0.0.4 起,在有设备码的设备上,setup 还会 要求输入设备码(印在标签上,也显示在设备自己的控制台上,即串口或显示器的 登录提示),以证明认领者持有这台设备:一旦蓝牙把未认领的设备 接入了网络,能打开它的控制台就不再是这种证明。输错设备码会计入登录退避。
  2. 配置文档——第 3 节。密码来自介质。
  3. 蓝牙,仅限 core 0.0.3——在未认领设备附近的手机,见第 5 节。认领通道记为 ble。从 core 0.0.4 起,手机只设置网络、不认领任何东西,设备通过 setup 认领。

在 core 0.0.3 上,在带 WiFi 的产品上,通过 setup 或蓝牙认领还会替换接入点的 标签密钥:换成调用方发送的密钥,或换成十六个随机字符——应答只携带一次,控制台 在进入前显示。通过配置文档认领不设置密钥,设备退回到首次启动时自己生成的密钥。 从 core 0.0.4 起,任何认领都不设置密钥:标签上的密钥一直有效,直到你在控制台的 Wi-Fi 页面设置一个。

从认领开始,每一次管理读写都需要认证。会话与 token 模型见 ../operate/api.md,接下来配置什么见 ../operate/configuration.md。GET /api/v1/claim 向已认证的调用方 回答是哪条通道、在什么时候认领了这台设备。

由配置文档认领的设备持有的是一个 bootstrap 秘密:它以明文躺在一份设备 故意不去擦除的介质上,而同一份文档可能被写进一整批卡。因此这类认领会置上 rotationRequired。在它被解除之前,设备服务所有读取,但对每一次已认证的 写操作返回 409 rotation_required——例外只有登录、读取原因,以及 POST /api/v1/actions/change-password 这一个能解除它的动作。通过 setup 认领则不会置这个标志:那个密码是调用方在认领当刻选定的,从未被写在设备 能够推理的任何地方。

这个约束是“首次登录”,不是经过的时间,也没有任何东西在倒计时。一台 已认领但从未被登录过的设备,其 bootstrap 凭据无限期有效——一台带着卡 下线、又在仓库里躺了一年的单元,开箱那天握着的仍是同一个可用密码。这是 故意的:这台设备不会拿自己的时钟去执行任何期限,因为未认领的设备恰恰就是 没有同步时钟的设备,而一个关闭时里面没人的窗口只会留下一台谁也进不去的 设备。**把“强制轮换”读成“凭据会自己失效”的读者,规划的是一个并不存在的 暴露窗口。**在首次登录之前限制这个暴露的,是对介质的物理保管,没有别的。

  • **它不是 SSH 凭据。**SSH 保持关闭,直到一位已认证的管理员启用它并装入 公钥——访问模型见 ../security/overview.md。
  • **它今天无法由设备本身恢复。**在现有的任何板卡上,丢失管理员凭据和全部 授权公钥就意味着没有软件路径能回到设备里。凭据恢复流程是建好的,而它在 已上线的设备上会被拒绝,原因见 ../operate/recovery.md 第 5 节。 请据此保管凭据。

status: shipped — evidence: mica-core:crates/mica-apid/openapi.json, docs/reference/access.md

在带 WiFi 和蓝牙的产品上(cx3576.full、s905x5m.sd-full、s905x5m.emmc-full), 手机可以不连设备的接入点,就把要加入的 WiFi 网络告诉设备,在 core 0.0.3 上还会在 设备未认领时认领它。从 core 0.0.4 起,手机也可以设置有线网口。设备只在配网窗口打开时广播:

窗口 何时打开 何时关闭 手机需要
未认领 未认领设备的每次启动 启动后 10 分钟,或手机完成时 无
启动 已认领设备的每次启动 启动后 10 分钟,或手机完成时 管理员密码
离线 已认领设备失去默认路由 120 秒,且 bluetooth.provisioning.autoWhenOffline 开启(默认) 路由恢复,或手机完成时 管理员密码
手动 管理员在控制台打开,5、10 或 30 分钟 时间到、控制台关闭,或手机完成时 控制台显示的临时码
  • 手机端是网页 https://init.micaos.dev,用 Android 或桌面上的 Chrome、 Edge 打开。iOS 浏览器没有 Web Bluetooth,页面在那里只做说明。
  • 在 core 0.0.3(2026-10-21 发布)上,页面为未认领设备设置管理员密码;认领在手机 完成时生效,先完成的手机胜出。因此这样的设备在每次启动后 10 分钟内,蓝牙范围内 的任何人都能认领它;请尽快认领,或在它离开你的保管之前认领。
  • 从 core 0.0.4 起,蓝牙不认领任何东西,除网络外什么都不设置:手机设置 WiFi 网络或 有线网口的地址;设备保持未认领,页面最后一屏引导你打开控制台,由控制台的 setup 要求输入管理员密码和设备码(在标签上,也在设备自己的控制台上)。主机名在那里 设置,或以后在控制台修改。只配置有线时,接入点保持开启、使用标签上的密钥, 认领后也保持这个密钥,直到你在控制台设置自己的密钥。认领之前,设备每次启动都会重新打开未认领窗口。
  • 密码窗口需要密码的验证数据,设备在管理员登录控制台时生成;自从设备获得这项 功能以来没人登录过的设备,会回答它无法使用密码。
  • 窗口打开期间,即使蓝牙开关关闭,适配器也会上电。输错密码会累计到锁定,锁定 期间设备停止广播。

status: board-dependent — evidence: mica-core:docs/ble-provisioning.md, mica-core:docs/factory-ap-key.md, mica-build:boards/products.md

**尚未在硬件上执行过的部分。**协议、设备端和网页都用对方的参考实现做了测试, 网页也已部署;还没有在实体板卡上运行的记录。