A simpler approach to deploying pre-defined machines or profiles at install time using only a bootable NixOS image and network connectivity.
Due to the number of different machines I maintain and how often I change their intended purpose I find it essential to be able to take a new system from baremetal to a pre-defined, purposefully built system serving in it's intended function as effortlessly as possible in a repoducible way. NixOS's functional Nix expression language and flakes provide a fantastic platform on which to build this functionality.
Any tooling or documentation here comes with absolutely no guarantees or support of any kind. It is to be used at your own risk. Any damages, issues, losses or problems caused by the use of any tooling or documentation here is strictly the responsiblity of the end user and not the developer/creator of this project. This project is highly opinionated and primarily for personal use but your welcome to fork it and build on my work.
- Getting Started
- Update and Upgrade
- Advanced use cases
- Development
- Homelab research
- Backlog
- Completed
clu is a bash script providing:
- An install wizard to walk you through simple system customization
- Automation for annoying tasks like
- disk paritioning and mounting
- generation of nixos hardware configuration
- transferring install time customizations to the underlying nix flake
- triggering the install of the complete system via nix flakes
- Wrapping of many of the disparate NixOS tooling
- Provides a single script with documentation on common tasks
My configuration can be installed using the pre-built upstream NixOS ISOs
- Download the minimal image from NixOS downloads
$ wget https://channels.nixos.org/nixos-23.11/latest-nixos-minimal-x86_64-linux.iso
- Burn the ISO to USB
- Determine the correct USB device
$ lsblk
- Optionally wipe your USB first e.g.
/dev/sdd
$ sudo wipefs --all --force YOUR/DEVICE
- Copy to the dev leaving off the partition
$ sudo dd bs=4M if=latest-nixos-minimal-x86_64-linux.iso of=YOUR/DEVICE status=progress conv=fsync oflag=direct
- Determine the correct USB device
- Boot from the new USB and start a nix shell
$ nix-shell -p git jq
- Clone this repo
$ git clone https://github.com/phR0ze/nixos-config
- Execute the installer
$ cd nixos-config $ chmod +x clu $ sudo ./clu install
By following the Build the live ISO for installation section of this doc you can build a custom ISO which will pre-populate the nix store of the target system during install with prebuilt binaries (i.e. you can think of it as a local binary cache) which will speed up the installation tremendously as you don't need to download nearly as much and any custom built binaries will already be built.
Of course this is really only useful if you install a lot of systems or your target system is rather limited in resources while your build system is beefy.
- Build the live ISO for installation
- Burn the ISO to USB see step 2 of Install from upstream ISO
- Boot from the new USB and open a shell
- You'll be greeted with the clu installer
I'm defining update
as configuration changes while an upgrade
would be changing the versions of
specific apps or the full system including all apps. I'm also using a two unstable commit strategy to
make a two versions of the unstable branch available to my system at a time which I name nixpkgs
and nixpkgs-unstable
which is a bit of a misnomer as they are both based on the unstable branch but
the different points in time. The one I call nixpkgs-unstable
is just newer.
- Switch to the configuration folder
$ cd /etc/nixos
- Make changes as desired
- e.g. perhaps you want to Upgrade an app
- Commit or stage your configuration changes so they are visible to nix flakes
$ git add .
- Update your system with the configuration changes
$ sudo ./clu update system
Note the base.nix
is all ready setup to use the latest unstable so all you really need to do is
update to pick it up as follows.
- Update the lock file to use latest
nixos-unstable
$ ./clu update flake
- Update target app overrides to use latest unstable updates
$ ./clu update system
Note the base.nix
is set to a specific unstable version. You'll need to change it to the next
version you'd like.
- Modifying
base.nix
to use your preferred nixpkgs sha e.g.nixpkgs.url = "github:nixos/nixpkgs/3566ab7246670a43abd2ffa913cc62dad9cdf7d5";
- Update the lock file to use this new sha version and get the latest for
nixos-unstable
$ ./clu update flake
- Build the target configuration to validate things are still working
$ ./clu build $HOSTNAME
- Update to changes
$ ./clu update system
-
Modify
base.nix
to ensure that theoverlays
section has an entry for your app e.g.vscode
:vscode = pkgs-unstable.vscode;`
-
Update to pickup your application changes
$ ./clu update system
Most linux users, especially those coming from Arch Linux, will immediately be interested in how they can extend and make this their own. Following best practices across the NixOS community I'm breaking down my configuration into modules. This allows for composability for higher level concepts like machines and profiles. I'm organizing my modules to follow the nix options for the most part.
- Define the VM to be built
- Create a new
machines/vm-NAME
directory - Create the essential files
configuration.nix
args.enc.json
args.nix
- Create a new
- Update and test your VM locally by building it
- From the root of the project run:
./clu build vm $NAME
- And then to run it:
./clu run vm $NAME
- From the root of the project run:
- Deploy the VM to the hosts vms directory
$ ./clu deploy vm prod1
Build the test VM based on the default system configuration and default flake_opts.nix
. If your
running the same system already this will only take a min and create the result
link with an
executable ./result/bin/run-nixos-vm
that will start the VM.
- Build the VM
$ ./clu build vm
- Run the VM
$ ./clu run vm
NixOS has a lot of reusable automation built into it. In the Arch world typically you have to start from scratch and build your own automation if you want control over how its being built. In the Nix world though this already exists.
- Clone this repo
$ git clone https://github.com/phR0ze/nixos-config
- Modify the ISO profile as desired
$ vim profiles/iso/default.nix
- Commit or at the least stage your changes so Nix will see them
$ git add .
- Now build the iso
$ ./clu build iso
- The ISO will end up in
result/iso/
- Clone this repo
$ git clone https://github.com/phR0ze/nixos-config
- Configure git hooks
$ ./clu init
It's nice to have a copy of nixpkgs to reference for options
$ git clone -b nixos-unstable --depth 1 https://github.com/NixOS/nixpkgs
Homelabs are an essential part of any tech enthusiast's set up. At its simplest, just a LAN with access to the internet and a single self-hosted service, Homelabs can also scale to be rather complicated with VLANs for specific needs and purpose built routers, dozens of IoT devices, numerous self hosted services and VPNs to multi-site and cloud based devices. Regardless of the configuration I would assert that the fundamental goals should be the same i.e. make the system, despite or perhaps because of its complexity, pre-defined, purposefully built and effortlessly reproducible.
Thus I'm working on supporting containers, declared in nix, as my next phase in building out my homelab.
References
-
Uptime Kuma
- Build and run vms
- Change image mime associatation
- Turn off firefox's prompting to save passwords
- gtk file picker doesn't sort directories first
- Add vim-colorize plugin
- Change nix flake symbol to blue in vim colorizer plugin
- Change the kernel boot colors
Reference nixos-config
- Norber Melzer's nixos-config
- Hung Le's nixos-config
- https://github.com/danth/stylix
- https://github.com/benetis/dotfiles-1/blob/master/nixos-config/machines/desktop/modules/android.nix
- https://github.com/benetis/dotfiles-1/blob/master/nixos-config/machines/desktop/modules/hardened-chromium.nix
- https://github.com/thexyno/nixos-config/blob/main/nixos-modules/hardware/laptop.nix
- https://github.com/jakehamilton/config/blob/main/modules/nixos/desktop/addons/gtk/default.nix
- https://github.com/librephoenix/nixos-config