docs: add standalone chezmoi bootstrap and gotchas

Document how to bring chezmoi up on another VPS without the provisioning
layer, and record the chezmoi behaviours that caused real breakage here.

The umask trap is the load-bearing one: chezmoi derives modes from the
umask at apply time rather than preserving them, so the atuin key dir and
config need both the private_ attribute and umask = 0o022 to land at 0700
and 0600. The apply-into-head SIGPIPE is the other: it truncates the apply
and reports head's exit status, so a partial apply looks successful.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 15:05:23 +02:00
parent 893ec8e3cb
commit d6fe9277cb

View File

@@ -29,6 +29,50 @@ Expect **1020 minutes**: atuin, eza, macchina and oxker are built from source
trade for matching the currently-running versions exactly rather than taking
whatever apt ships.
## chezmoi on another VPS
`setup.sh` already does all of this. Use this path only when you want the dotfiles
*without* the provisioning layer (no apt, no rust, no `chsh`) — e.g. a box where the
tools are already there, or where you don't have root.
```bash
# 1. install chezmoi (user-local, no root)
sh -c "$(curl -fsLS get.chezmoi.io)" -- -b "$HOME/.local/bin"
export PATH="$HOME/.local/bin:$PATH"
# 2. pin the umask BEFORE the first apply — see Notes, this is load-bearing
mkdir -p ~/.config/chezmoi
printf 'umask = 0o022\n' >> ~/.config/chezmoi/chezmoi.toml
# 3. pull the source state (private repo — needs Gitea credentials)
chezmoi init https://git.domverse-berlin.eu/domverse/dotfiles.git
# 4. look before you leap
chezmoi diff
# 5. write it out
chezmoi apply
```
Notes on the above:
- **Step 2 must come before step 4.** The umask is read at apply time; applying
first and fixing the config after leaves wrong modes on disk.
- **Step 3 needs repo access.** The repo is private. Either have
`credential.helper=store` already populated, or clone over SSH:
`chezmoi init git@git.domverse-berlin.eu:domverse/dotfiles.git`.
- The source clone lands in `~/.local/share/chezmoi` (chezmoi's default). This box
is the exception — it sets `sourceDir = /home/crabix/projects/dotfiles` in
`~/.config/chezmoi/chezmoi.toml` because the repo predates chezmoi. On a fresh
box, don't set `sourceDir`; the default is what `setup.sh` expects.
- `.chezmoiroot` contains `home`, so the source root is `home/`, not the repo root.
`setup.sh` and `README.md` sit outside chezmoi's view by design.
- If `~` already has real dotfiles, `chezmoi diff` in step 4 shows exactly what
gets clobbered. Back them up with modes intact first:
`cp -a ~/.config/fish ~/.config/atuin ~/backup/dotfiles-preapply-$(date -u +%Y%m%dT%H%M%SZ)/`
- Then do the **Manual steps** below (atuin key, git identity) — they are not
specific to `setup.sh`.
## Day-to-day
Configs are managed by chezmoi, so the file in `~/.config` is a *copy*, not a
@@ -83,6 +127,37 @@ The script prints these; repeated here because they're easy to miss:
```
3. **Log out and back in** for the fish shell change to take effect.
## chezmoi gotchas
Learned the hard way while building this. Don't rediscover them.
- **chezmoi does not preserve file modes.** It tracks only the `executable_` and
`private_` source attributes and derives the actual mode from the *umask at apply
time*. With `umask 002` (the default for this user), `~/.config/atuin/` silently
goes `0700` → `0775` and `config.toml` `0600` → `0664`. Correct modes need **both**
halves:
- the source attribute — `private_atuin/private_config.toml`, and
- `umask = 0o022` in `~/.config/chezmoi/chezmoi.toml` (`setup.sh` writes this).
Always `chezmoi diff` before trusting a dotfiles repo on a new box; the mode lines
are quiet and easy to scroll past.
- **Never pipe `chezmoi apply` into a truncating command.** `chezmoi apply --verbose |
head -20` SIGPIPEs chezmoi partway through, leaving the apply **incomplete** — files
sorting after the cutoff are never written. Worse, `$?` reports *head's* exit status
(0), so it looks like it succeeded. Redirect to a file and read that instead:
```bash
chezmoi apply --verbose > /tmp/apply.log 2>&1; echo "exit=$?"
```
- **The file in `~` is a copy, not a symlink.** Editing `~/.config/fish/config.fish`
directly gets silently clobbered on the next apply. Use `chezmoi edit`. The
`fishconfig` alias points at `chezmoi edit` for exactly this reason.
- **`chezmoi init` on a box with existing dotfiles overwrites without asking** once
you `apply`. `chezmoi diff` first, always.
## Notes
- `config.fish` aliases `cat` to `batcat` — on Ubuntu the bat binary really is