A dialog-driven, text-mode installer for headless and console NextBSD server deployments. This document specifies the screen-by-screen flow, interaction model, and visual treatment.
The installer runs in a 80×24 (or larger) text console. Navigation is keyboard-only: ↑↓ to move, Space to toggle, Tab to jump between widgets and buttons, Enter to confirm. The palette is deliberately minimal — amber on black — to remain legible on real serial terminals, VGA text mode, and modern emulators alike, while the highlight bar inverts to draw the eye.
First screen after boot. The Upgrade option is greyed out and unselectable unless a probe detects an existing NextBSD install on an attached disk.
┌───────────────────────── NextBSD Installer ──────────────────────────┐ │ │ │ Welcome to NextBSD Server │ │ continuous · 2026-06-08 00:19 UTC · 0d5f191 │ │ │ │ Choose an action. Use ↑↓ to move, Enter to select. │ │ │ │ ▸ Install Fresh install onto a selected disk │ │ Upgrade (no existing NextBSD install detected) │ │ Shell Drop to a live rescue shell │ │ Reboot Restart the machine │ │ │ │ Probe: scanned ada0, ada1 — found no bootable NextBSD root. │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < OK > < Cancel > │ └────────────────────────────────────────────────────────────────────────┘
When the probe does find an install, the row lights up and becomes selectable:
┌───────────────────────── NextBSD Installer ──────────────────────────┐ │ │ │ Welcome to NextBSD Server │ │ continuous · 2026-06-08 00:19 UTC · 0d5f191 │ │ │ │ Choose an action. Use ↑↓ to move, Enter to select. │ │ │ │ Install Fresh install onto a selected disk │ │ ▸ Upgrade Keep data, replace base — ada0 (2026-05-20) │ │ Shell Drop to a live rescue shell │ │ Reboot Restart the machine │ │ │ │ Probe: ada0p2 zroot NextBSD Server 2026-05-20 (upgradable) │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < OK > < Cancel > │ └────────────────────────────────────────────────────────────────────────┘
Upgrade is rendered with the disabled color and skipped by the selection cursor until probe_existing_root() returns a result. The detected version is shown inline so the operator knows exactly what will be upgraded.Whole-disk installs only — no partition editor in the server flow. Each disk is shown with its volume label(s), not just the device id, so operators don't wipe the wrong drive. Existing volumes are broken out underneath with their filesystem type.
┌────────────────────────── Select Install Disk ───────────────────────┐ │ │ │ The selected disk will be ERASED in full. Pick a target: │ │ │ │ ▸ ada0 238 GB Samsung SSD 860 EVO │ │ ├─ "BACKUP" 212 GB ufs │ │ └─ "EFI" 260 MB fat32 (ESP) │ │ │ │ ada1 931 GB WDC WD10EZEX-08WN4A0 │ │ ├─ "vault" 900 GB zfs (zpool: tank) │ │ └─ "swap" 16 GB freebsd-swap │ │ │ │ da0 15 GB SanDisk Ultra USB (install media) │ │ └─ "NEXTBSD_INST" 15 GB iso9660 │ │ │ │ Space toggles details · Enter selects · da0 is locked (booted from) │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < Select > < Back > < Rescan > │ └────────────────────────────────────────────────────────────────────────┘
| Column | Source | Purpose |
|---|---|---|
ada0 / da0 | geom disk list | Kernel device id — the unambiguous handle. |
| Size | diskinfo | Human-readable capacity for quick sanity check. |
| Model | GEOM ident / CAM | Physical drive identification ("which one is this?"). |
| "Label" | glabel status · GPT label · FS volname | The headline feature — operators recognize volumes by name, not by p2. |
| FS type | fstyp / GPT type | ufs · zfs · fat32 (ESP) · freebsd-swap · iso9660 — shows what's at risk. |
< ERASE ada0? > yes/no modal that echoes the labels about to be destroyed (e.g. "BACKUP", "EFI").da0) is shown for context but cannot be selected.One screen creates the primary admin account and sets the hostname. The hostname is auto-suggested from the username plus the detected machine model — and stays editable.
┌──────────────────────── Create Admin Account ────────────────────────┐ │ │ │ This user is added to the wheel group and may use sudo. │ │ │ │ Username [ joe________________ ] │ │ Password [ •••••••••__________ ] │ │ Confirm [ •••••••••__________ ] ✓ match │ │ │ │ Hostname [ joe-thinkpad-t460_ ] │ │ suggested from username + DMI model — editable │ │ │ │ DMI: LENOVO ThinkPad T460 (20FN) → slug: thinkpad-t460 │ │ │ │ Tab moves between fields · Enter on Next to continue. │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < Next > < Back > │ └────────────────────────────────────────────────────────────────────────┘
Validation states surface inline — mismatched confirmation blocks Next:
│ Password [ •••••••••__________ ] │ │ Confirm [ ••••••____________ ] ✗ does not match │ │ │ │ Passwords must match before you can continue. │
| Input | Derivation | Result |
|---|---|---|
username = joe | slugify(username) | joe |
DMI product = ThinkPad T460 | slugify(model), strip vendor noise | thinkpad-t460 |
| joined | <user>-<model-slug> | joe-thinkpad-t460 |
| no DMI / VM | fallback | joe-nextbsd |
-, non-[a-z0-9-] dropped, collapsed dashes, RFC-1123 length cap.wheel + doas/sudo.A live progress dialog streams each stage. The base system is cloned with cpdup from the running live media to the destination volume — no archive extraction. The gauge fills in amber; the current action and a scrolling log tail keep the operator informed during the copy.
┌────────────────────────── Installing NextBSD ────────────────────────┐ │ │ │ Cloning filesystem to destination volume… │ │ │ │ 64% │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < Cancel > │ └────────────────────────────────────────────────────────────────────────┘
cpdup clone — the dialog stays clean, just the current action title and a percentage.On success, a summary plus the two terminal actions: Reboot or Shutdown. A reminder to remove the install medium is shown.
┌──────────────────────── Installation Complete ───────────────────────┐ │ │ │ ✓ NextBSD Server installed successfully. │ │ │ │ Build continuous · 2026-06-08 00:19 UTC · 0d5f191 │ │ Disk ada0 │ │ Hostname joe-thinkpad-t460 │ │ Admin user joe (wheel, sudo) │ │ │ │ Remove the install medium (da0) before rebooting. │ │ │ │ What next? │ │ │ ├────────────────────────────────────────────────────────────────────────┤ │ < Reboot > < Shut Down > < Shell > │ └────────────────────────────────────────────────────────────────────────┘
Reboot. Shell stays as a final escape hatch for post-install tweaks before first boot.< View Log > / < Retry > / < Shell >.Notes for whoever implements this against bsddialog(1) / libdialog or a custom ncurses front-end.
| Token | Role | Treatment |
|---|---|---|
| Background | everything | Pure black #000 |
| Body text / frames | labels, box-draw | Amber #ff9416, dim frames #a85e0e |
| Title / emphasis | headings, field values | Bright amber #ffb454 + glow |
| Selection bar | current row / default button | Inverted — black text on solid amber |
| Disabled | gated options (Upgrade) | Muted brown #4a3517, skipped by cursor |
| Success / failure | ✓ match, ✗ mismatch | Green #39d353 / red #ff4f4f — the only non-amber accents |