This commit is contained in:
Morten Olsen
2025-12-15 11:42:42 +01:00
committed by Morten Olsen
commit f42a092b60
21 changed files with 4695 additions and 0 deletions

486
docs/migration-analysis.md Normal file
View File

@@ -0,0 +1,486 @@
# Chezmoi to Nix Home Manager Migration Analysis
## Executive Summary
This document analyzes the current chezmoi-based dotfiles configuration to prepare for migration to Nix Home Manager with flakes. The configuration manages a macOS development environment with two distinct profiles: **personal** and **work** (ZeroNorth).
---
## 1. Managed Dotfiles Overview
### 1.1 File Structure
| Chezmoi Path | Target Path | Type | Templated |
|--------------|-------------|------|-----------|
| `dot_zshrc` | `~/.zshrc` | Shell config | No |
| `dot_tmux.conf` | `~/.tmux.conf` | Tmux config | No |
| `dot_gitconfig.tmpl` | `~/.gitconfig` | Git config | **Yes** |
| `dot_gitignore_global` | `~/.gitignore_global` | Git ignore | No |
| `dot_Brewfile.tmpl` | `~/.Brewfile` | Homebrew packages | **Yes** |
| `dot_aerospace.toml` | `~/.aerospace.toml` | Window manager | No |
| `dot_config/atuin/config.toml` | `~/.config/atuin/config.toml` | Shell history | No |
| `dot_shellrc/rc.d/*` | `~/.shellrc/rc.d/*` | Shell scripts | No |
| `dot_ssh/config` | `~/.ssh/config` | SSH config | No |
| `dot_ssh/config.d/*` | `~/.ssh/config.d/*` | SSH host configs | No |
| `dot_ssh/private_keys/*` | `~/.ssh/keys/*` | SSH public keys | **Partial** |
| `private_Library/...` | `~/Library/...` | App configs | No |
| `private_Projects/*` | `~/Projects/*` | Project configs | No |
### 1.2 External Dependencies
From [`.chezmoiexternal.toml`](.chezmoiexternal.toml:1):
```toml
[".ssh/authorized_keys"]
type = "file"
url = "https://github.com/morten-olsen.keys"
refreshPeriod = "168h"
```
**Migration consideration:** This fetches SSH authorized keys from GitHub. In Nix, this could be handled by:
- A custom derivation that fetches the keys at build time
- A systemd service/launchd agent that periodically updates the file
- Manual management with `home.file` and periodic updates
---
## 2. Personal vs Work Differentiation
### 2.1 Template Variable: `.work`
The configuration uses a boolean `.work` template variable to differentiate between personal and work environments.
### 2.2 Conditional Logic Summary
#### `.chezmoiignore` - File Exclusions
From [`.chezmoiignore`](.chezmoiignore:2):
| Condition | Ignored Files |
|-----------|---------------|
| `work = false` (Personal) | `Projects/private`, `Projects/zeronorth` |
| `work = true` (Work) | `Projects/.gitconfig` |
**Interpretation:**
- **Personal machines:** Don't deploy work-related project configs
- **Work machines:** Don't deploy the personal Projects/.gitconfig, use project-specific ones instead
#### `dot_Brewfile.tmpl` - Package Differences
From [`dot_Brewfile.tmpl`](dot_Brewfile.tmpl:66):
| Environment | Additional Packages |
|-------------|---------------------|
| Personal only (`work != true`) | `darktable`, `signal`, `proton-mail-bridge`, `proton-pass`, `protonvpn`, `steam` |
| Work | (none additional) |
#### `dot_gitconfig.tmpl` - Git Configuration
From [`dot_gitconfig.tmpl`](dot_gitconfig.tmpl:45):
| Environment | Git Include Configuration |
|-------------|---------------------------|
| Personal (`work = false`) | Single includeIf for `~/Projects/``~/Projects/.gitconfig` |
| Work (`work = true`) | Two includeIfs: `~/Projects/private/` and `~/Projects/zeronorth/` with separate configs |
#### `dot_ssh/private_keys/private_github-private.pub.tmpl` - SSH Keys
From [`dot_ssh/private_keys/private_github-private.pub.tmpl`](dot_ssh/private_keys/private_github-private.pub.tmpl:1):
| Environment | SSH Key |
|-------------|---------|
| Personal | `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFaIAP/ZJ7+7jeR44e1yIJjfQAB6MN351LDKJAXVF62P` |
| Work | `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILAzuPy7D/54GxMq9Zhz0CUjaDnEQ6RkQ/yqVYl7U55k` |
---
## 3. Detailed Configuration Analysis
### 3.1 Shell Configuration
#### Zsh ([`dot_zshrc`](dot_zshrc:1))
- Sets `XDG_RUNTIME_DIR` and `LANG`
- Sources scripts from `~/.shellrc/rc.d/*.sh` and `~/.shellrc/zshrc.d/*.zsh`
- Configures GPG TTY for SSH sessions
- Displays ASCII art welcome banner
- Configures FZF with Catppuccin color scheme
- Initializes: `atuin`, `direnv`, `starship`, `zoxide`, `pyenv`
- Adds Rust/Cargo to PATH
#### Shell RC Scripts
| File | Purpose |
|------|---------|
| [`01-env.sh`](dot_shellrc/rc.d/01-env.sh:1) | PATH setup, aliases (ls→eza, cat→bat, grep→rg, diff→delta, less→bat) |
| [`01-nvim.sh`](dot_shellrc/rc.d/01-nvim.sh:1) | Sets EDITOR=nvim, alias vim=nvim |
| [`05-nvm.sh`](dot_shellrc/rc.d/05-nvm.sh:1) | NVM initialization |
### 3.2 Git Configuration
#### Global Config ([`dot_gitconfig.tmpl`](dot_gitconfig.tmpl:1))
- **Aliases:** graph, ll, st, cm, append, submodules, df, last, br, brr, undo, unstage
- **Core:** Uses delta as pager, disables hooks, references global gitignore
- **Pull:** Fast-forward only
- **Push:** Auto setup remote
- **LFS:** Configured
- **Difftool:** nvim diff
#### Project-Specific Configs
| Config | Email | Signing Key | URL Rewrites |
|--------|-------|-------------|--------------|
| [`Projects/.gitconfig`](private_Projects/dot_gitconfig:1) (Personal) | `fbtijfdq@void.black` | Personal key | github-private, gitea.olsen.cloud |
| [`Projects/private/.gitconfig`](private_Projects/private_private/dot_gitconfig:1) (Work) | `fbtijfdq@void.black` | Work key | github-private, gitea.olsen.cloud |
| [`Projects/zeronorth/.gitconfig`](private_Projects/private_zeronorth/dot_gitconfig:1) (Work) | `morten.olsen@zeronorth.com` | ZeroNorth key | github-zeronorth |
### 3.3 SSH Configuration
#### Main Config ([`dot_ssh/config`](dot_ssh/config:1))
- Includes colima SSH config
- Includes all files from `~/.ssh/config.d/`
- Global settings: ControlMaster, 1Password SSH agent, ForwardAgent
#### Host Configurations
| Host | Hostname | Port | Identity |
|------|----------|------|----------|
| [`github.com`](dot_ssh/config.d/github:1) | ssh.github.com | 443 | Default |
| [`github-private`](dot_ssh/config.d/git-private:1) | ssh.github.com | 443 | github-private.pub |
| [`github-zeronorth`](dot_ssh/config.d/git-zeronorth:1) | ssh.github.com | 443 | github-zeronorth.pub |
| [`gitea-ssh.olsen.cloud`](dot_ssh/config.d/git-private:8) | gitea-ssh.olsen.cloud | 2202 | github-private.pub |
| [`coder.*`](dot_ssh/config.d/git-coder:7) | (proxy) | - | Coder CLI |
### 3.4 Tmux Configuration ([`dot_tmux.conf`](dot_tmux.conf:1))
- Mouse enabled
- 256-color terminal support
- Vim-style keybindings (hjkl navigation)
- TPM (Tmux Plugin Manager) with auto-install
- Plugins: tmux-power, tmux-yank, tmux-sensible
- Vim-tmux navigator integration
- Custom bindings for splits, copy mode, lazygit popup
### 3.5 Aerospace Window Manager ([`dot_aerospace.toml`](dot_aerospace.toml:1))
- Starts at login
- Tiling layout with gaps
- QWERTY key mapping
- Workspace navigation (alt+1-6)
- Window movement (cmd+shift+hjkl)
- Service mode for layout management
- Floating layout for Elgato apps
### 3.6 Application Configs
#### Atuin ([`dot_config/atuin/config.toml`](dot_config/atuin/config.toml:1))
```toml
style = "compact"
keymap_mode = "vim-normal"
```
#### Jellyfin TUI ([`private_Library/private_Application Support/jellyfin-tui/private_config.yaml`](private_Library/private_Application Support/jellyfin-tui/private_config.yaml:1))
- Server: jellyfin.olsen.cloud
- Username: morten
- Password stored in separate file
### 3.7 Environment Variables (Work)
From [`Projects/zeronorth/.envrc`](private_Projects/private_zeronorth/dot_envrc:1):
```bash
export NODE_AUTH_TOKEN="op://Employee/Github NPM Token/password"
export NPM_TOKEN="op://Employee/Github NPM Token/password"
export NPM_GITHUB_TOKEN="op://Employee/Github NPM Token/password"
export AWS_PROFILE=zntest
```
Uses 1Password CLI references for secrets.
---
## 4. Homebrew Packages
### 4.1 Taps
- `coder/coder`
- `felixkratz/formulae`
- `fluxcd/tap`
- `nikitabobko/tap`
- `sst/tap`
### 4.2 Formulae (All Environments)
| Category | Packages |
|----------|----------|
| **Languages/Runtimes** | python@3.13, deno, rustup, pyenv, uv |
| **Shell Tools** | zsh, atuin, starship, fzf, zoxide, direnv |
| **File Utils** | bat, eza, fd, ripgrep, rsync, unzip |
| **Git** | git, gh, git-delta, jj |
| **Containers/K8s** | docker, docker-buildx, docker-compose, colima, kubernetes-cli, helm, helmfile, k9s, istioctl, flux |
| **Dev Tools** | neovim, tmux, jq, graphviz, terraform, ansible, sshpass |
| **Media** | ffmpeg |
| **Security** | gnupg |
| **Other** | curl, watch, coder, opencode, tree-sitter-cli |
### 4.3 Casks (All Environments)
- **Terminal:** ghostty
- **Productivity:** 1password, 1password-cli, raycast, obsidian
- **Development:** dbeaver-community, lens
- **Media:** jellyfin-media-player, ollama-app
- **Window Management:** aerospace
- **Networking:** localsend, mqtt-explorer
- **Home Automation:** home-assistant
### 4.4 Casks (Personal Only)
- darktable (photo editing)
- signal (messaging)
- proton-mail-bridge, proton-pass, protonvpn (Proton suite)
- steam (gaming)
---
## 5. Recommended Nix Home Manager Structure
### 5.1 Flake Structure
```
flake.nix
├── flake.lock
├── home/
│ ├── default.nix # Common configuration
│ ├── personal.nix # Personal-specific config
│ ├── work.nix # Work-specific config
│ └── modules/
│ ├── shell/
│ │ ├── zsh.nix
│ │ ├── starship.nix
│ │ ├── atuin.nix
│ │ └── aliases.nix
│ ├── git/
│ │ ├── default.nix
│ │ ├── personal.nix
│ │ └── work.nix
│ ├── ssh/
│ │ ├── default.nix
│ │ └── hosts.nix
│ ├── tmux.nix
│ ├── aerospace.nix
│ ├── neovim.nix
│ └── packages.nix
└── docs/
└── migration-analysis.md
```
### 5.2 Configuration Approach
```nix
# flake.nix (simplified)
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
# Darwin support for macOS
nix-darwin = {
url = "github:LnL7/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, home-manager, nix-darwin, ... }: {
homeConfigurations = {
"personal" = home-manager.lib.homeManagerConfiguration {
# Personal machine config
modules = [ ./home/default.nix ./home/personal.nix ];
};
"work" = home-manager.lib.homeManagerConfiguration {
# Work machine config
modules = [ ./home/default.nix ./home/work.nix ];
};
};
};
}
```
### 5.3 Module Mapping
| Chezmoi File | Nix Module | Home Manager Option |
|--------------|------------|---------------------|
| `dot_zshrc` | `shell/zsh.nix` | `programs.zsh` |
| `dot_tmux.conf` | `tmux.nix` | `programs.tmux` |
| `dot_gitconfig.tmpl` | `git/default.nix` | `programs.git` |
| `dot_gitignore_global` | `git/default.nix` | `programs.git.ignores` |
| `dot_Brewfile.tmpl` | `packages.nix` | `home.packages` + homebrew module |
| `dot_aerospace.toml` | `aerospace.nix` | `home.file` |
| `dot_config/atuin/*` | `shell/atuin.nix` | `programs.atuin` |
| `dot_ssh/*` | `ssh/default.nix` | `programs.ssh` |
---
## 6. Migration Challenges and Considerations
### 6.1 Homebrew Integration
**Challenge:** Many casks are macOS-specific and not available in nixpkgs.
**Solutions:**
1. Use `nix-darwin` with homebrew module for casks
2. Keep a minimal Brewfile for casks only
3. Use `home.packages` for CLI tools available in nixpkgs
**Packages requiring Homebrew:**
- All casks (1password, ghostty, aerospace, etc.)
- Some taps (coder, flux, opencode)
### 6.2 1Password SSH Agent Integration
**Challenge:** SSH config references 1Password agent socket.
**Solution:** Use conditional paths or environment-specific SSH config:
```nix
programs.ssh = {
extraConfig = ''
IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
'';
};
```
### 6.3 Tmux Plugin Manager (TPM)
**Challenge:** TPM auto-installs from git, which doesn't fit Nix's declarative model.
**Solutions:**
1. Use `programs.tmux.plugins` with nixpkgs tmux plugins
2. Package custom plugins as Nix derivations
3. Keep TPM but manage it outside Nix (hybrid approach)
### 6.4 NVM (Node Version Manager)
**Challenge:** NVM is imperative and conflicts with Nix's approach.
**Solutions:**
1. Use `programs.nodejs` with specific version
2. Use `nix-shell` or `direnv` with `use nix` for project-specific Node versions
3. Use `devenv` or `flake.nix` per-project
### 6.5 External Key Fetching
**Challenge:** `.chezmoiexternal.toml` fetches SSH keys from GitHub.
**Solutions:**
1. Create a derivation that fetches at build time (keys become stale)
2. Use a launchd agent to periodically update
3. Manual management with documentation
### 6.6 Private/Sensitive Files
**Challenge:** Files prefixed with `private_` contain sensitive data.
**Solutions:**
1. Use `sops-nix` for encrypted secrets
2. Use `agenix` for age-encrypted secrets
3. Keep sensitive files outside Nix, managed separately
4. Use 1Password CLI references (already used in `.envrc`)
### 6.7 Project-Specific Git Configs
**Challenge:** Multiple git configs for different project directories.
**Solution:** Use `programs.git.includes`:
```nix
programs.git = {
includes = [
{
condition = "gitdir:~/Projects/zeronorth/";
path = "~/Projects/zeronorth/.gitconfig";
}
];
};
```
### 6.8 macOS-Specific Paths
**Challenge:** Hardcoded paths like `/opt/homebrew/bin`, `/Applications/`.
**Solution:** Use Nix variables and conditionals:
```nix
home.sessionPath = [ "/opt/homebrew/bin" "$HOME/.local/bin" ];
```
---
## 7. Migration Phases
### Phase 1: Foundation
1. Set up flake structure with nix-darwin and home-manager
2. Create base configuration with common packages
3. Implement personal/work profile switching
### Phase 2: Shell Environment
1. Migrate zsh configuration
2. Set up starship, atuin, zoxide, direnv
3. Configure shell aliases and environment variables
### Phase 3: Development Tools
1. Migrate git configuration with conditional includes
2. Set up SSH configuration
3. Configure tmux (decide on TPM approach)
4. Set up neovim (if managed by chezmoi elsewhere)
### Phase 4: Applications
1. Configure aerospace (via home.file)
2. Set up application configs (atuin, jellyfin-tui)
3. Handle Homebrew casks via nix-darwin
### Phase 5: Secrets and Sensitive Data
1. Implement sops-nix or agenix for secrets
2. Migrate SSH keys
3. Handle 1Password integrations
### Phase 6: Testing and Validation
1. Test on personal machine
2. Test on work machine
3. Document any manual steps required
---
## 8. Summary
### Key Findings
1. **Two distinct profiles:** Personal and Work, differentiated by `.work` boolean
2. **Template usage:** Limited to Brewfile, gitconfig, SSH keys, and ignore rules
3. **External dependencies:** SSH authorized keys fetched from GitHub
4. **macOS-centric:** Heavy use of Homebrew casks, 1Password, aerospace
5. **Secrets:** 1Password CLI references used for work environment
### Recommended Approach
1. **Use nix-darwin** for macOS system configuration and Homebrew cask management
2. **Use home-manager** for user-level dotfiles and packages
3. **Implement profiles** using Nix modules with `mkIf` conditionals
4. **Keep Homebrew** for casks that aren't available in nixpkgs
5. **Use sops-nix** for managing sensitive configuration
6. **Gradual migration** - start with shell and git, then expand
### Files to Create
```
flake.nix # Main flake with darwin and home-manager
home/default.nix # Common home-manager config
home/personal.nix # Personal-specific settings
home/work.nix # Work-specific settings
home/modules/shell/zsh.nix # Zsh configuration
home/modules/git/default.nix # Git configuration
home/modules/ssh/default.nix # SSH configuration
home/modules/tmux.nix # Tmux configuration
home/modules/packages.nix # Package declarations

1288
docs/nix-architecture.md Normal file

File diff suppressed because it is too large Load Diff

626
docs/usage.md Normal file
View File

@@ -0,0 +1,626 @@
# Usage Guide
This guide provides detailed instructions for using and maintaining your Nix Home Manager configuration.
## Table of Contents
1. [Initial Setup on a New Machine](#initial-setup-on-a-new-machine)
2. [Switching Between Profiles](#switching-between-profiles)
3. [Adding New Packages](#adding-new-packages)
4. [Adding New Configuration Modules](#adding-new-configuration-modules)
5. [Updating Flake Inputs](#updating-flake-inputs)
6. [Day-to-Day Operations](#day-to-day-operations)
7. [Troubleshooting](#troubleshooting)
---
## Initial Setup on a New Machine
### Step 1: Install Nix
```bash
# Install Nix with the official installer
curl -L https://nixos.org/nix/install | sh
# Follow the prompts and restart your terminal
# Or source the nix profile manually:
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
```
### Step 2: Enable Flakes
Flakes are an experimental feature that needs to be enabled:
```bash
mkdir -p ~/.config/nix
cat >> ~/.config/nix/nix.conf << EOF
experimental-features = nix-command flakes
EOF
```
### Step 3: Install Homebrew (macOS only)
Homebrew is required for GUI applications:
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH (for Apple Silicon Macs)
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
```
### Step 4: Install 1Password and Configure SSH Agent
1. Download and install [1Password](https://1password.com/downloads/mac/)
2. Sign in to your 1Password account
3. Enable SSH Agent:
- Open 1Password → Settings → Developer
- Enable "SSH Agent"
- Enable "Use the SSH agent"
4. Enable CLI integration:
- In the same Developer settings
- Enable "Integrate with 1Password CLI"
### Step 5: Clone the Repository
```bash
# Clone to ~/.dotfiles (recommended location)
git clone <repository-url> ~/.dotfiles
cd ~/.dotfiles
```
### Step 6: Build and Apply Configuration
For a **personal machine**:
```bash
# First-time build (creates darwin-rebuild command)
nix build .#darwinConfigurations.personal.system
# Apply the configuration
./result/sw/bin/darwin-rebuild switch --flake .#personal
```
For a **work machine**:
```bash
# First-time build
nix build .#darwinConfigurations.work.system
# Apply the configuration
./result/sw/bin/darwin-rebuild switch --flake .#work
```
### Step 7: Restart Your Shell
```bash
# Start a new shell to pick up all changes
exec zsh
```
### Step 8: Verify Installation
```bash
# Check that key tools are available
which starship # Should show nix store path
which atuin # Should show nix store path
which nvim # Should show nix store path
# Verify git configuration
git config --get user.email
git config --get user.signingkey
```
---
## Switching Between Profiles
### Switching from Personal to Work
If you need to reconfigure a machine from personal to work:
```bash
cd ~/.dotfiles
darwin-rebuild switch --flake .#work
```
**Note:** This will:
- Change git configuration (email, signing key)
- Update SSH hosts
- Remove personal-only Homebrew casks
- Disable personal-only features (like jellyfin-tui)
### Switching from Work to Personal
```bash
cd ~/.dotfiles
darwin-rebuild switch --flake .#personal
```
**Note:** This will:
- Change git configuration to personal settings
- Update SSH hosts
- Install personal Homebrew casks (darktable, signal, proton-*, steam)
- Enable personal features
### Temporary Profile Testing
To test a profile without fully switching:
```bash
# Build without applying
darwin-rebuild build --flake .#work
# Inspect what would change
ls -la result/
```
---
## Adding New Packages
### Adding CLI Tools via Nix (Recommended)
Edit [`modules/home/packages.nix`](../modules/home/packages.nix):
```nix
home.packages = with pkgs; [
# ... existing packages ...
# Add your new package
your-new-package
];
```
Then rebuild:
```bash
darwin-rebuild switch --flake .#personal # or .#work
```
#### Finding Package Names
```bash
# Search for packages
nix search nixpkgs your-package-name
# Or use the online search
# https://search.nixos.org/packages
```
### Adding GUI Applications via Homebrew
Edit [`modules/darwin/homebrew.nix`](../modules/darwin/homebrew.nix):
#### For All Machines (Shared)
```nix
casks = {
shared = [
# ... existing casks ...
"your-new-app"
];
};
```
#### For Personal Machine Only
```nix
casks = {
personal = [
# ... existing personal casks ...
"personal-only-app"
];
};
```
Then rebuild:
```bash
darwin-rebuild switch --flake .#personal
```
### Adding Homebrew Formulae (Non-Nix CLI tools)
For CLI tools that must come from Homebrew (e.g., from custom taps):
```nix
# In modules/darwin/homebrew.nix
brews = [
# ... existing brews ...
"tap-name/formula-name"
];
```
### Adding Homebrew Taps
```nix
# In modules/darwin/homebrew.nix
taps = [
# ... existing taps ...
"owner/repo"
];
```
---
## Adding New Configuration Modules
### Creating a New Home Manager Module
1. Create a new file in `modules/home/`:
```bash
touch modules/home/your-module.nix
```
2. Add the module structure:
```nix
# modules/home/your-module.nix
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.modules.yourModule;
in {
options.modules.yourModule = {
enable = mkEnableOption "Your module description";
# Add your options here
someSetting = mkOption {
type = types.str;
default = "default-value";
description = "Description of this setting";
};
};
config = mkIf cfg.enable {
# Your configuration here
programs.someProgram = {
enable = true;
# ...
};
};
}
```
3. Import the module in [`home/default.nix`](../home/default.nix):
```nix
imports = [
# ... existing imports ...
../modules/home/your-module.nix
];
```
4. Enable the module:
```nix
# In home/default.nix or profile-specific file
modules.yourModule = {
enable = true;
someSetting = "custom-value";
};
```
### Creating Profile-Specific Configuration
For settings that differ between personal and work:
1. Add options to your module with sensible defaults
2. Override in profile files:
```nix
# home/personal.nix
modules.yourModule = {
enable = true;
someSetting = "personal-value";
};
# home/work.nix
modules.yourModule = {
enable = true;
someSetting = "work-value";
};
```
### Adding Application Configuration Files
For apps without Home Manager modules, use `home.file`:
```nix
# In modules/home/apps.nix or a new module
home.file = {
".config/your-app/config.toml".text = ''
# Your config content
setting = "value"
'';
# Or copy from a file
".config/your-app/config.toml".source = ./files/your-app-config.toml;
};
```
---
## Updating Flake Inputs
### Update All Inputs
```bash
cd ~/.dotfiles
# Update all inputs to their latest versions
nix flake update
# Review changes
git diff flake.lock
# Apply the updates
darwin-rebuild switch --flake .#personal
```
### Update Specific Input
```bash
# Update only nixpkgs
nix flake lock --update-input nixpkgs
# Update only home-manager
nix flake lock --update-input home-manager
# Update only nix-darwin
nix flake lock --update-input nix-darwin
```
### Pin to Specific Version
Edit `flake.nix` to pin an input:
```nix
inputs = {
# Pin to specific commit
nixpkgs.url = "github:nixos/nixpkgs/abc123...";
# Pin to specific branch
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
};
```
### Check for Updates
```bash
# Show current input versions
nix flake metadata
# Show what would be updated
nix flake update --dry-run
```
---
## Day-to-Day Operations
### Rebuilding After Changes
```bash
cd ~/.dotfiles
# Make your changes to .nix files
vim modules/home/packages.nix
# Rebuild and switch
darwin-rebuild switch --flake .#personal
```
### Quick Rebuild Alias
Add to your shell configuration or use directly:
```bash
# Alias for quick rebuilds
alias rebuild="darwin-rebuild switch --flake ~/.dotfiles#personal"
alias rebuild-work="darwin-rebuild switch --flake ~/.dotfiles#work"
```
### Checking Configuration Validity
```bash
# Validate the flake
nix flake check
# Build without switching (dry run)
darwin-rebuild build --flake .#personal
```
### Viewing Generation History
```bash
# List all generations
darwin-rebuild --list-generations
# See what's in the current generation
ls -la /run/current-system
```
### Rolling Back
```bash
# Rollback to previous generation
darwin-rebuild --rollback
# Switch to specific generation
darwin-rebuild switch --generation 42
```
### Garbage Collection
```bash
# Remove old generations (keeps current)
nix-collect-garbage
# Remove all old generations
nix-collect-garbage -d
# Remove generations older than 30 days
nix-collect-garbage --delete-older-than 30d
```
### Development Shell
For working on this repository:
```bash
cd ~/.dotfiles
# Enter development shell with formatting tools
nix develop
# Format all Nix files
nixfmt **/*.nix
```
---
## Troubleshooting
### Common Issues
#### "experimental-features" Error
**Problem:** `error: experimental Nix feature 'flakes' is disabled`
**Solution:**
```bash
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
```
#### Homebrew Cask Installation Fails
**Problem:** A cask fails to install during rebuild
**Solution:**
```bash
# Update Homebrew
brew update
# Check for issues
brew doctor
# Try installing manually first
brew install --cask problematic-cask
# Then rebuild
darwin-rebuild switch --flake .#personal
```
#### SSH Key Not Found
**Problem:** Git operations fail with SSH key errors
**Solution:**
1. Ensure 1Password SSH agent is enabled
2. Check the key is in 1Password
3. Verify the public key file exists:
```bash
ls -la ~/.ssh/keys/
```
4. Test SSH connection:
```bash
ssh -T git@github.com
```
#### Build Fails with "attribute not found"
**Problem:** `error: attribute 'somePackage' missing`
**Solution:**
```bash
# Update flake inputs
nix flake update
# Search for correct package name
nix search nixpkgs package-name
```
#### Conflicting Files
**Problem:** `error: collision between ... and ...`
**Solution:**
1. Check if the file is managed by multiple sources
2. Remove manual file if it exists:
```bash
rm ~/.config/conflicting-file
```
3. Rebuild
### Debug Mode
For detailed error information:
```bash
# Build with trace
darwin-rebuild switch --flake .#personal --show-trace
# Even more verbose
darwin-rebuild switch --flake .#personal --show-trace --verbose
```
### Interactive Debugging
```bash
# Open Nix REPL with flake loaded
nix repl
:lf .
# Now you can inspect the configuration
darwinConfigurations.personal.config.home-manager.users.alice.home.packages
```
### Reset to Clean State
If things are badly broken:
```bash
# Remove result symlink
rm -f result
# Clean Nix store
nix-collect-garbage -d
# Remove home-manager generations
rm -rf ~/.local/state/home-manager
# Rebuild from scratch
nix build .#darwinConfigurations.personal.system
./result/sw/bin/darwin-rebuild switch --flake .#personal
```
### Getting Help
```bash
# Home Manager options
man home-configuration.nix
# nix-darwin options
man darwin-configuration.nix
# Search for options online
# https://home-manager-options.extranix.com/
# https://daiderd.com/nix-darwin/manual/
```
---
## Best Practices
1. **Commit changes before rebuilding** - Makes it easy to rollback
2. **Test builds before switching** - Use `darwin-rebuild build` first
3. **Update inputs regularly** - Keep packages up to date
4. **Use garbage collection** - Prevent disk space issues
5. **Document custom modules** - Add comments explaining purpose
6. **Keep secrets out of Nix** - Use 1Password or sops-nix for secrets