--- 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 `/`, 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 -- ` 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 repo’s 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 ``` 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.