Overview
A complete dotfile management solution using chezmoi that enables seamless configuration synchronization across multiple machines and operating systems. Supports templating for machine-specific configurations, encrypted secrets, and one-command environment setup.
Problem
Managing configuration files across multiple machines is challenging:
- Manual synchronization is error-prone and time-consuming
- Platform differences (Windows/Linux/macOS) require different configurations
- Secrets management in dotfiles poses security risks
- Machine-specific settings make simple Git repos inadequate
- Setup time for new machines is lengthy and tedious
Solution
chezmoi provides a declarative approach to dotfile management:
- Version-controlled configurations with Git
- Template-based configs for cross-platform compatibility
- Encrypted secret storage
- Machine-specific customizations
- Idempotent apply operations
- One-command bootstrap process
Key Features
Cross-Platform Support
- Automatically detects OS and architecture
- Platform-specific templates (
.tmplfiles) - Conditional includes based on system properties
- Path handling for Windows vs Unix systems
Template System
- Go template syntax for dynamic configurations
- Variables for hostname, OS, architecture
- Custom data files for per-machine settings
- Conditional logic for environment-specific configs
Secret Management
- Encrypted files using age or gpg
- Secure password manager integration
- Environment variable substitution
- Automatic decryption on apply
State Management
- Tracks what files are managed
- Detects external modifications
- Interactive merge for conflicts
- Rollback capabilities
Architecture / Stack
Core Tool: chezmoi (written in Go)
Configuration Structure:
1~/.local/share/chezmoi/
2├── .chezmoi.toml.tmpl # Main config with machine data
3├── dot_gitconfig.tmpl # Git configuration
4├── dot_config/
5│ ├── nvim/
6│ │ └── init.lua
7│ ├── powershell/
8│ │ └── profile.ps1.tmpl
9│ └── starship.toml
10├── private_dot_ssh/
11│ └── encrypted_config # Encrypted SSH config
12└── run_once_install-packages.sh.tmpl
Managed Configurations:
- Shell configs (bash, zsh, PowerShell)
- Editor settings (Neovim, VS Code)
- Terminal emulator configs
- Git configuration
- SSH keys and config
- Development tool configs (Node, Python, Go)
Implementation Details
Template Examples
OS-specific paths:
1{{- if eq .chezmoi.os "windows" }}
2set-alias vim "C:\\Program Files\\Neovim\\bin\\nvim.exe"
3{{- else }}
4alias vim=nvim
5{{- end }}
Machine-specific configs:
1[user]
2 name = {{ .name | quote }}
3 email = {{ .email | quote }}
4{{- if .work }}
5 signingkey = {{ .work_gpg_key }}
6{{- end }}
Bootstrap Process
One-line install:
1sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply <github-username>Machine-specific data collected interactively
Templates applied based on OS/architecture
Secrets decrypted with password/key
Scripts executed for package installation
Configurations symlinked to home directory
What I Learned
- Templating is powerful: Go templates handle complex conditional logic elegantly
- Secrets should stay encrypted: Never commit plaintext secrets, even in private repos
- Idempotency matters: Configurations should be reapplied safely without side effects
- Documentation is crucial: Future you won’t remember the template syntax
- Start simple: Begin with a few critical configs and expand gradually
- Test on fresh systems: Bootstrap process should work on clean machines
Benefits Realized
- Setup time: New machine from bare to fully configured in < 15 minutes
- Consistency: Identical configurations across work laptop, personal desktop, and cloud VMs
- Security: SSH keys and API tokens never exposed in Git history
- Maintenance: Single source of truth for all configurations
- Experimentation: Easy to test config changes and rollback
Future Enhancements
- Integration with cloud secret managers (1Password, Bitwarden)
- Automated configuration testing in containers
- Machine role profiles (work, personal, server)
- Configuration generation from UI
- Team-shared base configurations
HISTTY