Install in depth
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. The stick's volume
label is LOSOS_INSTALLER. The BIOS boot menu, the UEFI splash and the
console banner say LosOS and the release tag, and the host name is
losos-installer. Underneath it is NixOS, and os-release says so with
ID_LIKE=nixos. The installed box carries the same name and tag in its
boot menu, its console banners and os-release (NAME=LosOS,
IMAGE_VERSION), and keeps ID=nixos.
Before you boot
- Secure Boot: off, or enrol the LosOS certificate. Release ISOs are
signed. The stick's UEFI loader is one unified kernel image (kernel,
initrd, command line) signed with the LosOS db certificate, and that
loader checks the system image's hash before mounting it. A firmware that
trusts only Microsoft's keys refuses the stick until the certificate from
the stick's
EFI/losos/or the release page is added to itsdb, next to Microsoft's certificates, never in place of them: Windows, other distributions' shim and graphics-card option ROMs need those. OVMF shows "Access Denied"; other firmware may skip the stick without a word. The installed box's loader is not signed, so the box itself needs Secure Boot off. The handbook's Secure Boot and signed media page has the steps and theSHA256SUMS.sigcheck.tests/secure-boot.nixis the proof. - 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 --biosand--uefiselect 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. The menu is part of the installer ISO only. The installed appliance never shows it. - 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, the installer seals the disk key to the
chip right after formatting (
systemd-cryptenroll). Most mini-PCs have one in the firmware, Intel PTT or AMD fTPM, usually switched on. The box then 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. The price is that a thief who takes the whole box with its chip can still get at the data. The same random key the volume was formatted with stays inside the encrypted volume at/etc/keys/persist-keyfileas a recovery slot. - Without a chip, or with
losos-ctl install --no-tpmfrom 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.--tpmmakes a missing chip an error rather than a silent keyfile install. TPM and the disk key explains what the chip is for and what a box without one gives up. - 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
it is curl -fsSL http://<address>/setup/trust.sh | sh, on Windows
irm http://<address>/setup/trust.ps1 | iex. The box itself serves the
script as plain text, so open the link in a tab to read it first. The script
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. It 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, which
holds its name and certificate fingerprint and nothing more, and nothing
about your network leaves your machine. The box lets only 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 reachable from the host only through the forward,
so 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 go unused. - 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.