6.2 KiB
NixOS + Home Manager Setup Overview (sam/nixos)
This document is a practical overview of how this NixOS setup was built and how “dotfiles” are managed, so another AI session (or you later) can replicate it on another machine.
Repo: ssh://git@gitea.lab.audasmedia.com.au:2222/sam/nixos.git
Goals of this setup
- Reproducible NixOS install via flakes (
nixos-rebuild/nixos-install) - Home Manager managed user config (zsh, kitty, nvim config, etc.)
- KDE Plasma + Hyprland selectable at SDDM login
- Neovim works reliably on NixOS:
- config tracked in git
- plugins installed via lazy.nvim into a writable directory
- avoid writing any lockfiles into
/nix/store(read-only)
High-level architecture
- System config:
hosts/<host>/configuration.nix - Hardware config:
hosts/<host>/hardware-configuration.nix- generated per-machine during install, then committed
- Home Manager (as NixOS module):
home/sam/home.nix - Neovim config stored in repo:
home/sam/nvim/...
Repo structure (typical)
flake.nixhosts/aspire-laptop/configuration.nixhosts/aspire-laptop/hardware-configuration.nixhome/sam/home.nixhome/sam/nvim/(init.lua, lua/, lazy-lock.json from old setup if needed)scripts/install-from-iso.sh
Installation procedure (wipe disk)
BIOS notes
- Secure Boot disabled on the Acer test laptop for easiest install. (If Secure Boot is locked by a BIOS Supervisor password, bare-metal install may be blocked; use a VM test instead.)
From the NixOS graphical ISO (live environment)
-
Connect to the internet.
-
Clone repo to the live environment:
git clone ssh://git@gitea.lab.audasmedia.com.au:2222/sam/nixos.git /tmp/nixos
-
Partition/mount (WIPES DISK):
- Identify disk (e.g.
/dev/sdaor/dev/nvme0n1) - Run:
sudo DISK=/dev/<disk> bash /tmp/nixos/scripts/install-from-iso.sh
This creates:
- EFI partition (vfat)
- Btrfs root with subvolumes
@and@home - Mounts under
/mntand generates/mnt/etc/nixos/hardware-configuration.nix
- Identify disk (e.g.
-
Copy repo into target:
sudo rm -rf /mnt/etc/nixossudo mkdir -p /mnt/etcsudo cp -a /tmp/nixos /mnt/etc/nixos
-
Copy generated hardware config into the repo host path:
sudo cp -f /mnt/etc/nixos/hardware-configuration.nix /mnt/etc/nixos/hosts/<host>/hardware-configuration.nix
-
Install:
sudo nixos-install --flake /mnt/etc/nixos#<host>- reboot
After first boot
- Set password for
samif needed:sudo passwd sam
- If using Tailscale:
sudo tailscale up
SSH access (to administer remotely)
This setup enabled OpenSSH server via NixOS config.
services.openssh.enable = true;services.openssh.openFirewall = true;- Password auth was enabled for convenience in testing (not best practice).
To apply:
sudo nixos-rebuild switch --flake /etc/nixos#<host>
“Dotfiles” / config management approach (what we actually did)
The key rule
Home Manager symlinks managed files into /nix/store (read-only). That is fine
for config files, but NOT fine for files that apps need to write to at runtime.
Neovim (special case)
Neovim + lazy.nvim expects to write:
- lockfile
- plugin installs
- cache/state
So:
- The Neovim config code is kept in git and linked by Home Manager, but we do
NOT have HM own the entire
~/.config/nvimdirectory.
We link only:
~/.config/nvim/init.lua~/.config/nvim/lua/
Example Home Manager linking (conceptual):
xdg.configFile."nvim/init.lua".source = ./nvim/init.lua;xdg.configFile."nvim/lua".source = ./nvim/lua;
- lazy.nvim is configured to write lockfile into a writable location:
- lockfile path:
vim.fn.stdpath("data") .. "/lazy-lock.json"(=>~/.local/share/nvim/lazy-lock.json)
- Plugins are installed by lazy.nvim into:
~/.local/share/nvim/lazy/
- After a new install / new machine, bootstrap plugins with:
nvim --headless "+Lazy! sync" "+qa"
Why we avoided Nix-managed Neovim plugins in HM
If programs.neovim.plugins = ... is used, Neovim may load plugins from a
read-only Nix “vim pack dir” under /nix/store/....
Some plugins (notably treesitter) try to write build artifacts into the plugin
directory, which fails on read-only paths.
Therefore:
- Nix installs
nvim+ dependencies (node/python/rg/fd/compilers). - lazy.nvim installs the plugins at runtime into user-writable dirs.
Other tools
Most other CLI tools can be installed declaratively via NixOS or Home Manager. Their configs can be safely managed by HM as symlinks (read-only is fine).
Notable fixes/decisions made during setup
-
If you see errors like “Read-only file system” writing
lazy-lock.json, it means HM is managing the lockfile path. Fix by moving lockfile to data dir and not linkinglazy-lock.jsoninto/nix/store. -
Treesitter module name mismatch was fixed in config to handle upstream changes: attempt
require("nvim-treesitter.config")and fallback torequire("nvim-treesitter.configs"). -
Avante was disabled on low-power machines by removing/renaming its plugin spec file so lazy.nvim does not load it.
-
Git remote update issues were resolved using:
git fetch origingit pull --rebase origin maingit push
Adding programs (basic workflow)
System-wide packages
Edit:
hosts/<host>/configuration.nixAdd to:environment.systemPackages = with pkgs; [ ... ];Apply:sudo nixos-rebuild switch --flake /etc/nixos#<host>
User-only packages
Edit:
home/sam/home.nixAdd to:home.packages = with pkgs; [ ... ];Apply:sudo nixos-rebuild switch --flake /etc/nixos#<host>
Then commit + push
cd /etc/nixosgit add -Agit commit -m "..." && git push
Secrets (do not put in git)
Do not commit API keys (Gemini/OpenAI/etc.) into this repo.
Preferred:
- store secrets outside git (password manager) and export into your shell
- or use a secret manager like
sops-nixlater
Example (local-only) environment file:
~/.config/environment.d/10-secrets.conf- contains
GEMINI_API_KEY=... - not tracked in git
- contains
References
- NixOS Manual: https://nixos.org/manual/nixos/stable/
- Home Manager Manual: https://nix-community.github.io/home-manager/
- Flakes: https://nixos.wiki/wiki/Flakes
- Packages/options search: https://search.nixos.org/