Get Started
From a fresh clone to a running system. Every command and option on this page is checked against the repository — if it is written here, it exists.
Prerequisites
- Nix with flakes enabled. Add
experimental-features = nix-command flakesto/etc/nix/nix.conf, or use the Determinate Systems installer, which enables them by default. - git
- Building a NixOS host requires NixOS. On macOS or another Linux you can still use the dev shell, the VM, and nix-darwin — see NON-NIXOS-USAGE.
This template tracks NixOS 26.05 (stable), so nearly everything comes from the binary cache rather than being compiled locally.
-
Clone and enter the dev shell
git clone https://github.com/olafkfreund/nixos-template.git cd nixos-template nix developThe shell provides
just,nixfmt,nixd(Nix LSP),statix,deadnix,treefmt,shellcheck,shfmt,pre-commit,nh, pluspciutils/lshwfor hardware detection.Running
justwith no arguments opens an interactive menu over every recipe. -
Pick a starting point
Template Use case hosts/desktop-templateWorkstation, full Home Manager profiles hosts/laptop-templateDesktop plus power management and TLP hosts/server-templateHeadless, SSH-hardened, server profile hosts/wsl2-templateNixOS inside Windows Subsystem for Linux 2 hosts/darwin-desktopmacOS workstation via nix-darwin hosts/darwin-laptopmacOS laptop via nix-darwin hosts/darwin-servermacOS server via nix-darwin cp -r hosts/desktop-template hosts/my-machine -
Generate your hardware configuration
Run this on the machine you are configuring — it describes that machine’s disks, filesystems and kernel modules, so it is never copied between hosts.
sudo nixos-generate-config --show-hardware-config \ > hosts/my-machine/hardware-configuration.nix -
Customise the host
Edit
hosts/my-machine/configuration.nix:networking.hostName = "my-machine"; # GPU support. autoDetect is on by default and enables the right # vendor module for you; set the profile to match your workload. modules.hardware.gpu = { autoDetect = true; profile = "desktop"; # desktop | gaming | ai-compute | server-compute }; environment.systemPackages = with pkgs; [ vim ];To pin a vendor explicitly instead of relying on detection:
modules.hardware.gpu.nvidia = { enable = true; driver = "production"; # stable | beta | production }; # legacy_470 | legacy_390 | openThen edit
hosts/my-machine/home.nixto choose Home Manager profiles:imports = [ ../../home/profiles/base.nix # git, shell, core CLI tools ../../home/profiles/desktop.nix # GUI applications ../../home/profiles/development.nix # languages and dev tooling ];See GPU-CONFIGURATION for the full set of GPU options.
-
Register the host in flake.nix
Open
flake.nixand find theADD YOUR OWN HOSTS HEREblock insidenixosConfigurations. Uncomment an entry and edit it:my-machine = flakeUtils.mkSystem { hostname = "my-machine"; # must match the hosts/ directory name profile = "workstation"; # workstation | server | laptop }; # gaming | development | minimalWhymkSystem? It imports yourconfiguration.nixand wires in Home Manager, agenix and the flake metadata module — so you never repeat that boilerplate. There is one builder; the machine type is a parameter. See HOST-TEMPLATES. -
Check before you switch
nix flake check # evaluates every host and runs the lint gatesThen dry-run your specific host to see exactly what would be built:
nix build .#nixosConfigurations.my-machine.config.system.build.toplevel --dry-run -
Build and activate
just test my-machine # activate now, no bootloader entry — safest first try just switch my-machine # activate and make it the default boot entryjust testis the one to reach for first: if something is wrong, reboot and you are back where you started.
Try it in a VM first
No install, no risk — this boots a complete desktop host in QEMU:
nix build .#nixosConfigurations.desktop-test.config.system.build.vm
./result/bin/run-desktop-test-vm
# login: vm-user / nixos
Any host can be built this way; swap desktop-test for test-server,
test-gaming, or your own host name.
Everyday commands
Run just on its own for the interactive menu, or call recipes directly:
| Command | What it does |
|---|---|
just switch [host] |
Build and activate, and set as default boot entry |
just test [host] |
Activate without adding a boot entry |
just build [host] |
Build only, do not activate |
just boot [host] |
Stage for next boot without switching now |
just update |
Update all flake inputs |
just update-switch [host] |
Update inputs, then switch |
just check |
nix flake check |
just fmt |
Format Nix, shell, Markdown, YAML and JSON via treefmt |
just lint |
statix check |
just validate |
check → lint → format-check → dead-code |
just test-vm [host] |
Build and boot a host as a QEMU VM |
just list-vms |
Show the VM configurations available |
just build-wsl2-archive |
Build a WSL2 import tarball |
just setup-secrets |
Initialise agenix secret management |
just edit-secret SECRET |
Create or edit an encrypted secret |
just list-secrets |
List age-encrypted secrets |
just rekey-secrets |
Re-encrypt after adding a new age key |
just list prints all ~100 recipes without the menu UI.
Keeping it green
just validate
This runs nix flake check, statix, the formatting check and deadnix. All
of them pass on a clean clone, and CI enforces the same set — so if validate
is green locally, your pull request will be too.
Where to go next
- Code Showcase — how the pieces fit together
- Usage & the just menu
- Features overview
- Host templates
- Secrets with agenix
- WSL2 configuration