---
render_with_liquid: false
---
{% raw %}

# Fleet Architecture

A "fleet" is two or more workstations sharing a single `.dotfiles` source repository. The fleet model handles per-host customization, drift detection, and cross-host trust propagation.

## Single Source, Many Hosts

All hosts clone the same repository. Platform and per-host differences are resolved at `chezmoi apply` time using three sources of data:

1. **`.chezmoidata.toml`** — defaults for all hosts
2. **`.chezmoidata/hardware.toml`** — machine presets (MacBook T2, Surface Pro, Geekom, etc.)
3. **`~/.config/chezmoi/chezmoi.toml`** — per-host overrides, generated by `chezmoi init`

The `machine` key in `chezmoi.toml` selects which preset applies:

```toml
# ~/.config/chezmoi/chezmoi.toml on a MacBook
[data]
machine = "macbook-t2"
theme = "tahoe-dark"
```

Templates read `.chezmoi.hardware` to get the resolved preset:

```go
{{- $hw := index .hardware .machine }}
display_scale = {{ $hw.display_scale }}  // 2.0 for MacBook, 1.5 for Surface
```

## Hardware Presets

`.chezmoidata/hardware.toml` ships with ~12 presets covering common laptop/desktop/NUC configurations. Each preset defines:

| Field | Purpose |
|:---|:---|
| `display_scale` | 1.0, 1.25, 1.5, 1.75, 2.0 |
| `kbd_layout` | colemak-dh, qwerty, dvorak |
| `modifier_mode` | left-cmd-control, fn-swap, standard |
| `perf_profile` | laptop, desktop, low-power |
| `wm` | aerospace, niri, gnome, kde |
| `features.X` | per-preset feature toggles |

Add a new preset by appending to `hardware.toml` — no code changes needed.

## Drift Detection

`dot drift` compares the current machine state against the rendered template output and reports:

| Drift Type | Example |
|:---|:---|
| **Added** | File exists locally but not in source |
| **Removed** | Source deletes a file still present locally |
| **Modified** | Local edit to a managed file |
| **Permission** | Chmod/chown changes |
| **Symlink target** | Link retargeted |

Drift is normal during development. `dot heal` reconciles the source → local direction. `dot apply` overwrites drift; `dot diff` previews the change without applying.

## Fleet Attestation

`dot fleet attest` runs `dot attest` locally and collects signed attestations from every known host (via SSH). The combined report shows:

- Whether all hosts are on the same Git SHA
- Whether policy hashes match
- Which hosts have drift
- Which hosts have verified signatures

A typical output:

```
Fleet Attestation — v0.2.501

Host           Git SHA    Policy    Tools OK   Drift   Verified
-------------- ---------- --------- ---------- ------- --------
macbook-t2     abc123d    0x7f2a…   ✓          0       ✓
surface-pro    abc123d    0x7f2a…   ✓          2       ✓
geekom-a9      def456e    0x7f2a…   ✗ (chezmoi 2.45)   ✗
-------------- ---------- --------- ---------- ------- --------
FLEET STATUS: 2/3 aligned; drift on geekom-a9
```

This becomes an auditable artifact — useful for compliance reporting, incident response, and post-upgrade validation.

## Fleet Deployment Workflow

Recommended rollout procedure for fleet-wide changes:

1. **Develop on one host** — make the change, test locally with `dot apply --dry-run` then `dot apply`
2. **Open a PR** — CI validates shellcheck, tests, security scanners
3. **Merge to master** — signed commit required
4. **Per-host pull** — on each fleet host: `dot update` (git pull + apply)
5. **Verify alignment** — run `dot fleet attest` from any host

For urgent rollback: every host can independently run `dot rollback` to return to the previous known-good state (stored in `~/.local/state/dotfiles/snapshots/`).

## Cross-Host Trust

Each host has its own SSH ED25519 signing key. To establish mutual trust:

1. On each host: `cat ~/.ssh/id_ed25519.pub` — capture the public key
2. Add every host's public key to `~/.ssh/allowed_signers` on every other host
3. Commit `allowed_signers` to the source repository (it's public-key material, safe to share)
4. After `dot apply`, any host can verify commits and attestations from any other host

This creates a **web-of-trust** among your own fleet. No central CA, no external service — just SSH keys.

## Machine-Scoped Secrets

Some secrets must decrypt only on specific hosts (e.g. a work VPN config that doesn't belong on a personal laptop). The SOPS approach:

```yaml
# dot_config/vpn.sops.yaml
vpn_key: ENC[AES256_GCM,data:...]
sops:
  age:
    - recipient: age1... # work laptop only
      enc: |
        -----BEGIN AGE ENCRYPTED FILE-----
        ...
```

Only the host with the matching Age private key can decrypt. Other hosts see the encrypted file but cannot read the content.

## Fleet Operational Commands

| Command | Purpose |
|:---|:---|
| `dot fleet` | Show all known hosts and their last-seen status |
| `dot fleet attest` | Collect signed attestations from every host |
| `dot fleet diff` | Compare rendered config across hosts |
| `dot fleet sync` | Run `dot update` on every host (requires SSH access) |

## Limitations

- Fleet commands assume SSH connectivity between hosts (or a dedicated orchestration agent — see [Roadmap](../../operations/ROADMAP.md))
- Secret rotation requires re-encrypting for all recipients; automated with `dot secrets rotate`
- There is no central policy store — policy is versioned in the Git repository itself

## See Also

- [Fleet Deployment Architecture](../../architecture/fleet-deployment.md) — diagrams
- [Trust Model](02-trust-model.md)
- [Tutorial: Deploy to a Fleet](../02-tutorials/05-deploy-fleet.md)
{% endraw %}
