colibri/docs/guide/install/first-boot.md
Sam & Claude 95c487546d
Some checks failed
CI / rust (pull_request) Has been cancelled
CI / markdown (pull_request) Has been cancelled
CI / port (pull_request) Has been cancelled
CI / agent-jail-pkgs (pull_request) Has been cancelled
docs(guide): port 39 procedural docs from clawdie-ai to colibri
New docs/guide/ tree — canonical home for operator-facing procedural docs.
Starlight frontmatter added to all files. 0.12 alignment fixes applied:

- v0.11.0 → v0.12.0 throughout
- PI_TUI_PROVIDER/MODEL → DEEPSEEK_API_KEY
- Headless Codex login → Agent runtime setup (zot + RPC mode)
- /login and auth.json references removed
- pi → zot in provider-fallback spawn reference
- colibri-provider-verify (was pi-provider-smoke)
- Language cleanup: smoke test → verification, fake → test,
  can't self-fix → requires operator intervention,
  broken → unresponsive, Fix anything broken → Verify all checks pass

Two-tree model: docs/wiki/ (decisions) + docs/guide/ (procedural).
Single source of truth in colibri. clawdie-ai docs/public/ to be retired.
2026-06-26 09:16:43 +02:00

416 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 'First Boot'
description: Edit one file, flash a USB, boot — get to a working assistant with minimal interaction.
---
> **Current ISO validation note:** the live ISO path is moving to a QML
> installer followed by post-install `/setup` in the Clawdie controlplane.
> Provider keys and Telegram are no longer install-time requirements. The
> `setup.txt` flow below documents the older non-interactive contract and will
> be rewritten after the current ISO live-install validation completes.
The first-boot model below is intentionally small. You edit a single
first-boot setup file (`setup.txt`), flash the USB, boot the
machine, and the
installer reads your file on first start. No interactive
out-of-the-box wizard, no autogenerated secrets you have to write
down later.
The first-boot setup file is versioned. If you do not set these
yourself, the installer fills safe defaults:
```text
SETUP_SCHEMA_VERSION=1
ISO_RELEASE=v0.10.0
ISO_GIT_COMMIT=
```
- `SETUP_SCHEMA_VERSION` tracks the file format the installer understands
- `ISO_RELEASE` records which Clawdie release the install media came from
- `ISO_GIT_COMMIT` is optional exact build provenance
## What you need
- The Clawdie ISO ([tags](https://codeberg.org/Clawdie/Clawdie-ISO/tags))
- A USB stick (16 GB+)
- A flashing tool (`dd`, Etcher, Rufus — your call)
- An [OpenRouter](https://openrouter.ai/keys) account (the
recommended bootstrap path; you can switch to direct provider
keys later)
- A Telegram account and a bot token from
[@BotFather](https://t.me/BotFather)
- Your Telegram numeric user ID from
[@userinfobot](https://t.me/userinfobot)
## Optional: inspect first
If you do not know your disk names, pool layout, PF-facing interface
names, or whether the machine already contains a Clawdie install, run
inspect first from the live environment:
```bash
./scripts/inspect-system.sh --output /path/to/writable/media
```
On a full Clawdie repo checkout, `npm run inspect -- --output ...` is
just a convenience wrapper around the same shell script.
To write the suggested install/storage values straight back into your
first-boot setup file:
```bash
./scripts/inspect-system.sh \
--output /path/to/writable/media \
--apply-setup /path/to/writable/media/setup.txt
```
That only fills blank or missing fields. It does not overwrite values
you already chose explicitly.
To populate the hardware contract file directly:
```bash
./scripts/inspect-system.sh \
--output /path/to/writable/media \
--apply-system-env /path/to/writable/media/system.env
```
That fills blank or missing hardware fields in `system.env` such as:
- `SYSTEM_SCHEMA_VERSION`
- `NETWORK_EXTERNAL_IF`
- `NETWORK_INTERNAL_IF`
- `TAILSCALE_IF`
- `ZFS_POOL`
- `ZFS_LAYOUT`
- `ZFS_DATA_DISKS`
- `ZFS_HOT_SPARES`
- `ZFS_DISKS`
- `ZFS_SPARE_DISKS`
- `ZFS_PREFIX`
- `GPU_DEVICE`
- `SND_DEVICE`
That writes:
- `system.txt` — a human summary
- `system.env` — hardware contract values the installer can use directly
- `inspect-facts.env` — richer machine-readable inspect metadata
- `suggested-setup.txt` — lines you can copy back into `setup.txt`
- raw artifacts such as `dmesg.txt`, `ifconfig.txt`, `zpool-status.txt`,
`zfs-list.txt`, and `pf-interfaces.txt`
The summary includes:
- detected disk device names
- observed ZFS pools, layouts, and datasets
- suggested `INSTALL_MODE`
- suggested `ZFS_LAYOUT`, `ZFS_DATA_DISKS`, and `ZFS_HOT_SPARES`
- detected interface names you can later reuse for PF/network setup
## The four lines
Open the first-boot setup file (`setup.txt`) in a text editor. The
required cognitive surface is **four lines**:
```text
OPENROUTER_API_KEY=sk-or-v1-...
TELEGRAM_BOT_TOKEN=123456:AA...
TELEGRAM_ADMIN_ID=12345678
ASSISTANT_NAME=Atlas
```
That is the minimum for a working install. Everything else in the
first-boot setup file is either prefilled with a sensible default or
optional. Leave any line you don't care about blank — the installer
will fall back.
### What each line does
| Line | What it controls |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OPENROUTER_API_KEY` | The LLM provider used for chat and compaction. |
| `TELEGRAM_BOT_TOKEN` | The bot identity your assistant runs as. |
| `TELEGRAM_ADMIN_ID` | The one Telegram account that can talk to it as operator. |
| `ASSISTANT_NAME` | What your assistant calls itself in chat. It is display-only and does not rename shared DBs, datasets, or the service account. Blank → `Clawdie`. |
## Optional fields worth knowing about
You don't have to fill these in. They exist because you might want
them later or because some installs need them on day one.
### Install mode
```text
INSTALL_MODE=auto
```
- `auto` — detect an existing install and choose fresh vs upgrade
- `fresh` — fail if an existing install is detected
- `upgrade` — require an existing install and upgrade it in place
- `rescue` — require an existing install and attempt recovery/repair
`auto` is the default and the right starting point for most
operators. It also supports reinstall, upgrade, and rescue flows when paired
with `system.env` and existing ZFS metadata.
If you ran inspect first, `system.txt` will suggest the install mode
it thinks fits the machine right now.
### Profile
```text
PROFILE=balanced
```
`economy`, `balanced`, or `quality`. Maps to a coordinated bundle
of chat + fallback + compaction models. `balanced` is the prefilled
default. Switch only if you have a reason.
### Time zone and hostname
```text
TIMEZONE=Europe/Ljubljana
HOSTNAME=
```
`TIMEZONE` defaults to `UTC`. `HOSTNAME` defaults to `clawdie` unless you set it explicitly. It does not derive from `ASSISTANT_NAME`.
### Storage layout
```text
ZFS_POOL=zroot
ZFS_LAYOUT=single
ZFS_DATA_DISKS=1
ZFS_HOT_SPARES=0
ZFS_PREFIX=clawdie-runtime
```
These fields declare the intended storage shape.
- `ZFS_POOL` — pool name, usually `zroot`
- `ZFS_LAYOUT``single`, `mirror`, `raidz1`, or `raidz2`
- `ZFS_DATA_DISKS` — number of disks in the main data layout
- `ZFS_HOT_SPARES` — standby disks reserved as hot spares
- `ZFS_PREFIX` — dataset root for the install
Defaults:
- `single` is the default because it matches the simplest one-disk install
- `single` is **not** the recommended long-running layout
- `raidz1` is the recommended durable multi-disk shape once the
operator opts in
Examples:
```text
# Simple one-disk install
ZFS_LAYOUT=single
ZFS_DATA_DISKS=1
ZFS_HOT_SPARES=0
# Three-disk raidz1
ZFS_LAYOUT=raidz1
ZFS_DATA_DISKS=3
ZFS_HOT_SPARES=0
# Four disks total: 3 in raidz1, 1 hot spare
ZFS_LAYOUT=raidz1
ZFS_DATA_DISKS=3
ZFS_HOT_SPARES=1
```
The installer derives full dataset paths from these values. You do
not type raw dataset paths into the first-boot setup file.
These storage declarations are also part of the long-term upgrade
contract. The installer can later compare:
- `setup.txt` operator intent
- `system.env` hardware intent
- persisted ZFS dataset metadata
For advanced operators, that metadata lives as ZFS user properties on
the root dataset `<ZFS_POOL>/<ZFS_PREFIX>`, using keys such as:
- `org.clawdie:install-uuid`
- `org.clawdie:setup-schema`
- `org.clawdie:system-schema`
- `org.clawdie:iso-release`
- `org.clawdie:iso-commit`
- `org.clawdie:assistant-name`
- `org.clawdie:hostname`
- `org.clawdie:telegram-admin-hash`
- `org.clawdie:zfs-layout`
- `org.clawdie:zfs-data-disks`
- `org.clawdie:zfs-hot-spares`
This is deliberate: the upgrade fingerprint lives with the data,
survives reflash, and can be inspected with native `zfs get`.
If you ran inspect first, it will already have written suggested
storage lines based on:
- detected disk count
- observed ZFS pool topology
- existing pool/dataset state when present
### Dashboard credentials
```text
OPERATOR_EMAIL=you@example.com
OPERATOR_PASSWORD=...
```
Optional. If you set both, the dashboard is preconfigured. If you
leave them blank, the dashboard waits until you run
`npm run set-operator -- <email>` from the running system. Telegram
is your operator interface in the meantime.
> **Plaintext warning:** `OPERATOR_PASSWORD` lives in plaintext on
> the install media until you reformat it. The installer will warn
> you about this in the post-install summary. Reformat the USB
> before storing it or handing it to anyone else.
### Headless / unattended access
For installs you don't sit at the console for:
```text
SSH_AUTHORIZED_KEY=ssh-ed25519 AAAAC3... you@laptop
CLAWDIE_USER_PASSWORD=
```
`SSH_AUTHORIZED_KEY` is the recommended way. Public keys are not
secrets, so plaintext on the USB is fine. When set, the installer
enables key-only SSH for the service user and disables password
SSH.
`CLAWDIE_USER_PASSWORD` is a fallback for console login or sudo,
used only if no SSH key is provided. Same plaintext warning as
above. **There is no `ROOT_PASSWORD` field** — root login is
locked by design. Use `sudo` from the service user.
## Where The First-Boot Setup Lives
The flashed USB exposes a writable FAT32 config surface. Edit these files there:
- `setup.txt`
- `system.env`
The installer reads those files on first boot.
Why this path works:
- it is writable from Windows, macOS, Linux, and FreeBSD
- it supports long API keys without console typing
- it works with the inspect loop naturally
- it matches the ISO repos existing “editable config on removable media”
direction without requiring a second USB
Operator flow:
1. Flash the USB.
2. Reinsert it on your normal computer.
3. Open the writable config surface.
4. Edit `setup.txt`.
5. Optionally leave `system.env` blank and let inspect populate it.
6. Boot the target machine from that USB.
The installer treats:
- `setup.txt` as operator intent
- `system.env` as hardware intent
Both files are versioned and can be compared against persisted ZFS
metadata during later upgrade and rescue flows.
## Boot
1. Plug the USB into the target machine.
2. Power on. Boot from USB (BIOS/UEFI key varies by hardware).
3. The installer reads the first-boot setup and proceeds without prompting.
Expect first boot to take several minutes — the installer
provisions databases, jails, and copies skills. The post-install
summary tells you what's ready and surfaces any warnings (plaintext
passwords, unset optional fields).
## After first boot
### Talk to your assistant
Open Telegram, find the bot you registered, send `/start`. If your
`TELEGRAM_ADMIN_ID` matches, you're talking to your operator
channel.
### Set dashboard credentials (if you skipped them)
If you left `OPERATOR_EMAIL` / `OPERATOR_PASSWORD` blank in the
first-boot setup:
```bash
npm run set-operator -- you@example.com
```
You'll be prompted for a password (twice, no echo). The dashboard
becomes available afterwards. This is first-set only — to rotate a
password later, use the dashboard's change-password flow.
### Switch off OpenRouter
OpenRouter is the bootstrap path, not a permanent commitment. To
move chat to a direct provider:
- **Per chat:** `/model` in Telegram lets you swap provider/model
for a single chat.
- **System-wide:** set `DEEPSEEK_API_KEY` in `provider.env`.
The agent uses DeepSeek by default.
[Provider Fallback](../operate/provider-fallback/).
### Reformat the install media
If your first-boot setup contained any password fields
(`OPERATOR_PASSWORD`, `CLAWDIE_USER_PASSWORD`), the installer did
**not** delete the file (by design — operators have lost installs
to overzealous auto-wipes). Reformat the USB once you've confirmed
the install is healthy.
## Troubleshooting
Check the first-boot log and progress files first:
```bash
tail -100 /var/log/${AGENT_NAME}-firstboot.log
cat /var/log/${AGENT_NAME}-firstboot.progress
```
If the install stopped after a named setup step, resume from that step:
```bash
cd /home/${AGENT_NAME}/clawdie-ai
just install-from <step>
```
For a full post-install verification pass, use the
[Fresh install checklist](./fresh-install-checklist/).
## Reflashing later
Use `INSTALL_MODE` to choose how the installer treats an existing system:
- `auto` — detect the existing install and choose the safest path
- `fresh` — fail if an existing install is detected
- `upgrade` — require an existing install and upgrade it in place
- `rescue` — require an existing install and attempt recovery/repair
Keep backups before upgrade or rescue work, especially when changing storage
layout values.
## Related
- [ISO Install](./iso/) — image selection, USB writing, rebuild path.
- [Operator Commands](../operate/operator-commands/) — what's
available in Telegram once your assistant is up.
- [Provider Fallback](../operate/provider-fallback/) — how the
agent stays alive when a provider hits a usage cap.