Fully declarative, cross-platform environment — shell, editor, git, CLI tools, system preferences, secrets, apps — all defined as code. This is a template repo: hit Use this template, swap in your identity, deploy. One command reproduces the entire setup on a new machine.
- macOS — nix-darwin + home-manager (system + user config)
- Linux / WSL — standalone home-manager (user config)
- NixOS-WSL — nixos-rebuild + home-manager (full system)
- NixOS server — nixos-rebuild + disko for cloud VPS / bare-metal deployment
curl -fsSL https://raw.githubusercontent.com/tskovlund/nix-config/main/bootstrap.sh | bashThe script installs Nix and Homebrew if needed, detects your platform, sets up identity, and runs the first deploy. After bootstrap completes: cd ~/repos/nix-config && make bootstrap for GitHub CLI auth, Claude Code settings, and SSH key upload.
Have an age key? Copy it to
~/.config/agenix/age-key.txtbefore running bootstrap so secrets decrypt on the first deploy.NixOS-WSL? Get git/curl first:
nix --extra-experimental-features "nix-command flakes" shell nixpkgs#git nixpkgs#curl, then run bootstrap.Prefer manual control? See
docs/manual-setup.md.
- Starship prompt with deterministic hash-colored hostname — each machine gets a unique, consistent color
- Full Neovim via nixvim — LSP, completion, format-on-save, telescope, treesitter
- Case-insensitive tab completion and zsh-autosuggestions out of the box
- Touch ID for sudo on macOS — no more typing passwords in the terminal
- Opinionated CLI toolkit — bat, delta, eza, zoxide, fzf, ripgrep, fd, and more
- direnv + nix-direnv — automatic per-project dev environments
- agenix secrets — age-encrypted, decrypted on deploy
- Forkable identity — zero personal info in the repo; your identity comes from a separate flake
See docs/features.md for the full inventory.
Every deployment is a target — a build tool + profile combination. Base gives you a solid dev environment on any machine. Personal layers on secrets, SSH keys, and personal config from your own flake.
| Target | Manages | Profile |
|---|---|---|
darwin |
macOS system + user config | personal |
darwin-base |
macOS system + user config | base |
nixos-wsl |
NixOS-WSL system + user config | personal |
nixos-wsl-base |
NixOS-WSL system + user config | base |
miles |
Hetzner VPS system + user config | personal |
linux |
User config only (any Linux distro) | personal |
linux-base |
User config only (any Linux distro) | base |
make switch auto-detects the right target. make switch-base picks the base variant.
This repo contains zero personal information. Your identity (username, name, email) comes from a separate personal flake:
mkdir -p ~/.config/nix-config
echo "git+ssh://git@github.com/YOUR_USER/nix-config-personal" > ~/.config/nix-config/personal-inputThe personal flake exports identity (username, name, email) and homeModules (secrets, SSH keys, dotfiles). See docs/architecture.md for the full design.
| Task | Command |
|---|---|
| Apply config (base + personal) | make switch |
| Apply config (base only) | make switch-base |
| Apply with machine-local config | make switch IMPURE=1 |
| Deploy to VPS | make deploy-miles MILES_HOST=root@<ip> |
| Validate without applying | make check |
| Update all inputs | make update |
| Format Nix files | make fmt |
| Lint Nix files | make lint |
All packages are pinned via flake.lock. Roll back with git checkout flake.lock && make switch. For platform-specific commands (rollback, diff closures, generations), see docs/platform-commands.md.
| Input | What it provides |
|---|---|
| nixpkgs (unstable) | Packages — rolling release, CI-tested |
| nix-darwin | Declarative macOS system config |
| home-manager | Declarative user environment |
| agenix | Age-encrypted secrets |
| nixvim | Neovim config as typed Nix |
| nixos-wsl | NixOS on WSL integration |
| disko | Declarative disk partitioning |
| mcp-servers-nix | MCP servers (persistent memory) |
| personal (stub) | Your identity flake — see Personal identity |
All inputs follow a single nixpkgs to avoid version drift.
| Document | Contents |
|---|---|
docs/features.md |
Full feature inventory (shell, editor, git, CLI tools, macOS defaults, Claude Code) |
docs/architecture.md |
Targets, profiles, builders, system modules, adding new hosts |
docs/manual-setup.md |
Post-deploy manual steps (fonts, permissions, MCP registration) |
docs/platform-commands.md |
Platform-specific commands (rollback, diff closures, generations) |
docs/miles.md |
Operational runbook for the Hetzner VPS |
After deploying (which installs direnv), enter the dev shell:
cd ~/repos/nix-config
direnv allowThis sets up commit hooks — pre-commit formats and lints .nix files, pre-push runs nix flake check --all-systems. CI validates both Linux and macOS on every PR.
Thomas Skovlund Hansen — skovlund.dev · thomas@skovlund.dev