Skip to content

Install

github-actions[bot] edited this page Oct 6, 2026 · 7 revisions

Install

Get the installer

Download the ISO and its .sha256 from the latest release, or build it:

nix build .#nixosConfigurations.iso.config.system.build.isoImage

Write it to a USB stick and boot the target machine.

Before you boot

  • Turn Secure Boot off. Nothing is signed. With Secure Boot on, the firmware refuses the stick (OVMF shows "Access Denied"; other firmware may skip it silently).
  • UEFI or BIOS, both work. On the installer ISO, a terminal menu lets you choose BIOS, UEFI, or autodetect (the firmware that booted the ISO). UEFI gets systemd-boot; legacy BIOS gets GRUB plus a 1 MiB BIOS boot partition on the first disk. With no answer within 30 seconds the menu takes autodetect, so an unattended boot still installs. losos-install --bios and --uefi select a mode without showing the menu. UEFI, from the menu or --uefi, needs the stick itself booted in UEFI mode, because systemd-boot writes the firmware's boot entry; from a BIOS-booted stick the installer refuses it before touching any disk. BIOS is mainly for testing in a VM. This menu is only part of the installer ISO; it is not shown on the installed appliance.
  • Connect the network. The installer clones the flake at run time.

What the installer does

After the firmware choice, the installer runs unattended. It finds every fixed disk, puts them in one LVM volume group, encrypts it with LUKS, formats /persist as ext4, and installs.

  • On a machine with a TPM 2.0 chip (most mini-PCs have one in the firmware, Intel PTT or AMD fTPM, usually switched on), the installer seals the disk key to the chip right after formatting (systemd-cryptenroll), so the box boots unattended from the first boot and nothing secret is on the boot partition. The disk alone, pulled or cloned, is unreadable. The key is not bound to firmware measurements (PCRs), because the box updates its firmware and bootloader unattended and has no shell to recover from a lockout; so a thief who takes the whole box with its chip is still able to get at the data. The same random key the volume was formatted with stays inside the encrypted volume at /etc/keys/persist-keyfile as a recovery slot.
  • Without a chip, or with losos-ctl install --no-tpm from the installer's shell, that keyfile is baked into the initrd instead. It then sits on the unencrypted ESP, and anyone who takes the disk can read the data. The installer prints which of the two it chose; --tpm makes a missing chip an error rather than a silent keyfile install.
  • In a VM, give it a TPM (swtpm, see below) or it installs in keyfile mode.

/persist is ext4 with the encrypt feature because fscrypt needs it and btrfs does not support it. You lose compression and data checksums.

After the reboot, tty1 shows a full-screen banner with the box's IP address and <hostname>.local. Open the IP address in a browser on any computer on the same network. The .local name works too wherever the computer resolves mDNS names (Windows, macOS, phones and most Linux desktops do; the host of a libvirt or VirtualBox NAT guest usually does not, so use the address there). Both reach the same pages. The banner updates when the address changes.

The first page is the setup wizard. Its first step is trusting the box's own certificate, so that the rest of the setup, and every later sign-in, travels over HTTPS and your browser can offer a passkey. The step shows one line to paste into a terminal, picked for the computer you are on: on macOS and Linux curl -fsSL http://<address>/setup/trust.sh | sh, on Windows irm http://<address>/setup/trust.ps1 | iex. The script is served by the box itself as plain text (open the link in a tab to read it first), adds the one certificate to the stores your browsers read for your user only (the login keychain on macOS, the user's Trusted Root store on Windows, the NSS stores Chrome and Firefox use on Linux), installs nothing else, never asks for administrator rights, and prints the certificate's SHA-256 fingerprint so you can compare it with the one on the page. Phones get the plain download instead. The manual route stays below it: download losos-ca.crt and add it as a trusted authority yourself.

If reading a screen and typing an address is the scary part, open losos-edge.dasmat.us/find in Chrome instead and press Find my box. Chrome asks once whether the page may look for devices on your local network (its Local Network Access permission, Chrome 142 or newer); say yes, and the page finds the box by its name and links you to its setup. The lookup runs inside your browser, between your computer and the box: the page reads the box's /setup/state.json (its name and certificate fingerprint, nothing more), and nothing about your network leaves your machine. The box only lets that one page read the document (losos.setup.finderOrigins). Firefox and Safari have no such permission and get the typed-address instructions instead.

Try it in a VM (BIOS)

For the TPM path, the VM needs an emulated chip at install time and at every boot, with the same state directory, or the installed system will not find the key it sealed. With swtpm:

mkdir -p tpm
swtpm socket --tpmstate dir=tpm --ctrl type=unixio,path=tpm/sock --tpm2 --daemon
qemu-system-x86_64 ... \
  -chardev socket,id=chrtpm,path=tpm/sock -tpmdev emulator,id=tpm0,chardev=chrtpm \
  -device tpm-tis,tpmdev=tpm0

Add those three lines to both the installer run and the later boots. Without them the installer says unlock: keyfile in the initrd and the box works, in keyfile mode.

qemu-img create -f raw disk.img 40G
qemu-system-x86_64 -m 4096 -smp 2 -enable-kvm -machine q35 \
  -drive file=losos.iso,media=cdrom,readonly=on \
  -drive file=disk.img,format=raw,if=virtio \
  -nic user,hostfwd=tcp::8080-:80

Without -bios QEMU boots SeaBIOS, so the installer picks GRUB. Once it finishes, shut the VM down and boot again without the -drive …media=cdrom line. The VM's address is only reachable from the host through the forward: open http://localhost:8080.

ISO with the full closure

nix build .#losos-disk-iso          # or: devenv shell build-media iso

The normal ISO makes the target download and build the whole system (about 5.8 GiB). This ISO carries the built closure, so nixos-install copies it from the stick.

  • It still needs a network to clone the flake and fetch nixpkgs.
  • Build it from the same commit the installer will clone (LOSOS_FLAKE_URL, --depth 1). Otherwise the store paths differ and the copies are not used.
  • It is too large for a GitHub release asset. Build it yourself.

Demo image for a VM

nix build .#losos-disk-qcow2        # or: devenv shell build-media qcow2

A preinstalled QCOW2 for QEMU or virt-manager. Tagged releases publish it to GHCR. It has no disk encryption and never runs the installer, so use it for demos and development only.

Growing the disk

The logical volume uses 90% of the volume group (losos.storage.fillPercent). To use the rest:

losos-ctl grow

This runs lvextend, cryptsetup resize and resize2fs, in that order, with /persist mounted. /persist holds /nix, so it fills up over time.

When the reserve is used up, add a disk and grow again:

pvcreate /dev/sdX && vgextend persist-vg /dev/sdX && losos-ctl grow

grow fails if there is nothing left to claim.

Clone this wiki locally