- Nix 86.1%
- Shell 8.4%
- Python 3%
- JavaScript 2.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| android | ||
| home | ||
| hosts | ||
| modules | ||
| pkgs | ||
| secrets | ||
| .gitignore | ||
| CHEATSHEET.md | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
NixOS machines
Declarative config for my NixOS machines. Multi-host flake: shared config in
modules/, per-machine specifics in hosts/, user environment in home/.
The repo is synced across machines by Syncthing, so every host builds from
~/Code/nixos directly.
Each host's default.nix imports ../../modules plus its own
hardware-configuration.nix, then sets only what's machine-specific. The
flake's mkHost adds nix-flatpak, home-manager, and agenix to
every host. No conditionals — a machine either imports a module or it doesn't.
Day-to-day
The flake attribute is the hostname, so bare nixos-rebuild targets the right
host:
sudo nixos-rebuild switch --flake /home/jonathan/Code/nixos#laptop
sudo nixos-rebuild build --flake /home/jonathan/Code/nixos#laptop # check without activating
nix flake update --flake /home/jonathan/Code/nixos # bump inputs
sudo nixos-rebuild switch --rollback # previous gen
New .nix files are picked up automatically (not a git flake, so no git add
needed).
Secrets (agenix)
The GitHub packages token lives encrypted in secrets/github-token.age,
decrypted at boot to /run/agenix/github-token, and read into
GITHUB_PACKAGES_TOKEN by zsh. Every host that consumes a secret must be a
recipient in secrets/secrets.nix — get a host's pubkey with
cat /etc/ssh/ssh_host_ed25519_key.pub.
cd secrets && nix run github:ryantm/agenix -- -e github-token.age # edit
cd secrets && nix run github:ryantm/agenix -- -r # re-encrypt
modules/secrets.nix guards on pathExists, so the config still evaluates
before the .age exists.
Home / dotfiles
home/jonathan.nix (home-manager): zsh + oh-my-zsh + starship, git, ssh,
editorconfig, Syncthing, GNOME dconf. The system only enables zsh as a login
shell; all shell config is here. Conflicting pre-existing files are moved to
*.hm-bak on first switch. Syncthing's device list is filtered per host so a
machine never lists itself; server is the introducer.
Adding a host
- Install NixOS (UEFI → systemd-boot).
sudo nixos-generate-config --show-hardware-config > hosts/<name>/hardware-configuration.nix- Write
hosts/<name>/default.nix: bootloader,networking.hostName,system.stateVersion, andimports = [ ./hardware-configuration.nix ../../modules ]. - Add
<name> = mkHost ./hosts/<name>;toflake.nix. - Add the host's SSH host key to
secrets/secrets.nix, thenagenix -r. sudo nixos-rebuild switch --flake /home/jonathan/Code/nixos#<name>.
Each host needs its own hardware-configuration.nix — never copy one machine's
to another.
pi-NN (Raspberry Pi 5 k3s agents)
Each Pi is a hostname and address in hosts/pi-NN/; everything else is
modules/pi5-k3s-agent.nix + modules/pi5-boot.nix. Provisioned from an SD
image rather than the installer. It's built from
nixpkgs-unstable via binfmt emulation, so the building host needs
boot.binfmt.emulatedSystems = [ "aarch64-linux" ] (the desktop has it). The
Pi firmware loads the kernel directly (no U-Boot — it can't reach a USB disk
on the Pi 5); modules/pi5-boot.nix explains the layout. There's no boot
menu, so keep an eye on the HDMI console after a risky switch.
nix build .#pi-NN-image # -> result/sd-image/*.img
sudo dd if=result/sd-image/*.img of=/dev/sdX bs=4M conv=fsync status=progress
nixos-rebuild switch --flake .#pi-NN --target-host root@<address> # thereafter
Each Pi's SSH host key was generated up front and copied onto the imaged
disk's /etc/ssh so the k3s join token (secrets/k3s-token.age) decrypts on
first boot. If a disk is ever re-imaged, either copy the same key back or add
the new host key to secrets/secrets.nix and re-encrypt. The nodes join
storage-01's cluster tainted arch=arm64:NoSchedule, so workloads must
tolerate it (and select kubernetes.io/arch: arm64) to land there. After
first boot, enrol in NetBird once with netbird up on the node.
| host | address |
|---|---|
| pi-01 | 10.0.1.40 |
| pi-02 | 10.0.1.41 |
SSH host key, so update secrets/secrets.nix and run agenix -r, or boot-time |
|
| decryption will fail. |