@sebastienrousseau/dotfiles
Version:
The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.
245 lines (177 loc) • 5.85 kB
Markdown
---
render_with_liquid: false
---
{% raw %}
# Tutorial: Create a Machine Profile
Machine profiles tell chezmoi how to render templates differently on each host — display scale, keyboard layout, performance preset, available features.
## When to Use a Profile
- You have more than one host (laptop + desktop, work + personal)
- Your hardware differs materially (HiDPI laptop vs 1080p external, ARM vs x86)
- Certain features only apply to specific setups (Niri on Wayland, AeroSpace on macOS)
## Step 1: Choose or Create a Preset
Presets live in `.chezmoidata/hardware.toml`:
```toml
[hardware.macbook-t2]
display_scale = 2.0
kbd_layout = "qwerty"
modifier_mode = "left-cmd-control"
perf_profile = "laptop"
wm = "aerospace"
[hardware.macbook-t2.features]
retina = true
touchid = true
[hardware.surface-pro]
display_scale = 1.5
kbd_layout = "colemak-dh"
modifier_mode = "standard"
perf_profile = "laptop"
wm = "niri"
[hardware.surface-pro.features]
touch = true
pen = true
```
If an existing preset fits: use its name. Otherwise, add a new one.
## Step 2: Select the Preset for This Host
Edit `~/.config/chezmoi/chezmoi.toml`:
```toml
[data]
machine = "surface-pro" # choose from .chezmoidata/hardware.toml
theme = "dome-dark"
default_shell = "fish"
terminal_font_family = "JetBrainsMono Nerd Font"
terminal_font_size = 11 # larger for HiDPI, smaller for dense screens
```
`chezmoi.toml` is **not** in the repository — each host has its own. Generated by `chezmoi init` on first install.
## Step 3: Reference the Preset in Templates
Inside any `.tmpl` file:
```go
{{- $hw := index .hardware .machine }}
# Ghostty config — uses machine-specific font size
font-family = "{{ .terminal_font_family }}"
font-size = {{ .terminal_font_size }}
# DPI-aware settings
{{ if eq $hw.display_scale 2.0 }}
window-decoration = false
{{ else }}
window-decoration = true
{{ end }}
# Feature-gated config
{{ if $hw.features.touch }}
mouse-scroll-multiplier = 3
{{ end }}
```
After editing the template, run `chezmoi apply` or `dot apply`.
## Step 4: Add a New Preset
Suppose you have a new mini PC. Add to `.chezmoidata/hardware.toml`:
```toml
[hardware.my-nuc]
display_scale = 1.0 # external 1440p
kbd_layout = "qwerty"
modifier_mode = "standard"
perf_profile = "desktop"
wm = "gnome"
[hardware.my-nuc.features]
multi-monitor = true
gaming = true
```
Then on that host:
```toml
# ~/.config/chezmoi/chezmoi.toml
[data]
machine = "my-nuc"
```
Apply:
```sh
dot apply
```
Templates automatically pick up the new preset data.
## Step 5: Per-Preset Feature Flags
Feature flags in `.chezmoidata.toml` can be gated by preset:
```toml
# .chezmoidata.toml — defaults for all hosts
[features]
dms = false
linux_desktop = false
waybar = false
```
Override per-preset in `.chezmoidata/hardware.toml`:
```toml
[hardware.surface-pro.features]
touch = true
pen = true
dms = true # override feature default
waybar = true
```
In templates:
```go
{{- $hw := index .hardware .machine }}
{{- $features := mergeOverwrite .features $hw.features }}
{{ if $features.waybar }}
# ... waybar-specific config ...
{{ end }}
```
## Example: Font Size by Preset
A single Ghostty config that renders correctly on every host:
```go
# dot_config/ghostty/config.tmpl
{{- $hw := index .hardware .machine }}
theme = {{ .theme }}
font-family = "{{ .terminal_font_family }}"
# DPI-aware font sizing
{{ if eq $hw.display_scale 2.0 }}
font-size = 12 # Retina MacBook
{{ else if eq $hw.display_scale 1.5 }}
font-size = 11 # Surface Pro
{{ else }}
font-size = 14 # External 1440p/4K
{{ end }}
```
On the MacBook: 12pt. On the Surface: 11pt. On the NUC: 14pt. One template.
## Example: Platform × Preset
Combine `.chezmoi.os` with the preset:
```go
{{- $hw := index .hardware .machine }}
{{ if and (eq .chezmoi.os "darwin") (eq $hw.wm "aerospace") }}
# macOS + AeroSpace specifics
{{ else if and (eq .chezmoi.os "linux") (eq $hw.wm "niri") }}
# Linux + Niri specifics
{{ end }}
```
## Listing Known Presets
```sh
chezmoi execute-template '{{- range $name, $_ := .hardware }}{{ $name }}{{ "\n" }}{{ end }}'
# macbook-t2
# surface-pro
# geekom-a9
# my-nuc
```
## Changing Presets on an Existing Host
If you reassign a host to a different preset:
```sh
# Edit ~/.config/chezmoi/chezmoi.toml
# machine = "my-nuc" (was "surface-pro")
dot apply --dry-run # preview changes
dot apply # apply
```
Chezmoi re-renders every template with the new preset data. No reboot needed.
## Troubleshooting
### "Machine preset 'foo' not found"
The `machine` value in `~/.config/chezmoi/chezmoi.toml` doesn't match any key under `[hardware.*]` in `.chezmoidata/hardware.toml`. Check spelling.
### Templates Silently Use Defaults
Make sure you're using `{{- $hw := index .hardware .machine }}` at the top of templates. If `machine` is empty, `index` returns `nil` — reference with `{{- with $hw }}...{{- end }}` guards.
### Feature Flag Not Taking Effect
Verify the merge order:
```sh
chezmoi execute-template '{{- $hw := index .hardware .machine -}}{{- $f := mergeOverwrite .features $hw.features -}}{{ $f | toToml }}'
```
Per-preset features must override global defaults. If the output doesn't reflect that, check template syntax.
## Summary
Profiles let one source tree produce correctly-configured output on every host you own. The machinery:
1. `.chezmoidata/hardware.toml` defines presets (declarative)
2. `~/.config/chezmoi/chezmoi.toml` selects a preset per host (per-host override)
3. `.tmpl` files read `.hardware` + `.machine` (template-time)
## Next
- [Concept: Fleet Architecture](../01-concepts/04-fleet.md)
- [Reference: Templates](../03-reference/04-templates.md)
- [Reference: Feature Flags](../03-reference/05-feature-flags.md)
{% endraw %}