Nix-managed dotfiles using nix-darwin and home-manager.
Defined once in machines.nix; the key is the flake configuration name.
| Configuration | Machine |
|---|---|
darwinConfigurations.Han-MBP |
Personal MacBook Pro |
darwinConfigurations.work |
Work MacBook Pro |
homeConfigurations.hanlee@ubuntu |
Personal Linux |
homeConfigurations.ephemeral |
Ephemeral machines (containers, devcontainers, WSL) |
Linux configurations also exist with an -aarch64 suffix (e.g. ephemeral-aarch64) for ARM.
git clone https://github.com/hannoeru/dotfiles ~/dotfiles
~/dotfiles/scripts/bootstrap.sh
macOS:
sudo darwin-rebuild switch --flake ~/dotfiles#Han-MBP
sudo darwin-rebuild switch --flake ~/dotfiles#work
Linux (x86_64):
nix run ~/dotfiles#home-manager -- switch -b backup --flake ~/dotfiles#ephemeral
Linux (aarch64):
nix run ~/dotfiles#home-manager -- switch -b backup --flake ~/dotfiles#ephemeral-aarch64
Update inputs:
nix flake update
nix fmt # format Nix files
nix run .#darwin-rebuild # pinned darwin-rebuild
scripts/check.sh # eval-only check of all flake outputs
A scheduled workflow opens a pull request every Monday to update flake.lock.
Because that pull request is opened with the default workflow token, GitHub
does not run the check workflow on it; the check runs after the merge.
containers/devcontainer/Dockerfile builds a base image (Ubuntu + Nix + this
repo's ephemeral configuration) and CI publishes it to
ghcr.io/hannoeru/devcontainer for amd64 and arm64. .devcontainer/devcontainer.json uses
that image, so any repository can adopt the same environment by referencing
it. mise runtimes are not pre-installed in the image; mise installs each one
on first use.
machines.nix— all machine definitions (single source of truth)modules/darwin.nix— shared nix-darwin system configmodules/home/— shared home-manager config (programs/holds one module per program)home/— dotfiles applied verbatim to$HOMEcontainers/devcontainer/— devcontainer base imagescripts/bootstrap.sh— fresh machine bootstrap
- GUI apps and fonts come from Homebrew (managed by nix-darwin); manually installed packages are left alone.
- Language runtimes (node, python, ...) come from mise; run
mise installafter first activation (bootstrap does this), or rely on mise's auto-install on first use (the devcontainer does). - Personal secrets (git signing key, SSH config) come from the 1Password CLI during activation; if it is missing, they are skipped. Run the switch a second time after installing it.
- Clean the Nix store occasionally:
nix-collect-garbage --delete-older-than 30d.