Managing Dotfiles Like a Pro with chezmoi: A Complete Guide

If you work on multiple machines or frequently set up new development environments, you know the pain of manually copying configuration files. chezmoi is a powerful dotfile manager that solves this problem elegantly, allowing you to manage your dotfiles securely across different machines.

What Are Dotfiles?

Dotfiles are configuration files in Unix-like systems that start with a dot (.), making them hidden by default. Common examples include:

  • .bashrc / .zshrc – Shell configuration
  • .gitconfig – Git settings
  • .vimrc / .config/nvim/init.lua – Editor configuration
  • .ssh/config – SSH client configuration
  • .tmux.conf – Terminal multiplexer settings

Why chezmoi?

While there are many dotfile managers (GNU Stow, yadm, dotbot), chezmoi stands out for several reasons:

  1. Security – Built-in support for secrets management with tools like 1Password, Bitwarden, or age encryption
  2. Templates – Use Go templates for machine-specific configurations
  3. Cross-platform – Works on Linux, macOS, and Windows
  4. Version control – Git integration out of the box
  5. Declarative – Define your desired state, chezmoi handles the rest

Installation

macOS (Homebrew)

brew install chezmoi

Linux (various methods)

# Using snap
sudo snap install chezmoi --classic

# Using curl (installs to ~/bin)
sh -c "$(curl -fsLS get.chezmoi.io)"

# Arch Linux
sudo pacman -S chezmoi

Windows

winget install twpayne.chezmoi
# or
choco install chezmoi

Getting Started

Initialize chezmoi

Create a new chezmoi repository:

chezmoi init

This creates a source directory at ~/.local/share/chezmoi where your dotfiles will be stored.

Add Your First Dotfile

chezmoi add ~/.zshrc

This copies .zshrc to the chezmoi source directory. The file is stored as dot_zshrc (chezmoi uses this naming convention for files starting with a dot).

Edit Files

Edit files in the source directory:

chezmoi edit ~/.zshrc

Or open the entire source directory in your editor:

chezmoi cd

Preview Changes

Before applying changes, see what would happen:

chezmoi diff

Apply Changes

Apply your dotfiles to your home directory:

chezmoi apply

Using Templates for Machine-Specific Config

One of chezmoi’s killer features is templating. Create machine-specific configurations using Go templates.

Example: Different Git Email per Machine

First, add your gitconfig as a template:

chezmoi add --template ~/.gitconfig

Then edit it:

chezmoi edit ~/.gitconfig
[user]
    name = Kim Nis Neuhauss
{{- if eq .chezmoi.hostname "work-laptop" }}
    email = [email protected]
{{- else }}
    email = [email protected]
{{- end }}

[core]
    editor = nvim

Using chezmoi Data

Define custom data in ~/.config/chezmoi/chezmoi.toml:

[data]
    name = "Kim Nis Neuhauss"
    email = "[email protected]"
    editor = "nvim"

Then use it in templates:

# In your .gitconfig.tmpl
[user]
    name = {{ .name }}
    email = {{ .email }}

Managing Secrets Securely

chezmoi integrates with popular secret managers to keep sensitive data out of your Git repository.

Using 1Password

# In your template
{{ onepasswordRead "op://Personal/SSH Key/private key" }}

Using Bitwarden

{{ (bitwarden "item" "github-token").login.password }}

Using age Encryption

For standalone encryption without external tools:

# Generate an age key
age-keygen -o ~/.config/chezmoi/key.txt

# Configure chezmoi to use it
chezmoi edit-config
encryption = "age"
[age]
    identity = "~/.config/chezmoi/key.txt"
    recipient = "age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Add encrypted files:

chezmoi add --encrypt ~/.ssh/id_ed25519

Syncing Across Machines

Push to Git

chezmoi cd
git add .
git commit -m "Update dotfiles"
git push

Set Up a New Machine

On a fresh machine, initialize chezmoi with your repository:

chezmoi init --apply https://github.com/yourusername/dotfiles.git

The --apply flag immediately applies the dotfiles after cloning.

Keeping in Sync

Pull and apply updates:

chezmoi update

Or just preview what would change:

chezmoi update --dry-run

Advanced Features

Run Scripts

Execute scripts during apply. Create files like run_once_install-packages.sh:

#!/bin/bash
# run_once_install-packages.sh

# This runs only once per machine
if command -v brew &> /dev/null; then
    brew install ripgrep fd fzf
fi

Script prefixes:

  • run_ – Run every time
  • run_once_ – Run only once (tracked by checksum)
  • run_onchange_ – Run when content changes

External Files

Fetch files from URLs:

# .chezmoiexternal.toml
[".oh-my-zsh"]
    type = "archive"
    url = "https://github.com/ohmyzsh/ohmyzsh/archive/master.tar.gz"
    exact = true
    stripComponents = 1

Ignore Files per Machine

Create .chezmoiignore:

# Ignore on Linux
{{ if ne .chezmoi.os "linux" }}
.config/i3/
{{ end }}

# Ignore on work machines
{{ if eq .chezmoi.hostname "work-laptop" }}
.config/personal/
{{ end }}
  1. Start simple – Begin by adding your most important configs (shell, git, editor)
  2. Use templates sparingly – Only template files that actually differ between machines
  3. Encrypt secrets – Never commit plain-text secrets to Git
  4. Document your setup – Add a README to your dotfiles repo
  5. Test on fresh installs – Periodically test your setup in a VM or container

Common Commands Reference

CommandDescription
chezmoi initInitialize chezmoi
chezmoi add <file>Add a file to chezmoi
chezmoi edit <file>Edit a file in source
chezmoi diffShow pending changes
chezmoi applyApply changes
chezmoi updatePull and apply from Git
chezmoi cdOpen source directory
chezmoi dataShow template data
chezmoi doctorCheck for problems

Conclusion

chezmoi transforms dotfile management from a tedious chore into a streamlined workflow. With features like templating, secret management, and cross-platform support, it’s the ideal tool for developers and sysadmins who work across multiple machines.

Start small, add your configs incrementally, and you’ll never have to manually copy dotfiles again.

Further Reading