Adding a module to the flake¶
This page gives every host something the inventory has no setting for: a program, a service, a kernel setting. The change is a new module in the fleet-nixos repo, tried on one host, pushed, and then deployed to the rest. Use it when Changing a host's setting sends you here.
Status: written, not yet run.
The steps take one module as their example: turning on tmux, so that a session on a host outlives a dropped connection. See Modules and options for what a module is.
Prerequisites¶
- The control shell, with fleet-nixos, fleet-ansible, and the private repo checked out next to each other under
~/src, and the right to push to fleet-nixos. See The control shell. - The fleet's SSH key in
~/.ssh/config, and the deploy key inSOPS_AGE_KEYorSOPS_AGE_KEY_FILE. Step 4 deploys from the shell. - The private repo's files are generated, committed, and pushed. See After a change.
- A host that can be down for a few minutes if the change goes wrong, to try the module on.
Placeholders¶
| Placeholder | Value |
|---|---|
<host> |
The host the module is tried on, such as pk01 |
<address> |
That host's address, ansible_host in the inventory |
<admin> |
The admin account, abbr_name followed by admin, such as mmadmin |
1. Find the option¶
Search for what you want in the NixOS option search, with the release set to the one in nixpkgs.url in flake.nix. The search for tmux gives programs.tmux.enable, which takes true or false.
If the search has no option and you only need a program installed, add the package's name to the list in modules/packages.nix instead of writing a module, and go to step 3.
2. Write the module¶
From ~/src/fleet-nixos, on an up-to-date main, create modules/tmux.nix:
Open with a comment that says what the module is for, as every module in the folder does. One module covers one concern.
Add the file to the imports list in modules/default.nix, in alphabetical order:
Then tell git about the new file:
The flake is built from the files git tracks. Without this, the build stops and says the file is not tracked.
Background: a module that differs from host to host
The example is on for every host, so it reads nothing from the fleet. A module that depends on a host's values reads them from the fleet options, as modules/ntp.nix reads config.fleet.ntpServers. When a feature switch decides whether it applies, the module wraps its settings in lib.mkIf, as modules/mosh.nix does.
A new value or switch is a larger change, in three places that have to agree: the option in modules/options.nix, the key in lib/fleet.nix, which stops the build when a host's file lacks it, and the nixos role in fleet-ansible, which writes the key into every host's file from the inventory. This page does not cover it.
3. Check that every host still evaluates¶
Format the files, then run the flake's checks against the example fleet inside the repo:
The second command ends without an error. It evaluates each example host and fails on a .nix file that is not formatted.
Run the checks again against your own fleet:
nix flake check --no-build --no-write-lock-file \
--override-input fleet git+file://$HOME/src/fleet-private
Then read the new option's value for the host you will try it on:
nix eval .#nixosConfigurations.<host>.config.programs.tmux.enable \
--override-input fleet git+file://$HOME/src/fleet-private \
--no-write-lock-file
An option name that does not exist, or a value of the wrong type, stops any of these commands with a message naming the option and the file. Nothing has reached a host so far.
4. Try it on one host¶
From ~/src/fleet-nixos, deploy the checkout as it is on disk to one host, with the action test:
The host builds the new system and activates it, and the boot menu keeps the previous system as its default. If the change leaves the host unreachable, restart the VM from Proxmox and it comes back as it was. See Build, activate, switch, and boot.
Log in and check the result:
The first command prints tmux's version, and the second list is empty.
5. Commit and push¶
From ~/src/fleet-nixos:
The run clones fleet-nixos from the pushed main at its start, so a module that is not pushed reaches no host through the run.
6. Deploy to every host¶
Run each host, one per run, starting with the host from step 4. That run makes the tried system the host's boot default.
In Semaphore, run the site Template with Target set to the host's name.
From ~/src/fleet-ansible, in a shell prepared for runs after the handover. See Running from a shell again.
Each run ends with failed=0 and unreachable=0 for its host. Take the hosts in the order Updating the fleet gives, and verify each as in step 4 before the next.
If a host is worse off after its run, go back to its previous generation, then revert the commit in fleet-nixos and push. See Rolling back.
What's next¶
A new VM is installed from the flake and not from the ISO's contents, so the installer ISO does not need building again for a new module.
Not yet confirmed¶
The example module was added to a copy of the flake on a workstation. It evaluated for the example host ex01 with programs.tmux.enable true, the two files passed the formatter, and the build refused the module until git add was run. No host has been deployed with it.
nix flake checkin full with the new module. Only the evaluation of one host and the formatter were run.deploy-host --action testagainst a host, and a restart returning the host to its previous system.- A run with
--tags nixosalone against a built host. - That
nix fmtwith file names formats those files with the Nix version on the control shell. The flake's formatter is nixfmt.