# Bootstrap Procedure ## Lessons from the last install - Do not use Flatpak 1Password, it's built into the actual bootc image now, as a first class citizen. - No need to worry about browsers, Helium is baked into the image too, because you ___do not want to use___ a Chromium browser in a Flatpak, and absolutely no Firefox. - SSH/YubiKeys are now handled by SOPS secrets, and nushell helper scripts. - Run `dfe` for dotfile edits so changes land in a fresh jj change, and aren't just added to the working copy. ## Basic assumptions This checklist is assuming an install onto zircadia, my custom bootc image. This image comes with chezmoi, homebrew, Helium Browser, Steam, 1Password, ykman, age, sops, age-plugin-yubikey, and jj preinstalled. They will absolutely be present. If they are not, this list does not apply. ## Stage 0: Pre-clone requirements to get to access the rest of the tools [ ] `brew install helix` This gives me my preferred editor. [ ] `curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin` My preferred terminal. [ ] Launch kitty [ ] `nu` We have to switch to nu, in order to use nushell commands consistently. [ ] `mkdir ~/.ssh` [ ] `chmod 700 ~/.ssh` [ ] `cd ~/.ssh` [ ] `ssh-keygen -K` Repeat with exactly one YubiKey inserted at a time, and preserve the identity-handle filenames expected by the encrypted SSH inventory. [ ] Write a temporary minimal `~/.ssh/config` entry for `Host tangled.org`; all you need is: - `IdentityFile ` - `IdentitiesOnly true` - `IdentityAgent none` [ ] `chmod 600 ~/.ssh/config` ## Stage 1: Fetching dotfiles from the remote [ ] `ls ~/.local/share/chezmoi` to see if the directory already exists. [ ] `mkdir ~/.local/share/chezmoi` if it doesn't. [ ] `cd ~/.local/share/chezmoi` [ ] `jj git clone --no-colocate git@tangled.org:threadweaver.dev/dotfiles .` This will copy down the files, and the bookmarks, setting the working copy one commit ahead of the trunk. [ ] `mkdir .git` This needs to exist as an empty directory so that chezmoi isn't confused. A test clone showed that no `.git` directory is created as part of the cloning process, and therefore it has to get made manually, so `chezmoi init` doesn't create a real git repo. [ ] `jj st` To check the repo status. ## Stage 2: Run the post-clone bootstrap The remaining stages are implemented by the standalone repository script `bootstrap.nu`. It intentionally runs outside chezmoi application and starts Nushell with `--no-config-file`, so it does not depend on the configuration or packages it is about to install. [ ] `cd ~/.local/share/chezmoi` [ ] `nu --no-config-file ./bootstrap.nu --plan` Review the ordered operations. [ ] `nu --no-config-file ./bootstrap.nu` The script stops on command errors, displays the chezmoi diff and dry-run before asking permission to apply, pauses for the licensed-font drive, and pauses for exactly one labeled YubiKey at a time. It never commits, moves jj bookmarks, pushes, or reboots. The detailed stages below document what it performs and remain the manual recovery path. Recovery/diagnostic options: - `--font-source `: supply the mounted licensed-font directory instead of entering it at the prompt. - `--skip-fonts`: skip the licensed-font drive ceremony. - `--skip-secrets`: skip YubiKey/SOPS/SSH setup. - `--skip-themes`: skip network downloads and public theme installation. - `--skip-auth-tests`: install SSH outputs without the per-YubiKey remote-login confirmations (the automated `ssh -G` identity checks still run). - `--test-stop-after `: stop after a named stage (`chezmoi-review`, `fonts`, `packages`, `apply`, `secrets`, `themes`). Test-harness checkpoint; not part of the normal bootstrap workflow. - `--yes`: accept confirmation prompts; physical-action instructions still print. Use only for controlled testing or reruns. ## Stage 2.5: Restoring licensed fonts Proprietary fonts (PragmataPro Mono, Berkeley Mono) cannot live in this public repo, so they are restored from a flash drive before `chezmoi apply` installs the configs that reference them. Doing this before apply means the terminals and DankMaterialShell resolve the real families on first launch instead of caching a fallback. [ ] Insert and mount the flash drive holding the fonts. [ ] `let font_source = ""` [ ] `mkdir ~/.local/share/fonts` [ ] `let font_files = (glob $"($font_source)/**/*.{otf,ttf}")` [ ] `if ($font_files | is-empty) { error make {msg: "No .otf or .ttf files found on the font drive"} }` [ ] `$font_files | each {|font| cp $font ~/.local/share/fonts/ }` [ ] `glob ~/.local/share/fonts/*.{otf,ttf} | each {|font| chmod 644 $font }` [ ] `fc-cache --force ~/.local/share/fonts` [ ] `fc-match "PragmataPro Mono"` Confirm it names PragmataPro Mono, not a fallback. [ ] `fc-match "Berkeley Mono"` Confirm it names Berkeley Mono, not a fallback. [ ] Unmount the flash drive. ## Stage 3: Installing packages and applying the dotfiles The tracked Nushell configuration invokes `carapace` and `starship` during startup, so `bootstrap.nu` restores the Brewfile before launching Nushell normally. [ ] On the first run, `chezmoi init` prompts for an email address and GitHub username (from `home/.chezmoi.toml.tmpl`); the answers are stored in `~/.config/chezmoi/chezmoi.toml`. The script runs this step in the foreground so the prompts are visible. [ ] `bootstrap.nu` trusts the third-party entries declared in `home/dot_Brewfile` and restores Flatpaks, formulae/casks, Cargo packages, and VS Code extensions in dependency-safe stages. [ ] `bootstrap.nu` preserves the temporary Tangled SSH config while packages, fonts, SOPS identities, generated SSH outputs, and themes are prepared. [ ] `bootstrap.nu` performs the single real `chezmoi apply` near the end, only after those prerequisites and generated assets are ready. [ ] After the script finishes, `nu` loads the applied configuration and helper scripts. ## Stage 4: Applying secrets `bootstrap.nu` performs this interactively, requiring exactly one labeled YubiKey at a time. Because it runs with `--no-config-file`, it explicitly sets `PCSCLITE_CSOCK_NAME=/run/pcscd/pcscd.comm` and validates that socket before using age-plugin-yubikey; it does not wait for chezmoi to apply `environment.d/pcsclite.conf`. These commands remain the manual recovery path. ### 4.1 - Create the baseline directories [ ] `mkdir ~/.config/sops/age` [ ] `chmod 700 ~/.config/sops` [ ] `chmod 700 ~/.config/sops/age` ### 4.2 - YubiKey age identity loop, repeat for each YubiKey [ ] `age-plugin-yubikey --identity | save -f ~/.config/sops/age/yubikey-