mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-02-11 19:52:17 +00:00
feat: switch to chezmoi
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
This commit is contained in:
462
docs/HOST-SPECIFIC-MIGRATION.md
Normal file
462
docs/HOST-SPECIFIC-MIGRATION.md
Normal 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!
|
||||
Reference in New Issue
Block a user