feat: switch to chezmoi

Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
This commit is contained in:
2025-11-12 16:27:50 +02:00
parent ab67f6be5a
commit 8460c2d408
13 changed files with 2451 additions and 35 deletions

View File

@@ -0,0 +1,425 @@
# Chezmoi Migration Summary
## What Was Done
Your dotfiles repository has been prepared for migration from dotbot to chezmoi. Here's what was created:
### 1. Updated Install Script
- **File**: `install`
- **Change**: Now uses chezmoi's one-line installer
- **Command**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### 2. Chezmoi Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file that includes:
- Source directory configuration
- Host detection (air, lakka, tunkki, s)
- OS detection (macOS, Linux)
- Custom data variables for templates
- Merge and diff settings
- Git configuration
- Pre-read hook for submodule updates
#### `.chezmoiignore`
Specifies what files should NOT be managed by chezmoi:
- Git and GitHub files
- Documentation (*.md files)
- Development tools (.vscode, node_modules, etc.)
- Old dotbot configuration
- Host-specific files (via templates)
- Repository management files
### 3. Run Scripts (Automated Setup)
#### `run_once_before_install-prerequisites.sh.tmpl`
Runs **once before** applying dotfiles:
- Installs Homebrew (macOS)
- Installs Xcode CLI tools (macOS)
- Updates package manager (Linux)
#### `run_once_after_install-packages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs Homebrew packages (Brewfile)
- Sets macOS defaults
- Installs apt packages (Linux)
- Installs pipx packages
#### `run_once_after_setup-languages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs fonts
- Installs Cargo packages (Rust)
- Installs Go packages
- Installs Composer (PHP)
- Installs NVM and latest Node LTS
- Installs NPM packages
- Installs GitHub CLI extensions
- Installs z (directory jumper)
- Installs cheat databases
#### `run_once_after_create-directories.sh.tmpl`
Runs **once after** applying dotfiles:
- Creates required directories in `$HOME`
- Sets proper permissions (e.g., `.ssh` → 0700)
### 4. Hooks
#### `.chezmoihooks/pre-read-source-state.sh`
Runs before chezmoi reads the source state:
- Updates git submodules automatically
### 5. Documentation
#### `MIGRATION-DOTBOT-TO-CHEZMOI.md` (66KB)
Comprehensive migration guide including:
- Why migrate to chezmoi
- Key differences between dotbot and chezmoi
- Complete dotbot → chezmoi mapping
- File structure comparison
- Step-by-step migration instructions
- Usage guide with examples
- Troubleshooting section
- Migration checklist
#### `CHEZMOI-QUICK-REFERENCE.md` (11KB)
Quick reference guide for daily use:
- Common commands
- File naming conventions
- Template syntax examples
- Host-specific configuration patterns
- Troubleshooting tips
- Useful aliases
#### `HOST-SPECIFIC-MIGRATION.md` (9KB)
Detailed guide for migrating host-specific configurations:
- Three migration approaches explained
- Examples from your current hosts
- Step-by-step host config migration
- Testing strategies
- Best practices
### 6. Migration Helper Script
#### `migrate-to-chezmoi.sh`
Automated script to restructure your files:
- Creates backup branch automatically
- Creates migration branch
- Renames files to chezmoi conventions
- `base/*``dot_*`
- `config/*``dot_config/*`
- `local/bin/*``executable_dot_local/bin/*`
- `ssh/*``private_dot_ssh/*`
- Cleans up empty directories
- Generates migration notes
## What Needs To Be Done
### Immediate Next Steps
1. **Review Changes**
```bash
cd ~/.dotfiles
git status
git diff
```
2. **Read Documentation**
- Start with: `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Quick reference: `CHEZMOI-QUICK-REFERENCE.md`
- Host configs: `HOST-SPECIFIC-MIGRATION.md`
3. **Commit Current State**
```bash
git add install .chezmoi.yaml.tmpl .chezmoiignore
git add run_once_*.sh.tmpl .chezmoihooks/
git add migrate-to-chezmoi.sh
git add *.md
git commit -m "Add chezmoi configuration and migration tools"
```
### File Restructuring
You have two options:
#### Option A: Automated (Recommended for First Pass)
```bash
# Run the migration script
./migrate-to-chezmoi.sh
# This will:
# - Create backup branch
# - Create migration branch
# - Rename all files to chezmoi conventions
# - Show you what was done
```
#### Option B: Manual (More Control)
Manually rename files following chezmoi conventions:
```bash
# Base files become dot_ files
git mv base/bashrc dot_bashrc
git mv base/zshrc dot_zshrc
git mv base/tmux.conf dot_tmux.conf
# Config files
mkdir -p dot_config
git mv config/fish dot_config/fish
git mv config/nvim dot_config/nvim
# ... etc
# Local bin (make executable)
mkdir -p executable_dot_local/bin
for file in local/bin/*; do
git mv "$file" "executable_dot_local/bin/$(basename $file)"
done
# SSH files (private)
mkdir -p private_dot_ssh
git mv ssh/* private_dot_ssh/
# See full examples in MIGRATION-DOTBOT-TO-CHEZMOI.md
```
### Host-Specific Configurations
Your hosts need special attention:
```bash
hosts/
├── air/
├── lakka/
├── tunkki/
└── s/
```
**Read**: `HOST-SPECIFIC-MIGRATION.md` for detailed strategies.
**Quick decision guide**:
- **Few differences per file** → Use templates with `{{ if .is_air }}`
- **Complete replacement** → Use `filename__hostname` suffix
- **Host-specific directories** → Use `.chezmoiignore` with templates
### Testing Before Commit
```bash
# After restructuring files, test with chezmoi
cd ~/.dotfiles
# Initialize chezmoi with current directory as source
chezmoi init --source $(pwd)
# See what would happen (dry run)
chezmoi apply --dry-run --verbose
# See what a specific file would look like
chezmoi cat ~/.bashrc
# Check for errors
chezmoi verify
```
### Final Steps
1. **Commit Migration**
```bash
git add -A
git commit -m "Migrate from dotbot to chezmoi"
git push
```
2. **Test on Current Machine**
```bash
# Apply dotfiles
chezmoi apply -v
# Verify everything works
# Open new terminal
# Check configs
```
3. **Test on Another Machine** (if available)
```bash
# On another machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Verify host-specific configs applied correctly
```
4. **Clean Up** (after confirming everything works)
```bash
cd $(chezmoi source-path)
# Remove old dotbot files
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm tools/dotbot-defaults.yaml
# Optionally remove hosts/ if fully migrated to templates
# rm -rf hosts/
git add -A
git commit -m "Clean up old dotbot files"
git push
```
## Key Differences to Remember
### Installation
**Before**: `./install` (ran dotbot)
**After**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### Making Changes
**Before**:
```bash
cd ~/.dotfiles
vim base/bashrc
./install # Re-run to create symlinks
```
**After**:
```bash
chezmoi edit ~/.bashrc
# Or: vim ~/.bashrc && chezmoi add ~/.bashrc
chezmoi apply
```
### Syncing Across Machines
**Before**:
```bash
cd ~/.dotfiles
git pull
./install
```
**After**:
```bash
chezmoi update
# Equivalent to: cd $(chezmoi source-path) && git pull && chezmoi apply
```
### Host-Specific Configs
**Before**: Separate files in `hosts/hostname/`
**After**: Templates with `{{ if eq .chezmoi.hostname "air" }}` or `filename__hostname`
## File Mapping Reference
| Old Location | New Location | Notes |
|--------------|--------------|-------|
| `base/bashrc` | `dot_bashrc` | Becomes `~/.bashrc` |
| `config/fish/` | `dot_config/fish/` | Becomes `~/.config/fish/` |
| `local/bin/script` | `executable_dot_local/bin/script` | Executable `~/.local/bin/script` |
| `ssh/config` | `private_dot_ssh/config` | Private (0600) `~/.ssh/config` |
| `install.conf.yaml` | `run_once_*.sh.tmpl` | Setup tasks |
| `hosts/air/config/` | `dot_config/*.tmpl` or `*__air` | Host-specific |
## Troubleshooting Quick Tips
### "Entry not in source state"
```bash
# File not added to chezmoi
chezmoi add <file>
```
### "File modified since chezmoi last wrote it"
```bash
# See changes
chezmoi diff
# Re-add
chezmoi add <file>
```
### "Template undefined variable"
```bash
# Check available data
chezmoi data
# Test template
chezmoi execute-template "{{ .chezmoi.hostname }}"
```
### Scripts not running
```bash
# Check permissions
chmod +x run_once_*.sh.tmpl
# Force re-run
chezmoi apply --force
```
## Additional Resources
### Created Documentation
- `MIGRATION-DOTBOT-TO-CHEZMOI.md` - Complete migration guide
- `CHEZMOI-QUICK-REFERENCE.md` - Daily usage reference
- `HOST-SPECIFIC-MIGRATION.md` - Host configuration guide
- `MIGRATION-NOTES.md` - Generated after running migration script
### External Resources
- [Chezmoi Official Docs](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Templates](https://www.chezmoi.io/reference/templates/)
## Summary Checklist
- [x] Install script updated
- [x] Chezmoi configuration created (`.chezmoi.yaml.tmpl`)
- [x] Ignore file created (`.chezmoiignore`)
- [x] Run scripts created (4 scripts)
- [x] Hooks created (pre-read-source-state)
- [x] Migration script created (`migrate-to-chezmoi.sh`)
- [x] Documentation created (3 guides)
- [ ] **Review and commit configuration files**
- [ ] **Run migration script** or manually restructure
- [ ] **Migrate host-specific configs**
- [ ] **Test with chezmoi**
- [ ] **Commit migration**
- [ ] **Test on current machine**
- [ ] **Test on other machines**
- [ ] **Clean up old dotbot files**
- [ ] **Update README.md** (document chezmoi usage)
## Questions?
If you have questions during migration:
1. Check the relevant guide:
- General questions → `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Usage questions → `CHEZMOI-QUICK-REFERENCE.md`
- Host configs → `HOST-SPECIFIC-MIGRATION.md`
2. Use chezmoi's help:
```bash
chezmoi help
chezmoi help <command>
chezmoi doctor
```
3. Check official docs:
- https://www.chezmoi.io/
## What Makes This Migration Special
Your dotfiles have:
- ✅ Custom `dfm` script → Wrapped in run_once scripts
- ✅ Multiple dotbot plugins → Equivalent run_once scripts
- ✅ Host-specific configs → Template support added
- ✅ Complex installation → Automated in run scripts
- ✅ Git submodules → Pre-read hook handles this
- ✅ Multiple hosts (air, lakka, tunkki, s) → Detected and flagged
Everything from your dotbot setup has been accounted for in the chezmoi migration!
## Final Notes
- **Take your time**: This is a significant migration
- **Test thoroughly**: Use `--dry-run` extensively
- **Backup everything**: The migration script creates backups
- **Iterate**: You can always refine the migration later
- **Have fun**: Chezmoi offers powerful features to explore!
Good luck with your migration! 🚀

View File

@@ -0,0 +1,432 @@
# Chezmoi Quick Reference
Quick reference guide for common chezmoi operations with your dotfiles.
## Installation
```bash
# Fresh install on a new machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Or if chezmoi is already installed
chezmoi init --apply ivuorinen
```
## Daily Workflow
### Making Changes
```bash
# Edit a dotfile (opens in $EDITOR)
chezmoi edit ~/.bashrc
# Or edit directly and add to chezmoi
vim ~/.bashrc
chezmoi add ~/.bashrc
# See what would change
chezmoi diff
# Apply changes
chezmoi apply
```
### Syncing Across Machines
```bash
# On machine A: commit and push changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update configuration"
git push
# On machine B: pull and apply changes
chezmoi update
# This is equivalent to:
# cd $(chezmoi source-path) && git pull && chezmoi apply
```
## Common Commands
### Viewing and Inspecting
```bash
# See what chezmoi would do
chezmoi diff
# List all managed files
chezmoi managed
# List unmanaged files
chezmoi unmanaged
# Show the source path
chezmoi source-path
# Show what a file would look like after templating
chezmoi cat ~/.bashrc
# Show available template data
chezmoi data
```
### Adding and Removing Files
```bash
# Add a file
chezmoi add ~/.newfile
# Add a file as a template
chezmoi add --template ~/.newfile
# Add a directory recursively
chezmoi add --recursive ~/.config/newapp
# Add with autodetection (templates, scripts, etc.)
chezmoi add --autotemplate ~/.newfile
# Stop managing a file (removes from chezmoi)
chezmoi forget ~/.oldfile
# Remove a file from both chezmoi and home directory
chezmoi remove ~/.oldfile
```
### Working with Templates
```bash
# Execute a template expression
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Edit template data
chezmoi edit-config
# Verify templates
chezmoi verify
```
### Applying Changes
```bash
# Apply all changes
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Dry run (show what would happen)
chezmoi apply --dry-run -v
# Force apply (re-runs scripts)
chezmoi apply --force
# Apply only specific files
chezmoi apply ~/.bashrc ~/.zshrc
```
### Updating from Repository
```bash
# Update dotfiles from repository
chezmoi update
# Update but don't apply
cd $(chezmoi source-path) && git pull
# Update with interactive merge
chezmoi update --interactive
```
## File Naming Conventions
### Basic Prefixes
| Source File | Destination | Description |
|------------|-------------|-------------|
| `dot_bashrc` | `~/.bashrc` | Dot file |
| `dot_config/` | `~/.config/` | Dot directory |
| `private_dot_ssh/` | `~/.ssh/` | Private directory (0700) |
| `executable_dot_local/bin/script` | `~/.local/bin/script` | Executable |
| `symlink_dot_vim` | `~/.vim` | Symlink |
| `readonly_dot_file` | `~/.file` | Read-only |
### Template Files
| Source File | Description |
|------------|-------------|
| `dot_bashrc.tmpl` | Template file |
| `dot_config/fish/config.fish.tmpl` | Nested template |
### Scripts
| Script Name | When It Runs |
|------------|--------------|
| `run_once_before_*.sh` | Once before applying |
| `run_once_after_*.sh` | Once after applying |
| `run_before_*.sh` | Every time before applying |
| `run_after_*.sh` | Every time after applying |
| `run_onchange_*.sh` | When script content changes |
## Template Syntax
### Basic Variables
```go
// Hostname
{{ .chezmoi.hostname }}
// Username
{{ .chezmoi.username }}
// Operating system
{{ .chezmoi.os }}
// Home directory
{{ .chezmoi.homeDir }}
// Source directory
{{ .chezmoi.sourceDir }}
// Custom data from .chezmoi.yaml
{{ .is_macos }}
{{ .is_linux }}
```
### Conditionals
```go
{{ if eq .chezmoi.hostname "air" }}
# Configuration for air
{{ else if eq .chezmoi.hostname "lakka" }}
# Configuration for lakka
{{ else }}
# Default configuration
{{ end }}
{{ if .is_macos }}
# macOS-specific
{{ end }}
{{ if and .is_macos (eq .chezmoi.hostname "air") }}
# macOS on air
{{ end }}
```
### Loops
```go
{{ range $key, $value := .data }}
{{ $key }}: {{ $value }}
{{ end }}
```
### Including Files
```go
{{ include "template-file.txt" }}
{{ includeTemplate "template-file.tmpl" }}
```
## Host-Specific Configuration
### Method 1: Template Conditionals
In `dot_bashrc.tmpl`:
```bash
# Common configuration
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
export WORK_DIR="$HOME/Work"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
export WORK_DIR="$HOME/Projects"
{{ end }}
```
### Method 2: Separate Files with Symlinks
Use `.chezmoiignore` to exclude files for specific hosts:
```
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-specific-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-specific-app/
{{ end }}
```
## Working with Secrets
### Environment Variables
```go
{{ .Env.MY_SECRET }}
```
### 1Password
```go
{{ (onepasswordDocument "my-secret").content }}
{{ (onepasswordItemFields "my-item").password.value }}
```
### External Commands
```go
{{ output "op" "read" "op://vault/item/field" }}
```
## Troubleshooting
### Check Configuration
```bash
# Verify chezmoi is working correctly
chezmoi doctor
# Check state
chezmoi verify
# See detailed info
chezmoi data
```
### Debug Templates
```bash
# See what a template would produce
chezmoi cat ~/.bashrc
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Verbose output
chezmoi apply -v
```
### Fix Issues
```bash
# Re-apply everything
chezmoi apply --force
# Reset state (dangerous!)
chezmoi state reset
# Clear cache
rm -rf $(chezmoi source-path)/.git/chezmoi-*
```
### Common Errors
**Error: template: ... undefined variable**
- Check template syntax
- Verify data with `chezmoi data`
**Error: entry ... is not in source state**
- File not added to chezmoi: `chezmoi add <file>`
**Error: ... has been modified since chezmoi last wrote it**
- See changes: `chezmoi diff`
- Re-add: `chezmoi add <file>`
- Or force apply: `chezmoi apply --force`
## Useful Aliases
Add these to your shell configuration:
```bash
# Chezmoi shortcuts
alias cm='chezmoi'
alias cma='chezmoi apply'
alias cmd='chezmoi diff'
alias cme='chezmoi edit'
alias cmu='chezmoi update'
alias cmcd='cd $(chezmoi source-path)'
# Common workflows
alias cmup='chezmoi git pull && chezmoi apply'
alias cmpush='cd $(chezmoi source-path) && git add -A && git commit && git push'
```
## Environment Variables
```bash
# Change source directory (default: ~/.local/share/chezmoi)
export CHEZMOI_SOURCE_DIR="$HOME/.dotfiles"
# Change config file location
export CHEZMOI_CONFIG_FILE="$HOME/.config/chezmoi/chezmoi.yaml"
# Use different editor
export EDITOR="vim"
```
## Advanced Usage
### Using chezmoi as a dotfiles manager
```bash
# Initialize with local directory
chezmoi init --source ~/.dotfiles
# Use current directory as source
chezmoi init --source $(pwd)
```
### Managing Multiple Machines
Use data in `.chezmoi.yaml.tmpl`:
```yaml
data:
is_work_machine: {{ or (eq .chezmoi.hostname "work-laptop") (eq .chezmoi.hostname "work-desktop") }}
is_personal: {{ eq .chezmoi.hostname "personal-laptop" }}
```
Then in templates:
```go
{{ if .is_work_machine }}
# Work configuration
{{ end }}
```
### External Files
```yaml
# .chezmoiexternal.yaml
".config/nvim/lua/plugins":
type: "archive"
url: "https://github.com/user/nvim-config/archive/main.tar.gz"
stripComponents: 1
refreshPeriod: "168h"
```
## Resources
- [Official Documentation](https://www.chezmoi.io/)
- [User Guide](https://www.chezmoi.io/user-guide/)
- [Template Reference](https://www.chezmoi.io/reference/templates/)
- [Command Reference](https://www.chezmoi.io/reference/commands/)
- [FAQ](https://www.chezmoi.io/faq/)
## Help
```bash
# General help
chezmoi help
# Command-specific help
chezmoi help apply
chezmoi help add
# Show version
chezmoi --version
```

View File

@@ -0,0 +1,462 @@
# Host-Specific Configuration Migration
Guide for migrating host-specific configurations from dotbot to chezmoi.
## Current Dotbot Structure
You currently have host-specific configurations in:
```
hosts/
├── air/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── lakka/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── tunkki/
│ └── install.conf.yaml
└── s/
└── install.conf.yaml
```
## Chezmoi Approaches
There are three main approaches to handle host-specific configurations in chezmoi:
### 1. Template Conditionals (Recommended)
Use if/else conditions in template files.
**Pros:**
- Single source file for all hosts
- Easy to see all variations
- Less file duplication
**Cons:**
- Files can get complex with many hosts
- Need `.tmpl` extension
**Example:**
Create `dot_bashrc.tmpl`:
```bash
# Common configuration for all hosts
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific
export WORK_DIR="$HOME/Work"
alias air-specific="echo air"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific
export WORK_DIR="$HOME/Projects"
alias lakka-specific="echo lakka"
{{ end }}
# More common configuration
```
### 2. Separate Files with .chezmoiignore (Simple)
Keep separate files per host and ignore the ones that don't apply.
**Pros:**
- Clean separation
- No template syntax needed
- Easy to maintain
**Cons:**
- More files to manage
- Some duplication
**Example:**
Create multiple version files:
```
dot_bashrc__air
dot_bashrc__lakka
dot_bashrc__tunkki
```
These automatically apply based on hostname. No `.chezmoiignore` needed!
Or use directories:
```
dot_config/
├── app/
│ ├── config.yaml__air
│ ├── config.yaml__lakka
│ └── config.yaml__default
```
### 3. Hybrid Approach (Most Flexible)
Combine both methods:
- Use templates for files with minor differences
- Use separate files for completely different configs
## Migration Steps for Your Hosts
### Step 1: Analyze Each Host
Review what's different per host:
```bash
# See what's in each host directory
ls -la hosts/air/
ls -la hosts/lakka/
ls -la hosts/tunkki/
ls -la hosts/s/
# Compare configs
diff hosts/air/config/some-app/config hosts/lakka/config/some-app/config
```
### Step 2: Choose Strategy Per File
For each file that differs:
**Small differences** (few lines):
→ Use templates with conditionals
**Complete replacement**:
→ Use `filename__hostname` suffix
**Shared base + host additions**:
→ Use templates with includes or blocks
### Step 3: Migrate Host Configurations
#### Example: Fish Configuration
Your `hosts/air/config/fish/config.fish` differences:
**Current dotbot way:**
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**New chezmoi way - Option A (Templates):**
Create `dot_config/fish/config.fish.tmpl`:
```fish
# Common fish configuration
set -gx EDITOR nvim
{{ if eq .chezmoi.hostname "air" }}
# air-specific config
set -gx WORK_DIR ~/Work
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific config
set -gx WORK_DIR ~/Projects
{{ end }}
# More common configuration
```
**New chezmoi way - Option B (Separate files):**
Create multiple files:
```
dot_config/fish/config.fish__air
dot_config/fish/config.fish__lakka
```
Chezmoi will automatically use the correct file based on hostname.
### Step 4: Update .chezmoi.yaml.tmpl
Add host flags for easier conditionals:
```yaml
{{- $hostname := .chezmoi.hostname -}}
data:
hostname: {{ $hostname | quote }}
# Host-specific flags
is_air: {{ eq $hostname "air" }}
is_lakka: {{ eq $hostname "lakka" }}
is_tunkki: {{ eq $hostname "tunkki" }}
is_s: {{ eq $hostname "s" }}
# Group flags
is_work: {{ or (eq $hostname "air") (eq $hostname "tunkki") }}
is_personal: {{ or (eq $hostname "lakka") (eq $hostname "s") }}
```
Then use simpler conditionals:
```go
{{ if .is_air }}
# air config
{{ end }}
{{ if .is_work }}
# All work machines
{{ end }}
```
## Specific Migration Examples
### Example 1: Simple Host-Specific Line
**Before (dotbot):**
```yaml
# hosts/air/config/app/config
setting=value_for_air
# hosts/lakka/config/app/config
setting=value_for_lakka
```
**After (chezmoi) - Option A:**
```
# dot_config/app/config.tmpl
{{ if .is_air -}}
setting=value_for_air
{{- else if .is_lakka -}}
setting=value_for_lakka
{{- end }}
```
**After (chezmoi) - Option B:**
```
# dot_config/app/config__air
setting=value_for_air
# dot_config/app/config__lakka
setting=value_for_lakka
```
### Example 2: Mostly Shared with Few Differences
**Before:**
100 lines shared, 5 lines different per host
**After (recommended - templates):**
```bash
# dot_config/app/config.tmpl
# ... 50 lines of shared config ...
{{ if .is_air }}
air_specific_setting=true
{{ else if .is_lakka }}
lakka_specific_setting=true
{{ end }}
# ... 50 more lines of shared config ...
```
### Example 3: Completely Different Configs
**Before:**
Two totally different config files
**After (recommended - separate files):**
```
dot_config/app/config__air
dot_config/app/config__lakka
```
### Example 4: Host-Specific Directories
**Before:**
```
hosts/air/config/air-only-app/
hosts/lakka/config/lakka-only-app/
```
**After - Use .chezmoiignore:**
```
# .chezmoiignore
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-only-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-only-app/
{{ end }}
```
Then create:
```
dot_config/air-only-app/ # Only applied on air
dot_config/lakka-only-app/ # Only applied on lakka
```
## Testing Host-Specific Configs
### Before Applying
```bash
# See what would be applied on this host
chezmoi diff
# See what a specific file would look like
chezmoi cat ~/.config/fish/config.fish
# Check template data
chezmoi data | grep hostname
```
### Simulating Other Hosts
```bash
# Test what would be applied on another host
chezmoi execute-template --init --promptString hostname=air "{{ .chezmoi.hostname }}"
# See what a file would look like on another host
# (This requires manual variable setting in templates)
```
### On Another Machine
```bash
# Initialize and test without applying
chezmoi init --dry-run --verbose ivuorinen
# Apply with dry-run
chezmoi apply --dry-run -v
```
## Migration Script Adjustments
Add to `migrate-to-chezmoi.sh`:
```bash
# Migrate host-specific configs
log_info "Processing host-specific configurations..."
CURRENT_HOST=$(hostname -s)
log_info "Current hostname: $CURRENT_HOST"
# Prompt for migration strategy
echo ""
log_warning "How do you want to handle host-specific configs?"
echo " 1) Merge into templates (recommended for small differences)"
echo " 2) Keep separate files per host (recommended for large differences)"
echo " 3) Manual (skip automatic migration)"
read -p "Choose (1/2/3): " -r STRATEGY
if [ "$STRATEGY" = "1" ]; then
log_info "Will merge into templates (requires manual editing after)"
# Create template files
# ... migration logic ...
elif [ "$STRATEGY" = "2" ]; then
log_info "Creating separate host-specific files..."
for host in air lakka tunkki s; do
if [ -d "hosts/$host" ]; then
log_info "Processing host: $host"
# Process host-specific base files
if [ -d "hosts/$host/base" ]; then
for file in hosts/$host/base/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
move_dotfiles "$file" "dot_${filename}__${host}" ""
fi
done
fi
# Process host-specific config files
if [ -d "hosts/$host/config" ]; then
for file in hosts/$host/config/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
dest="dot_config/$(dirname $file)__${host}"
move_dotfiles "$file" "$dest/$(basename $file)" ""
fi
done
fi
fi
done
else
log_info "Skipping automatic host-specific migration"
log_info "You'll need to manually migrate hosts/ directory"
fi
```
## Best Practices
1. **Start Simple**: Use separate files first, move to templates as you see patterns
2. **Don't Over-Template**: If a file is completely different per host, use separate files
3. **Document Hosts**: Add comments in `.chezmoi.yaml.tmpl` explaining each host
4. **Test Thoroughly**: Test on each host before committing
5. **Use Host Groups**: Group hosts (work/personal, laptop/desktop) for easier conditionals
## Checklist
- [ ] Identify all host-specific files
- [ ] Choose strategy per file (templates vs separate)
- [ ] Update `.chezmoi.yaml.tmpl` with host flags
- [ ] Migrate host-specific base files
- [ ] Migrate host-specific config files
- [ ] Update `.chezmoiignore` for host-specific directories
- [ ] Test on current host
- [ ] Test on other hosts
- [ ] Document which approach was used where
- [ ] Clean up old hosts/ directory
## Examples from Your Hosts
Based on your current structure:
### hosts/air/install.conf.yaml
```yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Migration approach:**
- Check what's in `hosts/air/config/`
- If it's app configs, use separate files: `dot_config/app/config__air`
- If it's just a few lines different, merge into templates
### Common Pattern
For configurations that need host-specific values but share structure:
```yaml
# dot_config/app/config.tmpl
# Common settings
port=8080
# Host-specific
{{ if .is_air -}}
workspace=/Users/yourname/Work
{{- else if .is_lakka -}}
workspace=/Users/yourname/Projects
{{- end }}
# More common settings
debug=false
```
## Need Help?
If you're unsure about a specific file:
1. Check the diff: `diff hosts/air/file hosts/lakka/file`
2. Count different lines
3. If < 20% different use templates
4. If > 20% different → use separate files
Remember: You can always refactor later!

View File

@@ -0,0 +1,523 @@
# Migration Guide: Dotbot to Chezmoi
This guide documents the migration from dotbot to chezmoi for managing dotfiles.
## Table of Contents
1. [Why Migrate to Chezmoi?](#why-migrate-to-chezmoi)
2. [Key Differences](#key-differences)
3. [Dotbot to Chezmoi Mapping](#dotbot-to-chezmoi-mapping)
4. [New File Structure](#new-file-structure)
5. [Migration Steps](#migration-steps)
6. [Usage Guide](#usage-guide)
7. [Troubleshooting](#troubleshooting)
## Why Migrate to Chezmoi?
Chezmoi offers several advantages over dotbot:
- **Built-in templating**: Use Go templates for dynamic configuration
- **Secret management**: Native support for password managers (1Password, LastPass, etc.)
- **Cross-platform**: Better support for managing dotfiles across different OS and machines
- **State tracking**: Chezmoi tracks what it manages more precisely
- **Active development**: Regular updates and large community
- **No dependencies**: Single binary, no Python required
## Key Differences
### Philosophy
**Dotbot**:
- Configuration-driven (YAML files)
- Manages symlinks from a source directory
- Plugins extend functionality
**Chezmoi**:
- Source-state driven
- Copies files to home directory (can also use symlinks)
- Built-in templating for dynamic content
- Manages the entire lifecycle of dotfiles
### Directory Structure
**Dotbot**:
```
~/.dotfiles/
├── base/ # Files symlinked to ~/.*
├── config/ # Files symlinked to ~/.config/
├── local/ # Scripts and local files
├── install # Installation script
└── install.conf.yaml # Configuration
```
**Chezmoi**:
```
~/.local/share/chezmoi/ # Source directory
├── .chezmoi.yaml.tmpl # Configuration template
├── .chezmoiignore # Files to ignore
├── run_once_*.sh.tmpl # One-time setup scripts
├── run_*.sh.tmpl # Scripts that run on every apply
├── dot_bashrc # Becomes ~/.bashrc
├── dot_config/ # Becomes ~/.config/
└── private_dot_ssh/ # Becomes ~/.ssh/ with 0700
```
## Dotbot to Chezmoi Mapping
### 1. Link Directives
**Dotbot** (install.conf.yaml):
```yaml
- link:
~/.bashrc: base/bashrc
~/.config/fish: config/fish
```
**Chezmoi**:
- Files are automatically managed based on their names in the source directory
- `dot_bashrc``~/.bashrc`
- `dot_config/fish/``~/.config/fish/`
- Use `symlink_` prefix for symlinks: `symlink_dot_vim` → symlinked `~/.vim`
### 2. Create Directives
**Dotbot**:
```yaml
- create:
~/.ssh:
mode: 0700
~/.local/bin:
```
**Chezmoi**:
- Create a `run_once_after_create-directories.sh.tmpl` script
- Or use `.chezmoitemplates` for reusable directory creation
- Chezmoi automatically creates parent directories
### 3. Shell Commands
**Dotbot**:
```yaml
- shell:
- git submodule update --init --recursive
- bash local/bin/dfm install all
```
**Chezmoi**:
- Use `run_once_*.sh.tmpl` for one-time setup scripts
- Use `run_*.sh.tmpl` for scripts that run every time
- Use `run_before_*.sh` for scripts that run before applying
- Use `run_after_*.sh` for scripts that run after applying
### 4. Clean Directives
**Dotbot**:
```yaml
- clean:
~/:
~/.config:
recursive: true
```
**Chezmoi**:
- Chezmoi doesn't automatically remove files
- Use `chezmoi unmanaged` to see unmanaged files
- Manually remove or add to `.chezmoiignore`
### 5. Host-Specific Configuration
**Dotbot**:
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Chezmoi**:
- Use templates with conditionals:
```
{{ if eq .chezmoi.hostname "air" }}
# air-specific content
{{ end }}
```
- Or use separate files: `dot_config/file.tmpl` with hostname checks
### 6. Dotbot Plugins
**dotbot-brew**:
- Replace with `run_once_after_install-packages.sh.tmpl`
- Use `brew bundle install`
**dotbot-asdf**:
- Chezmoi doesn't have built-in asdf support
- Use `run_once_after_*.sh` scripts to install asdf plugins
**dotbot-pip/pipx**:
- Use `run_once_after_*.sh` scripts
- Or use chezmoi's external management
## New File Structure
### Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file with template support. Defines:
- Source directory
- Data variables (hostname, OS, custom flags)
- Merge strategy
- Template options
- Git options
#### `.chezmoiignore`
Files and patterns to ignore when applying dotfiles. Includes:
- Repository management files (.git, .github, etc.)
- Documentation
- Development tools
- Old dotbot configuration
### Run Scripts
Scripts follow a naming convention:
- `run_once_before_*.sh.tmpl`: Runs once before applying (prerequisites)
- `run_once_after_*.sh.tmpl`: Runs once after applying (installation)
- `run_before_*.sh.tmpl`: Runs every time before applying
- `run_after_*.sh.tmpl`: Runs every time after applying
- `run_onchange_*.sh.tmpl`: Runs when file content changes
### File Naming
Chezmoi uses special prefixes:
- `dot_`: Becomes a dot file (`.`)
- `private_`: Sets permissions to 0600
- `executable_`: Makes file executable
- `symlink_`: Creates a symlink
- `readonly_`: Makes file read-only
Examples:
- `dot_bashrc``~/.bashrc`
- `private_dot_ssh/``~/.ssh/` (mode 0700)
- `executable_dot_local/bin/script``~/.local/bin/script` (executable)
## Migration Steps
### 1. Backup Current Setup
```bash
# Backup your current dotfiles
cd ~/.dotfiles
git add -A
git commit -m "Backup before chezmoi migration"
git push
```
### 2. Install Chezmoi
```bash
# The new install script will do this automatically
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
```
### 3. Initialize Chezmoi with Existing Dotfiles
```bash
# If you want to test before full migration
chezmoi init --apply ivuorinen
# Or initialize without applying
chezmoi init ivuorinen
```
### 4. Restructure Files (Manual Step)
You'll need to rename files to follow chezmoi conventions:
```bash
cd ~/.local/share/chezmoi
# Rename base files
mv base/bashrc dot_bashrc
mv base/zshrc dot_zshrc
mv base/tmux.conf dot_tmux.conf
# Move config files
mkdir -p dot_config
mv config/* dot_config/
# Move local/bin files
mkdir -p dot_local/bin
for file in local/bin/*; do
mv "$file" "executable_dot_local/bin/$(basename "$file")"
done
# Move SSH files with proper permissions
mkdir -p private_dot_ssh
mv ssh/* private_dot_ssh/
```
### 5. Convert Host-Specific Configurations
For files that differ between hosts, use templates:
```bash
# Instead of hosts/air/config/fish/config.fish
# Create: dot_config/fish/config.fish.tmpl
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
{{ end }}
```
### 6. Test the Migration
```bash
# See what changes chezmoi would make
chezmoi diff
# Apply changes
chezmoi apply
# Verify everything works
chezmoi verify
```
### 7. Clean Up Old Files
```bash
# Remove dotbot directories (after confirming everything works)
cd ~/.local/share/chezmoi
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm -rf hosts/ # If fully migrated to templates
```
## Usage Guide
### Basic Commands
```bash
# Initialize chezmoi with your dotfiles
chezmoi init ivuorinen
# See what changes would be made
chezmoi diff
# Apply dotfiles
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Edit a file managed by chezmoi
chezmoi edit ~/.bashrc
# Add a new file to chezmoi
chezmoi add ~/.newfile
# Update dotfiles from source
chezmoi update
# See what files are managed
chezmoi managed
# See what files are unmanaged
chezmoi unmanaged
# Re-run scripts
chezmoi apply --force
# Check for issues
chezmoi doctor
```
### Working with Templates
```bash
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# See the data available in templates
chezmoi data
# Edit template data
chezmoi edit-config
```
### Managing Secrets
```bash
# Use with 1Password
chezmoi secret keychain
# Template with 1Password
{{ (index (onepasswordDocument "my-secret") 0).content }}
# Use with environment variables
{{ .Env.MY_SECRET }}
```
### Updating Dotfiles
```bash
# Edit source file
chezmoi edit ~/.bashrc
# Or edit directly and add
vi ~/.bashrc
chezmoi add ~/.bashrc
# Commit changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update bashrc"
git push
# On another machine
chezmoi update
```
## Troubleshooting
### Common Issues
#### 1. File Permissions
**Problem**: Files have wrong permissions after applying.
**Solution**: Use prefixes:
```bash
# For 0600 permissions
chezmoi add --template private_dot_ssh/config
# For 0700 directories
mkdir -p private_dot_ssh
```
#### 2. Symlinks Not Working
**Problem**: Chezmoi copies files instead of symlinking.
**Solution**: Use `symlink_` prefix:
```bash
chezmoi add --symlink ~/.vim
# This creates symlink_dot_vim in the source directory
```
#### 3. Templates Not Rendering
**Problem**: Template syntax is showing literally in files.
**Solution**:
- Ensure file has `.tmpl` extension
- Check template syntax
- Verify data with `chezmoi data`
#### 4. Scripts Not Running
**Problem**: `run_once_` scripts not executing.
**Solution**:
- Check script permissions: `chmod +x run_once_*.sh.tmpl`
- Run with force: `chezmoi apply --force`
- Check script order (before/after)
#### 5. Host-Specific Files Not Applying
**Problem**: Wrong host configuration applied.
**Solution**:
- Check hostname: `chezmoi data | grep hostname`
- Verify template conditionals
- Use `.chezmoiignore` for host-specific exclusions
### Debugging
```bash
# Verbose output
chezmoi apply -v
# Very verbose output
chezmoi apply -vv
# Dry run to see what would happen
chezmoi apply --dry-run -v
# Check configuration
chezmoi doctor
# Verify state
chezmoi verify
# See source directory
chezmoi source-path
# See what would be applied to a specific file
chezmoi cat ~/.bashrc
```
### Migration Checklist
- [ ] Backup current dotfiles
- [ ] Install chezmoi
- [ ] Create `.chezmoi.yaml.tmpl`
- [ ] Create `.chezmoiignore`
- [ ] Rename files with proper prefixes
- [ ] Convert host-specific configs to templates
- [ ] Create `run_once_before` scripts
- [ ] Create `run_once_after` scripts
- [ ] Test with `chezmoi diff`
- [ ] Apply with `chezmoi apply`
- [ ] Verify everything works
- [ ] Update documentation
- [ ] Clean up old dotbot files
- [ ] Update README.md
- [ ] Test on another machine
## Additional Resources
- [Chezmoi Documentation](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Template Reference](https://www.chezmoi.io/reference/templates/)
- [Example Dotfiles Using Chezmoi](https://github.com/topics/chezmoi)
## Notes
### What Stays the Same
- Your actual dotfile contents
- Directory structure in home directory
- Git workflow for managing dotfiles
- The `dfm` script functionality (wrapped in run_once scripts)
### What Changes
- Installation method (new `install` script)
- Source directory location (`~/.local/share/chezmoi` by default)
- Configuration method (templates instead of YAML)
- File naming (special prefixes)
- No more symlinks by default (unless specified)
### Benefits of Migration
1. **Simplicity**: Single binary, no dependencies
2. **Templating**: Dynamic content based on hostname, OS, etc.
3. **Secrets**: Built-in support for password managers
4. **State Management**: Better tracking of what's managed
5. **Cross-platform**: Excellent support for different OSes
6. **Documentation**: Extensive docs and examples
7. **Community**: Active development and support
## Post-Migration
After successful migration:
1. Update your README to reflect chezmoi usage
2. Archive dotbot configuration for reference
3. Document any custom scripts or workflows
4. Test on all your machines
5. Share your experience!