Skip to content
appsbynate
← dev tools

dotfiles

My development environment as one idempotent script — fresh machine to configured in four minutes.

Section
dev tools
Year
2024
Role
Solo project
Stack
Bash, Nix, Neovim

Replace this file with a real project. Small tools count — a well-explained 300-line script says more about how you think than a large project described in one sentence.

The problem

I set up a new laptop roughly once a year and spent most of a day on it every time, rediscovering which settings I cared about by noticing their absence.

What I chose, and why

One entry point, ./bootstrap, safe to run repeatedly. Everything it does is idempotent: it checks the desired state, and acts only if reality differs.

I went with Nix for packages and plain symlinks for configuration, rather than going all-in on home-manager. Nix gives reproducible tool versions, which is the part I actually wanted. Config files stay as ordinary dotfiles I can edit in place and see under version control without a rebuild step — the friction of that rebuild is what made me abandon a fully-declarative setup the first time.

The hard part

Secrets. The repo is public, but the environment needs SSH keys, API tokens, and a work-specific Git identity.

The answer was that the repo contains no secrets and no encrypted secrets either — it contains the shape of them. bootstrap generates a template at ~/.config/local/env, prompts for anything missing on first run, and every subsequent run leaves it alone. The public repo describes the environment; the machine holds the values.

What I’d change

The Neovim config is still 900 lines of Lua that I’ve never fully re-read. It works, and roughly 200 of those lines are for a workflow I abandoned in 2023.

I’d also add a test. A GitHub Action that runs bootstrap twice in a clean container — asserting the second run makes no changes — would have caught the three separate occasions I broke idempotency without noticing.