A declarative macOS system configuration managed with nix-darwin, Home Manager, and Nix Flakes. This repository contains a complete setup for macOS including system packages, GUI applications, development tools, shell configuration, and system preferences.
- What is nix-darwin?
- Features
- Prerequisites
- Installation
- Configuration Overview
- What's Included
- Usage
- Customization
- Project Structure
- Troubleshooting
- Maintenance
nix-darwin is a tool that lets you manage your macOS system configuration declaratively using Nix. You can version control your entire system setup, making it reproducible and easy to replicate across machines. This means:
- Reproducible: Rebuild the exact same environment on any Mac
- Version Controlled: Track all changes in git
- Declarative: Define what you want, not how to get it
- Atomic: Updates are atomic - either everything works or nothing changes
- 🎨 System Configuration: Dock, Finder, Trackpad, Keyboard, and macOS preferences
- 📦 Package Management: System packages via Nix and GUI apps via Homebrew
- 🛠️ Development Tools: Kubernetes, Docker, Terraform/OpenTofu, and more
- 🐚 Shell Configuration: Zsh with Starship prompt and useful aliases
- 📝 Editor Setup: NixVim (Neovim) and Cursor IDE with auto-installed extensions
- 🖥️ Terminal Emulators: Fully configured Kitty, Ghostty, and Tabby with Edo theme
- 🎨 Theme System: Custom Edo color theme with semantic colors
- 🔐 Security: Touch ID for sudo, system hardening options
- ⚡ Optimizations: Fast key repeat, dock animations, and system tweaks
- ⏰ Menu Bar Apps: Clock-rs with 24-hour time display
- macOS (tested on Apple Silicon, but Intel should work with modifications)
- Administrator access (for system configuration)
- Basic familiarity with terminal commands
Choose one of the following installation methods:
Lix is a modern, community fork of Nix with improvements and fixes.
curl -sSf -L https://install.lix.systems/lix | sh -s -- installDeterminate Nix Installer is the easiest and most reliable way to install Nix—as well as our longest-running project.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- installApply the necessary Nix environment variables to your current shell session:
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.shImportant: If using a new terminal session, you may need to source this again, or restart your terminal.
Verify Nix is installed:
nix --versionHomebrew is used for GUI applications (Casks) that aren't available in nixpkgs:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"After installation, add Homebrew to your PATH:
eval "$(/opt/homebrew/bin/brew shellenv)"git clone https://github.com/jmutai/nixos-configs-mac.git
cd nixos-configs-macThe configuration now supports dynamic hostname detection! Check your Mac's hostname:
scutil --get LocalHostNameAutomatic Detection (Recommended):
darwin-rebuildwill automatically detect and use your system's hostname when you rundarwin-rebuild switch --flake .- Simply add your hostname to the
hostnameslist inflake.nix(see below) - After adding it once, it will work automatically on subsequent builds
Manual Configuration (If you have multiple machines):
Edit flake.nix and add your hostname(s) to the hostnames list at the top of the let block:
hostnames = [
"macbook-pro" # Current hostname
"Your-New-Hostname" # Add additional hostnames here
];HostName, LocalHostName and ComputerName can be changed from CLI:
sudo scutil --set HostName macbook-pro-m3
sudo scutil --set LocalHostName macbook-pro-m3
sudo scutil --set ComputerName "Mutai's MacBook Pro"Confirm settings:
scutil --get HostName
scutil --get LocalHostName
scutil --get ComputerNameYou may see different values, they each serve a slightly different purpose.
| Type | Description | Example |
|---|---|---|
| HostName | Used by network services (e.g., SSH, Terminal prompt). | macbook-pro.local |
| LocalHostName | Used for Bonjour/AirDrop. | macbook-pro |
| ComputerName | Visible name in System Settings → General → Sharing. | Josphat’s MacBook Pro |
All configuration variables (hostnames, username) are now defined at the top of the let block for easy customization.
Update Username:
Edit flake.nix and change the username variable at the top of the let block:
username = "jkmutai"; # Change to your macOS usernameThe configuration will automatically use this username throughout the setup.
Update Git Configuration:
Edit home.nix and update the git user settings:
programs.git = {
settings = {
user = {
name = ""; # Change to your git username
email = ""; # Change to your git email
};
# ... rest of config
};
};This will configure your git identity globally for all repositories.
Run the initial build to apply your configuration:
sudo nix run nix-darwin -- switch --flake .This will:
- Install all system packages
- Configure macOS settings
- Set up Home Manager
- Install GUI applications via Homebrew
- Configure your shell and development tools
First build may take 20-30 minutes depending on your internet connection and system.
After the first build completes, verify everything is working:
# Test your update alias
update
# Check if packages are available
which nvim
which git
which kubectl
# Verify shell configuration
echo $SHELL # Should show zshThis configuration uses:
- nix-darwin: System-level configuration and macOS settings
- Home Manager: User-level configuration and packages
- Nix Flakes: Modern Nix package management with locked dependencies
- NixVim: Neovim configuration managed in Nix
flake.nix: Main flake configuration - inputs, outputs, and system setuphome.nix: User configuration - imports all program modulesmodules/packages.nix: System packages installed via Nix and Homebrewmodules/system-settings.nix: macOS system settings and preferencesmodules/nix-core.nix: Nix configuration settingsmodules/aliases.nix: Shell aliases (git, kubectl, docker, etc.)modules/keyboard-remap.nix: Keyboard remapping configurationnixvim.nix: Neovim configuration - plugins, themes, LSP servers
All user programs are configured in modules/home/programs/:
zsh.nix: Zsh shell with Starship promptcursor.nix: Cursor IDE with extensions and settingskitty.nix: Kitty terminal configurationghostty.nix: Ghostty terminal configurationtabby.nix: Tabby terminal configurationgit.nix: Git configurationbat.nix: Bat (cat replacement) configurationfzf.nix: Fuzzy finder configurationtmux.nix: Tmux configurationstarship.nix: Starship prompt configurationclock-rs.nix: Clock-rs menu bar appantigravity.nix: Antigravity configurationhtop.nix: Htop configurationtheme.nix: Edo color theme definition
- Communication: Slack, Zoom, Discord
- Terminals: Kitty, Alacritty (configured: Kitty, Ghostty, Tabby)
- Browsers: Firefox
- Development: GitHub CLI, Docker Compose, Lazydocker, Devbox
- Productivity: Obsidian, Joplin Desktop, LazyGit
- Editors: Neovim, Vim, Nix IDE tools (nil, nixd, nixpkgs-fmt)
- CLI Tools: Git, curl, wget, tree, ripgrep, fzf, bat, eza, tmux, zellij
- System Tools: htop, btop, bottom, neofetch, fastfetch, ranger
- Languages: Python 3, Go, Lua, Node.js (via Homebrew)
- Media: Spotify, yt-dlp, ffmpeg
- Fonts: Nerd Fonts (Fira Code, JetBrains Mono, Meslo LG, Hack)
- Editors: Cursor (fully configured), Visual Studio Code, Zed
- Browsers: Brave, Vivaldi, Google Chrome, Microsoft Edge
- Terminals: iTerm2, Ghostty, Tabby
- Productivity: Notion
- File Sharing: Transmission, qBittorrent, Motrix
- Containers: Docker Desktop, Podman Desktop
- System Tools: Karabiner Elements, KeepassXC
- VPN: Tailscale, Tunnelblick, Pritunl
- Database: Beekeeper Studio
- Remote Access: Microsoft Remote Desktop
- Fonts: SF Mono, SF Pro, Maple Mono, SF Symbols
- Kubernetes: kubectl, k9s, Lens, Kubernetes Helm, Kustomize
- Containers: Podman, podman-compose
- Infrastructure: OpenTofu, Terragrunt, Ansible, Terraform Docs, TFLint, Infracost
- Security Scanning: Checkov, TFSec, Terrascan, Trivy
- Cloud: Google Cloud SDK (with GKE auth plugin)
- Databases: PostgreSQL, MariaDB
- VPN: OpenVPN, Tailscale, NetBird
- Tools: HCL Edit, Pre-commit, Graphviz, TFUpdate
- Zsh with Starship prompt (modern, fast, and customizable)
- Plugins: git, docker, kubectl, terraform, macos, fzf, and more
- Aliases: Git shortcuts, kubectl aliases, Docker/Podman shortcuts, Terraform/OpenTofu shortcuts
- Modern Tools: eza (ls), bat (cat), fzf (fuzzy finder), tmux, zellij
- Configuration: Modular setup in
modules/home/programs/zsh.nix
- Theme: Catppuccin
- Plugins: Lualine, nvim-tree, Telescope, Treesitter
- LSP: Nix (nil-ls), Lua (lua-ls)
- Features: Syntax highlighting, file tree, fuzzy finder, status bar
- Auto-installed Extensions: Python, Go, Rust, Prettier, ESLint, GitLens, Terraform, Kubernetes, and more
- Font: SF Mono for editor, Nerd Fonts for terminal
- Theme: Cursor Dark Midnight
- Features: Format on save, bracket pair colorization, minimap, and more
- Configuration: Managed in
modules/home/programs/cursor.nix
All terminals are configured with the Edo theme and Nerd Fonts:
- Kitty: Powerline tabs, Edo theme, JetBrainsMono Nerd Font, optimized spacing
- Ghostty: GPU-accelerated, Edo theme, Nerd Fonts, hidden titlebar
- Tabby: Modern terminal, Edo theme, Nerd Fonts, configurable profiles
Configuration files:
modules/home/programs/kitty.nixmodules/home/programs/ghostty.nixmodules/home/programs/tabby.nix
- Edo Theme: Custom dark theme with excellent contrast
- Semantic Colors: Success, error, warning, info colors
- Terminal Colors: Optimized ANSI color palette
- Configuration:
modules/home/theme.nix
- Dock: Auto-hide, left position, optimized animations
- Finder: Show extensions, path bar, list view
- Keyboard: Caps Lock → Control, fast key repeat
- Trackpad: Tap to click, three-finger drag
- Security: Touch ID for sudo, guest account disabled
- Screenshots: PNG format, saved to
~/Pictures/Screenshots - Menu Bar: Clock-rs with 24-hour time display
# Update system configuration
update
# Update and rebuild with latest flake inputs
upgrade
# Clean up old Nix generations
cleanup
# Rebuild configuration (if you're already in the config directory)
sudo darwin-rebuild switch --flake .See home.nix for a complete list, but here are some highlights:
Git:
g= gitgs= git statusga= git addgc= git commitgp= git push
Kubernetes:
k= kubectlkgp= kubectl get podskl= kubectl logskexec= kubectl exec -it
Docker/Podman:
d= dockerdc= docker-composep= podmanpc= podman-compose
Terraform/OpenTofu:
tf= tofutg= terragrunttgaa= terragrunt apply -auto-approve
System packages (available to all users):
Edit modules/packages.nix and add to environment.systemPackages:
environment.systemPackages = with pkgs; [
# ... existing packages
your-package-name
];User packages (specific to your user):
Edit home.nix and add to home.packages:
home.packages = with pkgs; [
# ... existing packages
your-package-name
];Homebrew Casks (GUI applications):
Edit modules/homebrew.nix and add to homebrew.casks:
homebrew = {
casks = [
# ... existing casks
"your-app-name"
];
};After making changes, rebuild:
updateEdit modules/home/programs/zsh.nix for shell configuration:
- Starship prompt: Configured in
modules/home/programs/starship.nix - Custom shell functions: Add to
programs.zsh.initExtra
Shell aliases are in modules/aliases.nix:
- Edit
modules/aliases.nixto add, modify, or remove aliases - This keeps all aliases organized in one place
Edit home.nix under programs.git.settings.user:
- Name: Change
user.nameto your git username - Email: Change
user.emailto your git email - Aliases: Add custom git aliases under
alias.* - Editor: Change
core.editorif you prefer a different editor
Neovim: Edit nixvim.nix:
- Theme: Change
colorschemes.*.enable - Plugins: Add to
plugins.* - Options: Modify
opts.*
Cursor IDE: Edit modules/home/programs/cursor.nix:
- Extensions: Add to
cursorExtensionslist (auto-installed) - Settings: Modify
settings.jsoncontent - Keybindings: Modify
keybindings.jsoncontent
All terminals use the Edo theme from modules/home/theme.nix:
- Kitty: Edit
modules/home/programs/kitty.nix - Ghostty: Edit
modules/home/programs/ghostty.nix - Tabby: Edit
modules/home/programs/tabby.nix
To change the theme colors, edit modules/home/theme.nix.
Edit modules/system-settings.nix:
- Dock settings:
system.defaults.dock.* - Finder settings:
system.defaults.finder.* - Keyboard settings:
system.defaults.NSGlobalDomain.* - Trackpad settings:
system.defaults.trackpad.*
nixos-configs-mac/
├── flake.nix # Main flake configuration with inputs and outputs
├── flake.lock # Locked dependencies (auto-generated)
├── home.nix # User configuration: imports all program modules
├── nixvim.nix # Neovim configuration: plugins, themes, LSP
├── modules/ # Modular configuration files
│ ├── packages.nix # System packages (Nix) and Homebrew
│ ├── system-settings.nix # macOS system settings and preferences
│ ├── nix-core.nix # Nix configuration settings
│ ├── keyboard-remap.nix # Keyboard remapping configuration
│ ├── aliases.nix # Shell aliases (git, kubectl, docker, etc.)
│ └── home/ # Home Manager program configurations
│ ├── theme.nix # Edo color theme definition
│ └── programs/ # Individual program configurations
│ ├── zsh.nix # Zsh with Starship
│ ├── cursor.nix # Cursor IDE configuration
│ ├── kitty.nix # Kitty terminal
│ ├── ghostty.nix # Ghostty terminal
│ ├── tabby.nix # Tabby terminal
│ ├── git.nix # Git configuration
│ ├── bat.nix # Bat configuration
│ ├── fzf.nix # Fuzzy finder
│ ├── tmux.nix # Tmux
│ ├── starship.nix # Starship prompt
│ ├── clock-rs.nix # Clock-rs menu bar app
│ ├── antigravity.nix # Antigravity
│ └── htop.nix # Htop
└── README.md # This fileBenefits of this modular structure:
- Better organization: Each file has a single, clear purpose
- Easier maintenance: Find and edit specific configurations quickly
- Cleaner files: Main config files are more readable
- Scalable: Easy to add new modules as your configuration grows
Issue: Package not available after installation
Solution:
- Check if the package name is correct in nixpkgs
- Rebuild:
update - Start a new terminal session
Issue: Homebrew casks not installing
Solution:
- Verify Homebrew is installed:
which brew - Check if the cask name is correct:
brew search <app-name> - Manually install to verify:
brew install --cask <app-name>
Issue: Zsh configuration not loading
Solution:
- Verify zsh is your default shell:
echo $SHELL - Check if home.nix is properly imported in flake.nix
- Rebuild:
update - Source your shell config:
source ~/.zshrc
Issue: sudo: ... command not found or permission denied
Solution:
- Make sure you're using
sudofor system-level changes - Verify your user has sudo privileges
- Check file permissions if editing files directly
Issue: Nix store growing too large
Solution: Run cleanup regularly:
cleanup # or: nix-collect-garbage -dYou can also adjust the garbage collection settings in flake.nix:
nix.gc = {
automatic = true;
interval = { Weekday = 7; }; # Run on Sundays
options = "--delete-older-than 30d"; # Keep last 30 days
};Update packages and configuration:
upgradeThis updates all flake inputs and rebuilds your system.
Update just packages (keep flake inputs locked):
updateNix keeps old system generations for rollback. Clean them up periodically:
cleanupOr manually:\
nix-collect-garbage -dYour configuration is already version controlled! Just commit and push:
git add .
git commit -m "Update configuration"
git pushIf something goes wrong, you can rollback to a previous generation:
sudo darwin-rebuild switch --rollbackOr list all generations:
sudo darwin-rebuild --list-generationsThen switch to a specific generation:
sudo darwin-rebuild switch --rollback <generation-number>ln -sfn ~/.cheats/.p10k.zsh ~/.p10k.zsh
ln -sfn ~/.cheats/.p10k.zsh ~/.config/p10k.zsh
rm -rf ~/.ssh
ln -sfn ~/.cheats/.ssh/ ~/.sshDisable iPhone apps showing in Spotlight search:
- Open System Settings ( menu > System Settings).
- Click Spotlight in the sidebar (or search for "Spotlight" in the top search bar).
- Under Results from System, find iPhone Apps - it might be a checkbox or toggle.
- Uncheck to off "iPhone Apps".
This configuration is for personal use. Feel free to fork and adapt for your needs!
Note: This configuration is tailored for Apple Silicon Macs. If you're on Intel, change hostPlatform in flake.nix from "aarch64-darwin" to "x86_64-darwin".