17 KiB
Dotfile Management with chezmoi
Complete guide to managing your dotfiles with chezmoi on this Gentoo workstation and across multiple machines.
Table of Contents
- Overview
- Quick Reference
- Daily Workflow
- Adding New Tools
- Editing Existing Configs
- Templates for Cross-Platform Configs
- Syncing Across Machines
- Advanced Usage
- 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
# 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
# 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
# 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
# Install via package manager
sudo emerge -av x11-terms/alacritty
Step 2: Create and test the configuration
# 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
# 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
# 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
chezmoi cd
git add dot_config/alacritty/
git commit -m "feat: add alacritty terminal emulator configuration"
git push
Step 6: Test on another machine
# 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:
# 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
# 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
# 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
# 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
# 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:
# 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
# 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
# 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
# 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):
sh -c "$(curl -fsLS https://git.hinrichs.dev/alexander/dotfiles/raw/branch/main/install.sh)"
Manual setup:
# 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):
# 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):
# 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:
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:
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 changesrun_before_*- Runs before applyingrun_after_*- Runs after applying
Encrypt Sensitive Files
# Add encrypted file
chezmoi add --encrypt ~/.ssh/id_rsa
# chezmoi uses age or gpg for encryption
Dry Run / Testing
# 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:
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:
# 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:
# 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:
# 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
# Remove all managed files (DESTRUCTIVE!)
chezmoi purge
# Start fresh
chezmoi init https://git.hinrichs.dev/alexander/dotfiles.git
chezmoi apply
Re-run Installation Scripts
# Reset script state (scripts will run again)
chezmoi state reset --bucket=scriptState
# Re-apply
chezmoi apply
Check Configuration
# 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
# 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
# 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
# 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
# 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
-
Always preview before applying
chezmoi diff # Check what will change chezmoi apply # Then apply -
Test changes before committing
chezmoi apply # Test the changes # If broken, fix and re-apply # Only commit when working -
Use templates for cross-platform configs
- OS-specific paths
- Package manager commands
- Tool locations
-
Keep commits atomic and descriptive
# Good git commit -m "feat: add starship prompt configuration" # Bad git commit -m "update stuff" -
Document complex templates
# Add comments in templates # {{ if eq .chezmoi.os "darwin" -}} # macOS uses Homebrew in /opt/homebrew export PATH="/opt/homebrew/bin:$PATH" # {{- end }} -
Don't commit secrets
- Use
.chezmoiignorefor sensitive files - Or use encryption for files that must be synced
- Use
-
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:
chezmoi edit ~/.config- Edit configschezmoi diff- Preview changeschezmoi apply- Apply changeschezmoi cd && git add . && git commit && git push- Commitchezmoi updateon other machines - Sync
Adding new tools:
- Install and configure the tool
chezmoi add ~/.config/tool- Add to chezmoi- Commit and push
Cross-platform:
chezmoi chattr +template ~/.file- Make template- Add
{{ if eq .chezmoi.os "..." }}logic - Apply and test on each platform
Your dotfiles are now version controlled, synced across machines, and managed professionally!