| title | Host files: disko, hardware-config, default.nix |
|---|---|
| time | 15 minutes |
Prerequisite: Anatomy of an instance repo.
Outcome: you know what each file under
hosts/<name>/is for, when to change it, and how to escape the defaults when your target is not a plain Hetzner Cloud VM.
Every host has its own directory, hosts/<name>/, imported from the
inventory (modules = [ ./hosts/<name> ]). add-host scaffolds it
with three files.
hosts/web-1/
|-- default.nix
|-- disko.nix
`-- hardware-configuration.nix
default.nix-- the entry point. Imports the two others and is where your per-host NixOS options go (services, users, opened ports). You edit this file by hand as the host grows.disko.nix-- the disk layout. Consumed by disko to partition and format the target on install. Written by the preset you pick duringadd-host, or by you if you pickcustom.hardware-configuration.nix-- kernel modules and hardware quirks NixOS needs to boot on the specific machine. Generated byinstall-hostvianixos-anywhere --generate-hardware-config nixos-generate-config. The placeholderadd-hostleaves is overwritten on first install. You do not hand-edit this file.
add-host prompts:
Disk layout:
hetzner-vm
> custom (write disko.nix by hand)Options are enumerated from templates/disko/*.nix in the nixops
repo, plus the always-present custom escape hatch.
- Preset (e.g.
hetzner-vm) -- the file attemplates/disko/hetzner-vm.nixis copied verbatim tohosts/<name>/disko.nix. Ready toinstall-host. custom-- nodisko.nixis written. You must create it beforeinstall-host, orinstall-hostrefuses to run.
The current preset list is intentionally small. When the presets
do not fit (bare metal, ZFS, mirror, encryption, non-standard disk
names) pick custom and see Escape hatches
below.
- Checks
hosts/<name>/disko.nixexists. Bails if not. - Calls
nixos-anywhere --flake .#<name> --generate-hardware-config nixos-generate-config hosts/<name>/hardware-configuration.nix. nixos-anywhererunsnixos-generate-configon the target inside the installer, writes the result back to your flake, then builds and deploys the fully-formed configuration.- First install: the placeholder
hardware-configuration.nixis replaced with the real one. Commit the change. --forcereinstall: the file is regenerated from live hardware -- useful when you swap disks or move the host.
Pick custom in add-host, then drop a file. The disko module is
already imported by every host (through nixops.nixosModules.default),
so you only set the disko.devices option.
Minimal example for a single-disk VPS with BIOS boot:
# hosts/web-1/disko.nix
{
disko.devices.disk.main = {
device = "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = { size = "1M"; type = "EF02"; }; # BIOS boot
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
boot.loader.grub = {
enable = true;
efiSupport = false;
device = "/dev/sda";
};
}ZFS mirror on two NVMe drives:
# hosts/db-1/disko.nix
{
disko.devices = {
disk = {
x = { device = "/dev/nvme0n1"; type = "disk"; content = { type = "gpt"; partitions = {
ESP = { size = "1G"; type = "EF00"; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; }; };
zfs = { size = "100%"; content = { type = "zfs"; pool = "tank"; }; };
}; }; };
y = { device = "/dev/nvme1n1"; type = "disk"; content = { type = "gpt"; partitions = {
zfs = { size = "100%"; content = { type = "zfs"; pool = "tank"; }; };
}; }; };
};
zpool.tank = {
type = "zpool";
mode = "mirror";
rootFsOptions = { compression = "zstd"; atime = "off"; xattr = "sa"; };
mountpoint = "/";
};
};
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.supportedFilesystems = [ "zfs" ];
networking.hostId = "12345678"; # required by ZFS
}More layouts (raidz, LUKS, LVM, bcachefs, btrfs subvolumes): nix-community/disko/tree/master/example.
Not sure where to start? Ask Claude to draft one from your target's
lsblk output and iterate.
Presets are just files. If you picked hetzner-vm and later need
to change the ESP size or filesystem, edit
hosts/<name>/disko.nix directly. It is your file now.
If you already ran install-host, disk changes require a wipe --
re-run with install-host <name> --force. Ordinary deploy will
not reformat disks.
Common enough to be reusable? Drop a file into
templates/disko/ in the nixops repo. add-host picks it up
automatically. No code changes needed to enumerate it.
- Disko README + quickstart
- Disko examples
- NixOS Manual -- Configuration options
(search for
boot.loader.*andboot.supportedFilesystems) - NixOS Wiki -- Disko
- nixos-anywhere -- --generate-hardware-config