# Dotfile Management with chezmoi Complete guide to managing your dotfiles with chezmoi on this Gentoo workstation and across multiple machines. ## Table of Contents - [Overview](#overview) - [Quick Reference](#quick-reference) - [Daily Workflow](#daily-workflow) - [Adding New Tools](#adding-new-tools) - [Editing Existing Configs](#editing-existing-configs) - [Templates for Cross-Platform Configs](#templates-for-cross-platform-configs) - [Syncing Across Machines](#syncing-across-machines) - [Advanced Usage](#advanced-usage) - [Troubleshooting](#troubleshooting) --- ## Overview ### What is chezmoi? chezmoi is a cross-platform dotfile manager that allows you to: - Keep your dotfiles in a git repository - Sync configs across multiple machines (Gentoo, macOS, Ubuntu, etc.) - Use templates for machine-specific configurations - Manage secrets securely - Automate setup on new machines ### Current Setup **Dotfiles Repository**: `~/repository/git.hinrichs.dev/alexander/dotfiles` - This is your main git repository - Contains all your dotfiles and chezmoi configuration - Pushed to your Gitea server **Chezmoi Source Directory**: `~/.local/share/chezmoi` - Git clone of your dotfiles repository - Working directory for chezmoi - Where you make changes before applying them **Chezmoi Config**: `~/.config/chezmoi/chezmoi.yaml` - Generated from `.chezmoi.yaml.tmpl` - Contains your machine-specific values (name, email, work/personal, etc.) ### How It Works ``` ┌─────────────────────────────────────────────────┐ │ 1. Edit dotfiles in chezmoi source │ │ chezmoi edit ~/.zshrc │ │ (edits ~/.local/share/chezmoi/dot_zshrc) │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 2. Preview changes │ │ chezmoi diff │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 3. Apply to home directory │ │ chezmoi apply │ │ (copies to ~/.zshrc) │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 4. Commit and push │ │ chezmoi cd │ │ git add . && git commit && git push │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ 5. Pull on other machines │ │ chezmoi update │ └─────────────────────────────────────────────────┘ ``` --- ## Quick Reference | Task | Command | |------|---------| | Edit dotfile | `chezmoi edit ~/.zshrc` | | Preview changes | `chezmoi diff` | | Apply changes | `chezmoi apply` | | Add new file | `chezmoi add ~/.newfile` | | Go to source dir | `chezmoi cd` | | Update from git | `chezmoi update` | | List managed files | `chezmoi managed` | | Show status | `chezmoi status` | | View rendered template | `chezmoi cat ~/.zshrc` | --- ## Daily Workflow ### Scenario 1: Edit Existing Config **Goal**: Update your shell configuration ```bash # 1. Edit the file chezmoi edit ~/.zshrc # 2. Preview what will change chezmoi diff # 3. Apply the changes chezmoi apply # 4. Test the changes source ~/.zshrc # 5. If everything works, commit chezmoi cd git add dot_zshrc.tmpl # or dot_zshrc if not a template git commit -m "feat: add new shell alias" git push ``` ### Scenario 2: Update Neovim Config **Goal**: Modify Neovim configuration ```bash # 1. Edit the config chezmoi edit ~/.config/nvim/lua/alxndrhi/options.lua # 2. Preview chezmoi diff # 3. Apply chezmoi apply # 4. Test in neovim nvim # 5. Commit chezmoi cd git add dot_config/nvim/lua/alxndrhi/options.lua git commit -m "feat: update neovim tab settings" git push ``` ### Scenario 3: Pull Latest Changes **Goal**: Sync dotfiles from another machine ```bash # Pull and apply in one command chezmoi update # Or step by step: chezmoi cd git pull exit chezmoi apply # Restart affected services source ~/.zshrc # If shell config changed # or restart terminal ``` --- ## Adding New Tools When you install a new CLI tool or application with configuration files, here's how to add it to your dotfiles. ### Example: Adding a New Tool (e.g., 'alacritty') **Step 1: Install the tool** ```bash # Install via package manager sudo emerge -av x11-terms/alacritty ``` **Step 2: Create and test the configuration** ```bash # Create config directory mkdir -p ~/.config/alacritty # Create config file nvim ~/.config/alacritty/alacritty.toml # Test the tool alacritty --version alacritty # Launch and verify config works ``` **Step 3: Add configuration to chezmoi** ```bash # Add the config file chezmoi add ~/.config/alacritty/alacritty.toml # Or add entire directory chezmoi add --recursive ~/.config/alacritty ``` **What this does:** - Copies `~/.config/alacritty/` to `~/.local/share/chezmoi/dot_config/alacritty/` - File is now managed by chezmoi **Step 4: Verify it was added** ```bash # Check if file is managed chezmoi managed | grep alacritty # View the source file chezmoi cd ls -la dot_config/alacritty/ ``` **Step 5: Commit to git** ```bash chezmoi cd git add dot_config/alacritty/ git commit -m "feat: add alacritty terminal emulator configuration" git push ``` **Step 6: Test on another machine** ```bash # On another machine chezmoi update # Verify alacritty config is there ls -la ~/.config/alacritty/ ``` ### Adding Shell Scripts If you have custom scripts in `~/bin` or `~/.local/bin`: ```bash # Add entire directory chezmoi add --recursive ~/.local/bin # Or individual scripts chezmoi add ~/.local/bin/my-script.sh # Make sure they're executable chezmoi chattr +executable ~/.local/bin/my-script.sh # Commit chezmoi cd git add . git commit -m "feat: add custom shell scripts" git push ``` --- ## Editing Existing Configs ### Edit and Apply ```bash # Edit any managed file chezmoi edit ~/.gitconfig # This opens: ~/.local/share/chezmoi/dot_gitconfig.tmpl # (or dot_gitconfig if not a template) # After editing, preview changes chezmoi diff # Apply chezmoi apply # Test git config --list ``` ### Edit Multiple Files ```bash # Edit several files in your editor chezmoi edit ~/.zshrc ~/.gitconfig ~/.config/starship.toml # Preview all changes chezmoi diff # Apply all chezmoi apply # Commit all chezmoi cd git add . git commit -m "feat: update shell and git configs" git push ``` ### Edit Directly in Source Directory ```bash # Go to chezmoi source chezmoi cd # Edit files directly nvim dot_zshrc.tmpl nvim dot_config/nvim/init.lua # Preview from anywhere chezmoi diff # Apply from anywhere chezmoi apply # Commit git add . git commit -m "feat: update configs" git push ``` --- ## Templates for Cross-Platform Configs Some configs need to be different on different operating systems or machines. Use templates for this. ### Convert a File to Template ```bash # Make a file a template chezmoi chattr +template ~/.zshrc # This renames: dot_zshrc → dot_zshrc.tmpl ``` ### Template Syntax Templates use Go's `text/template` syntax: ```bash # OS detection {{ if eq .chezmoi.os "darwin" -}} # macOS-specific config export PATH="/opt/homebrew/bin:$PATH" {{- else if eq .chezmoi.os "linux" -}} # Linux-specific config export PATH="/usr/local/bin:$PATH" {{- end }} # Distribution detection {{ if eq .osid "linux-gentoo" -}} # Gentoo-specific config alias emerge-update="sudo emerge --sync && sudo emerge -uDNav @world" {{- else if eq .osid "linux-ubuntu" -}} # Ubuntu-specific config alias apt-update="sudo apt update && sudo apt upgrade" {{- end }} # Work vs Personal {{ if .work -}} # Work-specific config export COMPANY_DOMAIN="company.com" {{- else if .personal -}} # Personal config export PROJECTS_DIR="$HOME/repository" {{- end }} # Machine-specific {{ if eq .machine "gentoo-workstation" -}} # Workstation config export DISPLAY=:0 {{- else if eq .machine "macos-laptop" -}} # Laptop config {{- end }} ``` ### Available Template Variables ```bash # View all available data chezmoi data # Common variables: .chezmoi.os # darwin, linux, windows .chezmoi.osRelease.id # gentoo, ubuntu, arch .chezmoi.hostname # lenovo-thinkpad .osid # linux-gentoo, darwin, etc. .machine # gentoo-workstation, macos-laptop .work # true/false .personal # true/false .email # your@email.com .name # Your Name .features.desktop # true/false .features.development # true/false .features.docker # true/false ``` ### Example: Cross-Platform .zshrc ```bash # Edit the template chezmoi edit ~/.zshrc # Add OS-specific paths {{ if eq .chezmoi.os "darwin" -}} # macOS Homebrew export PATH="/opt/homebrew/bin:$PATH" # macOS-specific aliases alias update="brew update && brew upgrade" {{- else if eq .osid "linux-gentoo" -}} # Gentoo paths export PATH="/usr/local/bin:$HOME/.local/bin:$PATH" # Gentoo-specific aliases alias update="sudo emerge --sync && sudo emerge -uDNav @world" {{- end }} # Common config (works on all platforms) export EDITOR=nvim export VISUAL=nvim # Apply chezmoi apply # Test echo $PATH ``` ### View Rendered Template ```bash # See how template renders on this machine chezmoi cat ~/.zshrc # Test specific template expression chezmoi execute-template "{{ .chezmoi.os }}" chezmoi execute-template "{{ .osid }}" ``` --- ## Syncing Across Machines ### Setup on New Machine **One-line install** (if you have the bootstrap script): ```bash sh -c "$(curl -fsLS https://git.hinrichs.dev/alexander/dotfiles/raw/branch/main/install.sh)" ``` **Manual setup**: ```bash # 1. Install chezmoi # (see installation instructions for your OS) # 2. Initialize with your dotfiles repo chezmoi init https://git.hinrichs.dev/alexander/dotfiles.git # 3. Preview what will be applied chezmoi diff # 4. Apply dotfiles chezmoi apply # 5. Restart shell exec zsh ``` ### Keep Machines in Sync **On Machine A** (where you made changes): ```bash # Edit configs chezmoi edit ~/.zshrc # Apply chezmoi apply # Commit and push chezmoi cd git add . git commit -m "feat: update shell config" git push ``` **On Machine B** (pull the changes): ```bash # Pull and apply chezmoi update # Or step by step: chezmoi cd git pull exit chezmoi apply # Restart shell if needed exec zsh ``` --- ## Advanced Usage ### Ignore Files Per Machine Edit `.chezmoiignore` to exclude files on specific machines: ```bash chezmoi cd nvim .chezmoiignore # Example content: {{ if not .features.desktop -}} # Ignore desktop configs on servers .config/hypr/ .config/waybar/ {{- end }} {{ if eq .chezmoi.os "darwin" -}} # Ignore Linux-specific configs on macOS .config/systemd/ {{- end }} ``` ### Run Scripts on Apply Create scripts that run when applying dotfiles: ```bash chezmoi cd nvim .chezmoiscripts/run_once_after_setup-tool.sh #!/bin/sh # Install tool if not present if ! command -v tool >/dev/null 2>&1; then echo "Installing tool..." # Installation commands fi ``` Script naming: - `run_once_*` - Runs once (tracked by hash) - `run_onchange_*` - Runs when script content changes - `run_before_*` - Runs before applying - `run_after_*` - Runs after applying ### Encrypt Sensitive Files ```bash # Add encrypted file chezmoi add --encrypt ~/.ssh/id_rsa # chezmoi uses age or gpg for encryption ``` ### Dry Run / Testing ```bash # See what would change without applying chezmoi apply --dry-run --verbose # Test on a VM before applying to main machine ``` --- ## Troubleshooting ### Warning: Config File Template Changed **Error**: `chezmoi: warning: config file template has changed` **Solution**: ```bash chezmoi init # Answer prompts for name, email, work/personal ``` ### Diff Shows Too Much / Opens vim The default diff tool is `nvim -d`. To use built-in diff: ```bash # Use built-in diff (easier to read) chezmoi diff --use-builtin-diff # Or use it with pager chezmoi diff --use-builtin-diff | less ``` ### File Conflicts **Error**: File already exists and differs **Solution**: ```bash # Merge manually chezmoi merge ~/.zshrc # Or force overwrite chezmoi apply --force # Or remove from management and re-add chezmoi forget ~/.zshrc # Fix the file manually chezmoi add ~/.zshrc ``` ### Template Errors **Error**: Template syntax error **Solution**: ```bash # View raw template chezmoi cd cat dot_zshrc.tmpl # Check template syntax chezmoi cat ~/.zshrc # Test specific expression chezmoi execute-template "{{ .chezmoi.os }}" ``` ### Reset Everything ```bash # Remove all managed files (DESTRUCTIVE!) chezmoi purge # Start fresh chezmoi init https://git.hinrichs.dev/alexander/dotfiles.git chezmoi apply ``` ### Re-run Installation Scripts ```bash # Reset script state (scripts will run again) chezmoi state reset --bucket=scriptState # Re-apply chezmoi apply ``` ### Check Configuration ```bash # View chezmoi data chezmoi data | less # View config file cat ~/.config/chezmoi/chezmoi.yaml # Edit config chezmoi edit-config ``` --- ## Common Patterns ### Pattern 1: Update Tool on All Machines ```bash # On your main machine chezmoi edit ~/.config/tool/config chezmoi apply chezmoi cd git add . && git commit -m "feat: update tool config" && git push # On other machines chezmoi update ``` ### Pattern 2: Add New Tool ```bash # Install and configure sudo emerge tool nvim ~/.config/tool/config # Add to chezmoi chezmoi add --recursive ~/.config/tool chezmoi cd git add . && git commit -m "feat: add tool configuration" && git push ``` ### Pattern 3: Machine-Specific Config ```bash # Edit template chezmoi edit ~/.zshrc # Add machine-specific logic {{ if eq .machine "gentoo-workstation" -}} # Workstation-only config {{- end }} # Apply and commit chezmoi apply chezmoi cd && git add . && git commit -m "feat: add workstation config" && git push ``` ### Pattern 4: Temporarily Disable Chezmoi ```bash # Edit file directly (bypassing chezmoi) nvim ~/.zshrc # Test changes source ~/.zshrc # If good, update chezmoi chezmoi add ~/.zshrc chezmoi cd && git add . && git commit -m "feat: update zshrc" && git push ``` --- ## Best Practices 1. **Always preview before applying** ```bash chezmoi diff # Check what will change chezmoi apply # Then apply ``` 2. **Test changes before committing** ```bash chezmoi apply # Test the changes # If broken, fix and re-apply # Only commit when working ``` 3. **Use templates for cross-platform configs** - OS-specific paths - Package manager commands - Tool locations 4. **Keep commits atomic and descriptive** ```bash # Good git commit -m "feat: add starship prompt configuration" # Bad git commit -m "update stuff" ``` 5. **Document complex templates** ```bash # Add comments in templates # {{ if eq .chezmoi.os "darwin" -}} # macOS uses Homebrew in /opt/homebrew export PATH="/opt/homebrew/bin:$PATH" # {{- end }} ``` 6. **Don't commit secrets** - Use `.chezmoiignore` for sensitive files - Or use encryption for files that must be synced 7. **Test on a VM before deploying widely** - Especially for major changes - Prevents breaking all machines at once --- ## Resources - **Official chezmoi docs**: https://www.chezmoi.io/ - **Dotfiles repository**: `~/repository/git.hinrichs.dev/alexander/dotfiles` - **This system's USER-GUIDE.md**: Quick reference for chezmoi commands - **chezmoi GitHub**: https://github.com/twpayne/chezmoi --- ## Summary **Daily workflow:** 1. `chezmoi edit ~/.config` - Edit configs 2. `chezmoi diff` - Preview changes 3. `chezmoi apply` - Apply changes 4. `chezmoi cd && git add . && git commit && git push` - Commit 5. `chezmoi update` on other machines - Sync **Adding new tools:** 1. Install and configure the tool 2. `chezmoi add ~/.config/tool` - Add to chezmoi 3. Commit and push **Cross-platform:** 1. `chezmoi chattr +template ~/.file` - Make template 2. Add `{{ if eq .chezmoi.os "..." }}` logic 3. Apply and test on each platform Your dotfiles are now version controlled, synced across machines, and managed professionally!