First boot, offline setup and claiming the device
A Mica OS appliance must reach a fully working state with zero external input — no DHCP server, no DNS, possibly no cable. That property is designed in, not incidental. This page covers what the first boot does by itself, the offline route for configuring a device with no network at all, and how the device stops being unclaimed and becomes yours.
1. What the device does by itself
Section titled “1. What the device does by itself”On the first boot from empty DATA state directories, the management daemon seeds the device’s configuration once, atomically, before anything else consumes it:
- a device id — 32 hex characters drawn from the system CSPRNG;
- a hostname —
mica-followed by the first eight hex characters of the device id. Derived from the identity, not from the network, so it is stable across subnets, lease renewals and NIC replacements, and short enough to print on a label; - per-device secrets, minted on the device — never baked into the image, which is byte-identical across every device of a release;
- SSH off, on both image profiles;
- no wired network configuration — deliberately. The image ships a static
DHCP match for wired
eth*interfaces, so a fresh device acquires an address on any DHCP network without micad guessing interface names; - on a product with WiFi, the factory access point on, with the WiFi station off, unless a provisioning document declares a network (section 2).
A durable undo journal covers the DATA configuration documents and DATA identity record. A pending rollback must finish before the next startup can consume them (../integrate/provisioning.md). A failed seed aborts loudly and the next boot retries from scratch; a half-provisioned device that looks provisioned is the failure this design refuses. SSH host keys are generated on the device on first boot, and DATA grows to fill the disk (see install.md).
status: shipped — evidence:
docs/integrate/provisioning.md,mica-system-base:payload/usr/lib/mica/mica-seed-state
The authenticated early loader creates /mnt/data/state/machine-id before
systemd on every current target and binds it read-only at /etc/machine-id.
It stays stable across reboot, update and rollback. A complete reflash creates a
new identity. No identity is stored in the bootloader’s attempt records.
status: shipped — evidence:
mica-core:crates/mica-deploy/src/bin/mica-runkit/init.rs,mica-build:src/verify/checks-file-root.ts
2. Finding the device
Section titled “2. Finding the device”- On a DHCP network: the device requests an address on its wired interfaces
and announces the
mica-xxxxxxxxhostname to the DHCP server. Its own name also resolves locally on the device regardless of DNS. - The management surface is apid on the device’s address: plain HTTP on
port 8080 out of the box. Turn HTTPS on from the console’s access page (or
PUT /api/v1/web) and it serves on 8443 with a certificate generated per device, and 8080 only redirects there; a first HTTPS visit shows a self-signed-certificate warning — expected, and worth explaining to operators rather than training them to ignore warnings elsewhere. An operator can upload the device’s own certificate instead.
status: shipped — evidence:
mica-core:crates/mica-apid,docs/reference/remote.md
- Over the factory access point, on a product with WiFi (cx3576.full,
s905x5m.sd-full, s905x5m.emmc-full): the device’s label carries its
device code, printed
DFN4-L34C-T8N, the access point’s name (mica-and four characters) and its key, also as a QR code. Join that network and openhttp://192.168.4.1:8080. On core 0.0.3 the label’s key works only while the device is unclaimed: the claim replaces it with a key you choose or one the device generates and shows once (section 4). From core 0.0.4 it keeps working after the claim, until you set a key of your own on the console’s Wi-Fi page. A factory reset brings the label’s key back.micad device-codeprints the code on the device, and from core 0.0.4 the device’s own console shows it at the login prompt; nothing on the device prints the key. - The label’s key is a first-contact credential, not a secret: every image of a product carries the product secret it is derived from, so whoever holds an image and reads a label can compute it (../security/overview.md section 3).
status: board-dependent — evidence:
mica-core:docs/factory-ap-key.md,mica-build:boards/products.md
On cx3576 neither Ethernet port has a MAC address in hardware, so the device derives one for each of them from the eMMC chip identifier and from where the port is attached to the board. The addresses are therefore stable across reboots, reflashes and image updates.
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
3. The offline route: a provisioning document
Section titled “3. The offline route: a provisioning document”A device with no network you control, or one that has to arrive configured out
of the box, is configured by a provisioning document: one TOML file named
mica-provisioning.toml, at the root of a medium’s filesystem, read once
during the first boot and applied before anything else.
Read this first, because it is where the feature is most often assumed to be
broken: a provisioning document is honoured ONLY while the device has no
administrator credential. Once a device is claimed — by setup, or by an
earlier document — a document offered on a medium is refused with
already-claimed and nothing on it is applied. A fielded device cannot be
re-provisioned from a stick. That is the rule that makes an unsigned
transport safe, and it is not a defect to be worked around: reconfiguring a
claimed device goes through the authenticated API. An operator who pushes a
card into a running appliance and sees no change is seeing this rule, not a
failure.
The two transports
Section titled “The two transports”| Transport | Where the file goes | When it is read |
|---|---|---|
boot |
the UEFI ESP, by its GPT label esp; absent on cx3576 |
first; written with any card reader, with the medium out of the device |
media |
an attached removable block device — its partitions first, then the bare disk | when the ESP is absent or carries no document |
Both are read once, at boot, before anything is listening. There is
deliberately no udev trigger and no HTTP route that applies a document: a
stick pushed in later is a next-boot document, never a way to reconfigure a
running appliance. The internal eMMC or NVMe the device boots from is never a
candidate for the media source. A medium that will not mount never becomes a
document at all, so journalctl -u mica-provisioning-import is where an
operator whose stick did nothing looks first — not the status route.
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
What it may carry, and what it refuses by name
Section titled “What it may carry, and what it refuses by name”A document may set the device identity, the first administrator password and authorized SSH keys, wired network settings, WiFi client networks, and time settings. Every key maps onto a setting that already exists and is validated by the same validator an API write goes through.
Two things are refused by name, and asking for them is an error, not an omission: a certificate section and a hostname. There is no settings path for either — the only certificate on the device is apid’s own self-signed TLS pair, a file in DATA/state rather than a setting, and the device names itself from the identity the document injects. A document carrying either is refused naming the offending key.
Two more properties an operator has to plan around:
- The whole document is validated before any of it is applied. One bad field applies nothing, and the refusal names the key path and never the value — so a malformed file cannot leak the password it carries into a log, and cannot leave a device half-configured either. A refusal is not a brick: the device comes up unclaimed and configurable.
- Neither transport verifies a signature. Said plainly, because a reader who infers it can infer it wrong: the document is checked against no key at all. Its only authorisation is physical possession of the medium, bounded by the already-claimed rule above.
The file is left on the medium exactly as written — not deleted, not rewritten. Treat a provisioning medium as credential material, because a document may carry an administrator password and a WPA2 pre-shared key, and one document may be written onto a whole batch of cards.
GET /api/v1/provisioning/status reports, to an authenticated caller, which
document version and digest were last applied and what the last import attempt
did. It returns no value the document carried.
status: shipped — evidence:
mica-core:crates/micad/src/provisioning_doc.rs,mica-core:crates/mica-apid/src/provisioning_api.rs,docs/integrate/provisioning.md
What has never been executed on hardware. The document parser, its validators and the status route are covered by tests. The transports are not: no test and no bench run has staged a real boot partition or a real USB stick into a booting device, and the boot-partition transport in particular has never run on a physical board. The mechanism ships; the procedure is unproven, and a board page is where a run of it gets recorded (../hardware/qualification.md).
status: shipped — evidence:
mica-system-base:payload/usr/lib/mica/mica-provisioning-import,docs/integrate/provisioning.md
4. Claiming the device
Section titled “4. Claiming the device”The claim is the unclaimed → claimed transition, and the one fact that decides which side a device is on is whether an administrator credential exists. Exactly three channels can create the first one:
- Setup — the first visit to
/_ui/, orPOST /api/v1/setupfor API clients. You choose the administrator password; the route establishes a browser session and mints no API token. A second setup call on a claimed device is refused withalready_configuredand writes nothing. From core 0.0.4, on a device with a device code, setup also asks for that code, printed on the label and shown on the device’s own console (serial or display login prompt), as proof that whoever claims the device holds it: reaching its console is no such proof once Bluetooth has put an unclaimed device on a network. A wrong code counts towards the sign-in backoff. - A provisioning document — section 3. The password came off the medium.
- Bluetooth, on core 0.0.3 only — a phone in range of an unclaimed
device, section 5. The claim channel reads
ble. From core 0.0.4 a phone sets up the network and claims nothing; the device is claimed through setup.
On core 0.0.3, on a product with WiFi, the claim through setup or Bluetooth also replaces the access point’s label key: with the key the caller sends, or with sixteen random characters the answer carries once and the console shows before it enters. A claim by provisioning document sets no key, and the device falls back to a key it generated at first boot. From core 0.0.4 no claim sets a key: the label’s key applies until you set one on the console’s Wi-Fi page.
From the claim onward, every management read and write is authenticated. See
../operate/api.md for the session and token model and
../operate/configuration.md for what to configure next.
GET /api/v1/claim answers, to an authenticated caller, which channel claimed
the device and when.
The rotation bound, and what it does not do
Section titled “The rotation bound, and what it does not do”A device claimed by a provisioning document holds a bootstrap secret: it
sat in plaintext on a medium the device deliberately does not erase, and one
document may have been written onto a batch of cards. So that claim sets
rotationRequired. Until it is discharged, the device serves every read and
refuses every authenticated mutation with 409 rotation_required —
except signing in, reading why, and POST /api/v1/actions/change-password,
which is the one action that clears it. A claim through setup sets no such
flag: that password was never written down anywhere the device can reason
about.
The bound is FIRST SIGN-IN, not elapsed time, and nothing counts down. A device that is claimed but has never been signed into keeps its bootstrap credential working indefinitely — a unit that came off the line with a document on its card and then sat in a warehouse for a year is holding the same working password on the day it is unboxed. That is deliberate: this appliance enforces no deadline against its own clock, because an unclaimed device is exactly the device with no synchronised clock, and a window that closed with nobody in it would leave a device nobody can get into. A reader who takes “forced rotation” to mean the credential stops working on its own will plan an exposure window that does not exist. What bounds that exposure before the first sign-in is physical custody of the medium, and nothing else.
Two things the claim is not
Section titled “Two things the claim is not”- It is not an SSH credential. SSH stays off until an authenticated administrator enables it and installs a key — ../security/overview.md covers the access model.
- It is not recoverable by the device today. Losing the administrator credential and every authorized SSH key leaves no software path back in on any board that exists. A credential-recovery flow is built and is refused on a fielded device for the reason ../operate/recovery.md section 5 states. Store the credential accordingly.
status: shipped — evidence:
mica-core:crates/mica-apid/openapi.json,docs/reference/access.md
5. Setting up from a phone over Bluetooth
Section titled “5. Setting up from a phone over Bluetooth”On a product with WiFi and Bluetooth (cx3576.full, s905x5m.sd-full, s905x5m.emmc-full), a phone can give the device the WiFi network to join, and on core 0.0.3 claim it if it is unclaimed, without joining its access point. From core 0.0.4 the phone can also set up the wired port. The device advertises only while a provisioning window is open:
| Window | Opens | Closes | The phone needs |
|---|---|---|---|
| unclaimed | every boot of an unclaimed device | 10 minutes after boot, or when the phone finishes | nothing |
| boot | every boot of a claimed device | 10 minutes after boot, or when the phone finishes | the administrator password |
| offline | a claimed device that lost its default route for 120 s, while bluetooth.provisioning.autoWhenOffline is on (the default) |
the route returns, or when the phone finishes | the administrator password |
| manual | an administrator in the console, for 5, 10 or 30 minutes | its time, the console, or when the phone finishes | the temporary code the console shows |
- The phone side is the web page
https://init.micaos.dev, in Chrome or Edge on Android or a desktop. iOS browsers have no Web Bluetooth, so the page only explains that there. - On core 0.0.3, the release of 2026-10-21, the page sets the administrator password on an unclaimed device; the claim takes effect when the phone finishes, and the first phone to finish wins. Such a device is therefore claimable by anyone within Bluetooth range for 10 minutes after each boot; claim it promptly, or before it leaves your custody.
- From core 0.0.4 Bluetooth claims nothing and sets nothing but the network: the phone sets the WiFi network or the wired port’s addressing; the device stays unclaimed, and the page’s last screen sends you to the console, whose setup asks for the administrator password and the device code, which is on the label and on the device’s own console. The hostname is set there, or later in the console. After a wired-only session the access point stays on with the label’s key, and keeps that key after the claim until you set your own in the console. Until it is claimed, the device opens its unclaimed window again at every boot.
- A password window needs the password’s verifier, which the device builds when the administrator signs in to the console; a device nobody has signed in to since it gained the feature answers that it cannot use the password.
- While a window is open the adapter is powered even if Bluetooth is switched off. Wrong passwords count towards a lockout, during which the device stops advertising.
status: board-dependent — evidence:
mica-core:docs/ble-provisioning.md,mica-core:docs/factory-ap-key.md,mica-build:boards/products.md
What has never been executed on hardware. The protocol, the device side and the page are covered by tests against each other’s reference, and the page is deployed; no run on a physical board is recorded yet.