summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md7
-rw-r--r--README.md10
-rw-r--r--docs/canonical-laptop.md234
3 files changed, 248 insertions, 3 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 5c17d79..c614a30 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,7 +1,8 @@
# Dotfiles Repository Notes
This is a personal dotfiles repository for an Arch Linux host and an Ubuntu
-remote-dev VM. The repo root is a chezmoi source directory.
+remote-dev VM, plus a Canonical Ubuntu GNOME laptop. The repo root is a chezmoi
+source directory.
## Layout
@@ -33,6 +34,10 @@ remote-dev VM. The repo root is a chezmoi source directory.
- `host`: user dotfiles plus host-only `/etc`, Firefox/LibreWolf, and Flatpak
integration hooks.
- `vm`: user dotfiles, skipping host-only `/etc` and Firefox/LibreWolf hooks.
+- `canonical`: an explicit home-file allowlist, shared Nix CLI tools, and GNOME.
+ Package lists are in `meta/canonical/`. Do not deploy the Arch `etc/` tree,
+ personal keys, Sway units, or pass-secret-service. Keep authd/GDM, GNOME
+ Keyring, and company policies intact. See `docs/canonical-laptop.md`.
- Machine-specific dotfile behavior belongs in chezmoi templates keyed by
`machineRole`.
- The VM Home-Manager profile installs packages and session variables only. Do
diff --git a/README.md b/README.md
index 82616c9..9205b49 100644
--- a/README.md
+++ b/README.md
@@ -139,7 +139,7 @@ Verify with `sudo nft list ruleset`.
## Git hooks
-The user-level hooks at `~/.config/git/hooks/` (set as `core.hooksPath` in `dot_config/git/config`) apply globally and auto-dispatch into the repo's hooks if present. Lookup order, first wins:
+On the personal host, the user-level hooks at `~/.config/git/hooks/` (set in `dot_config/git/config.tmpl`) apply globally and dispatch into project hooks. The corporate role uses project hooks only. Lookup order for the global dispatcher, first wins:
1. `<git-dir>/hooks/<name>` — the classic untracked per-clone location (where `husky` / `lefthook` / `pre-commit` install by default). Use this to replace a tracked hook on a shared repo without affecting teammates.
2. `<repo-top>/.githooks/<name>` — the project's tracked, shared hook.
@@ -149,7 +149,7 @@ Projects opt in by just dropping a file at `.githooks/<name>` — no `core.hooks
- `pre-commit` → repo's `.githooks/pre-commit` (if any). No global logic. In this repo: `just check`.
- `commit-msg` → repo's `.githooks/commit-msg` (if any), then strips any `Co-authored-by:` whose identity matches an AI agent (Copilot/Claude/Codex/…) so they don't trip the push gate.
- `pre-push` → repo's `.githooks/pre-push` (if any), then rejects pushes that contain unsigned commits or commits whose author/committer/coauthor looks like an AI agent.
-- `post-commit` → repo's `.githooks/post-commit` (if any). No global logic. In this repo: `chezmoi apply`.
+- `post-commit` → repo's `.githooks/post-commit` (if any). In this repo it prints a deployment reminder. Commits do not deploy files.
Bypass any of these with `--no-verify` on `commit`/`push`.
@@ -168,3 +168,9 @@ Recovery on a fresh install: run `bootstrap.sh`, then `gpg --import` + `pass ini
```sh
xdg-mime default org.mozilla.thunderbird.desktop x-scheme-handler/mailto
```
+
+# Canonical Laptop
+
+Use the [corporate laptop guide](docs/canonical-laptop.md) for the `canonical`
+role. It uses Ubuntu GNOME, Snap GUI apps, selected Flatpaks, and shared Nix
+tools. Do not use the Arch or remote-VM bootstrap on that machine.
diff --git a/docs/canonical-laptop.md b/docs/canonical-laptop.md
new file mode 100644
index 0000000..7b82e27
--- /dev/null
+++ b/docs/canonical-laptop.md
@@ -0,0 +1,234 @@
+# Canonical Laptop
+
+Target: Ubuntu 26.04 LTS on the company ThinkPad T14 Gen 6, with GNOME/GDM.
+Use the `canonical` role. Do not use the Arch bootstrap or the old VM bootstrap.
+
+## Company Provisioning
+
+1. Download the current LTS image from [Ubuntu](https://ubuntu.com/download/desktop).
+2. [Verify the image](https://ubuntu.com/tutorials/how-to-verify-ubuntu#1-overview)
+ and [make the USB installer](https://documentation.ubuntu.com/desktop/en/latest/how-to/create-a-bootable-usb-stick/).
+3. Use the current corporate autoinstall file from the internal guide. Do not
+ put that file, its registration key, or company credentials in this repo.
+4. Select encrypted storage **with LVM**. Use different passwords for disk
+ encryption and login. Verify both choices before starting installation.
+5. Complete Landscape registration with the temporary account, as instructed
+ by the company. Reboot and log in through Google/authd with the final work
+ account. Wait for provisioning and sudo access to complete.
+6. Set the time zone to Europe/Lisbon. Confirm registration:
+
+ ```sh
+ sudo landscape-config --actively-registered
+ ```
+
+Do all remaining steps as the **final work account**, without a root shell.
+Do not change its login shell. Do not disable company lock, suspend, AppArmor,
+network, update, or account policies. This repo does not own those policies.
+
+## Install Nix and Get the Repo
+
+Install [upstream multi-user Nix](https://nixos.org/download/):
+
+```sh
+curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh -s -- --daemon
+```
+
+Open a new terminal. Check `nix --version`. If Nix is already installed, inspect
+its owner first; do not run another installer over it.
+
+```sh
+sudo apt-get update
+sudo apt-get install git
+git clone https://github.com/sommerfelddev/dotfiles "$HOME/dotfiles"
+cd "$HOME/dotfiles"
+nix --extra-experimental-features 'nix-command flakes' develop ./nix
+CHEZMOI_MACHINE_ROLE=canonical chezmoi init -S .
+```
+
+Enter your work name, Canonical email, and full work GPG signing fingerprint.
+These values stay in the local chezmoi config. Check that `chezmoi data` reports
+`machineRole` as `canonical`. Do not accept `host` or `vm` for this laptop.
+
+## Deploy
+
+Run these commands on the laptop, not inside aibox:
+
+```sh
+just test
+just canonical-setup
+```
+
+This installs declared packages, builds the locked Home-Manager profile,
+deploys the corporate home files, loads two program-specific AppArmor profiles,
+connects Thunderbird's GPG interface, and installs the GNOME extensions.
+It does not remove packages or switch to another source when installation fails.
+
+Log out and back in through GDM. Then run:
+
+```sh
+cd "$HOME/dotfiles"
+just canonical-desktop
+just canonical-check
+```
+
+The extension schemas can be unavailable until the first new login. Repeat
+`canonical-desktop` after that login if it reported missing schemas. Keep Ubuntu
+AppIndicator enabled for tray icons. Disable Ubuntu Tiling Assistant in the
+Extensions app if it conflicts with PaperWM. Do not override a policy lock.
+
+Ghostty starts Nix zsh as a login shell. It does not change the authd account's
+shell. GNOME keeps its own desktop environment and GNOME Keyring. `pass` remains
+a terminal tool; this role does not install the pass Secret Service daemon.
+
+## Package Sources
+
+| Source | Applications |
+| -------------- | -------------------------------------------------------------------------------- |
+| Snap, stable | Firefox, Thunderbird, Ghostty, Mattermost, Zoom, Okular, LibreOffice, Keybase |
+| Flatpak, user | Nheko work profile, Zathura, NormCap, GPU Screen Recorder |
+| Nix | Shared CLI and AI tools, Neovim, zsh, Podman, GPG, desktop helper commands |
+| apt exceptions | Git, Flatpak, uidmap, Copyous libraries, zbar-tools, pinentry-gnome3, python3-gi |
+
+The lists are in `meta/canonical/`. Ghostty's classic confinement is explicit.
+The stable Keybase GUI has an old Electron dependency; its risk was accepted
+for this setup. Installing the Snap does not remove that risk.
+The Snap package also starts Electron with its internal sandbox disabled.
+Snap confinement is a separate layer.
+
+## Work Keys and Containers
+
+Transfer and import only the existing **work** secret key through a protected
+channel. Do not copy personal or former-employer keyrings. Check:
+
+```sh
+gpg --list-secret-keys --with-keygrip
+gpg --export-ssh-key YOUR_WORK_FINGERPRINT
+gpg-connect-agent 'keyinfo --list' /bye
+ssh-add -L
+git var GIT_AUTHOR_IDENT
+```
+
+Add the work authentication subkey's keygrip to the local `~/.gnupg/sshcontrol`
+if it is not exposed by the agent. That file is not deployed by this role.
+Use `~/.ssh/config.local` for work host rules. Register the public key with the
+required services. Do not enable agent forwarding.
+
+The Nix agent uses Ubuntu's user sockets and graphical pinentry. Log out and
+back in after the first deployment so an older agent does not remain active.
+Test one signed Git commit and one SSH connection before moving work to this
+machine. Do not expose the private key or full agent logs in support requests.
+
+Rootless Podman needs subordinate UID and GID ranges for the final authd user:
+
+```sh
+getsubids "$USER"
+getsubids -g "$USER"
+podman info
+podman run --rm docker.io/library/alpine:latest id
+```
+
+If either range is missing, have a free, non-overlapping range assigned through
+the system's account administration method. Do not copy another user's ranges
+or assume that an authd user can be changed with `usermod`. The setup does not
+rewrite `/etc/subuid`, `/etc/subgid`, or company account data.
+
+The repo loads only `dotfiles-nix-bwrap` and `dotfiles-nix-podman` AppArmor
+profiles. Global user-namespace restrictions stay enabled. Test `aibox -p` and
+a rootless container. If AppArmor denies another executable, inspect the exact
+denial before adding a rule. Do not allow every program under `/nix/store`.
+
+## Browser and Mail
+
+Start Firefox and Thunderbird once, then close them. Run:
+
+```sh
+just canonical-profiles
+```
+
+This discovers profiles from each Snap's `profiles.ini`, saves an initial
+`user.js.pre-dotfiles` backup, and replaces only the marked preference block.
+It keeps existing preferences outside that block. New profiles need another
+run. The personal Arkenfox profile, accounts, passwords, and Thunderbird cache
+are not imported.
+
+Add work accounts through the applications. Thunderbird autostarts as a normal
+window; there is no scratchpad or Birdtray. Enable system notifications in its
+settings and test a message from a different account.
+
+For external GPG, `canonical-system` connects `thunderbird:gpg-keys` and the
+managed preferences enable external GnuPG. Select the external work key in
+Thunderbird's account settings. Test signing and decryption.
+
+For Neovim compose, install External Editor Revived from Thunderbird Add-ons.
+`canonical-profiles` installs the host native-messaging manifest for the Nix
+helper. The Ubuntu Thunderbird Snap supplies native-messaging portal support.
+Approve the portal prompt. Configure the add-on's custom editor to start a
+separate Ghostty process, run Nix Neovim on its supplied file, and wait for exit.
+Use the add-on's file placeholder, not a fixed draft filename. Disable Ghostty
+single-instance reuse for this command (`--gtk-single-instance=false`). Test
+that closing Neovim returns the text to the draft. Do not use a Flatpak host
+wrapper or grant access to the full home directory to fix a failed test.
+
+PDF files use Zathura. Test a PDF attachment with spaces and accented letters
+in its name. Okular is also available. Re-select Zathura in the application
+chooser if an old portal choice overrides the default.
+
+## Desktop Checks
+
+Mattermost, Keybase, Thunderbird, and one Nheko `work` profile autostart through
+GNOME. In Nheko, enable its tray and start-in-tray options for that profile.
+Disable duplicate application-owned autostart entries. Test notifications with
+another account, not a message to yourself.
+
+The managed shortcuts are listed in `KEYBINDS.md`. Settings are reapplied by
+`just apply` in GNOME. Policy-locked keys are reported and skipped. Only touched
+keys are saved in `~/.local/state/dotfiles/gnome-settings.json`.
+
+```sh
+just canonical-desktop-restore
+```
+
+Restore skips keys changed since deployment. It does not reset all of dconf.
+
+Check these operations both docked and undocked:
+
+- PaperWM focus, window movement, terminal and browser launch.
+- Lock, unlock, suspend, resume, lid state, and external monitors.
+- HP webcam selection with `rqr`; the integrated camera when undocked.
+- A Google Meet camera, microphone, speaker, and screen-share session.
+- `ocr` with NormCap and `ocr image.png` with Tesseract. Add English and
+ Portuguese recognition data in NormCap's settings.
+- `dictate` twice: start recording, then transcribe to the clipboard. Paste
+ manually. GNOME does not use the Sway `wtype` path.
+- `record start`, portal selection, `record status`, then `record stop`.
+ Check the output in `~/vids`. Also test cancellation of the portal prompt.
+- `wqr`, Copyous history, and Emoji Copy.
+
+No existing laptop camera IDs, udev rules, firewall rules, power workarounds,
+or dock settings are copied to this machine.
+
+## Updates and Rollback
+
+`just update` upgrades apt packages, refreshes Snaps without overriding holds,
+updates declared Flatpaks, refreshes Nix inputs and release locks, updates
+Neovim, and updates the declared extensions. It does not run apt autoremove or
+dist-upgrade. Snap refresh also covers other installed Snaps; snapd still owns
+automatic refresh and company controls.
+
+Use `just nix-daemon-update` separately for the upstream Nix engine. It updates
+the root-owned default Nix profile, not the Home-Manager package inputs. Nix
+database changes can make an engine downgrade unsafe; consult the upstream
+upgrade instructions before downgrading.
+
+Keep the previous Home-Manager generation until the new one passes the checks.
+Use `home-manager generations` to find its activation path. Restore GNOME keys
+with the recipe above. Remove only the `dotfiles-*` XDG autostart entries to
+stop repo-owned startup. Do not remove company software during rollback.
+
+## Validation Boundary
+
+`just test` checks package commands, template identities, and role file
+boundaries. CI also checks formatting, lint, and Nix profile evaluation. These
+checks do not prove that Snap portals, the dock, authd, or GNOME extensions work
+on the real laptop. Complete the desktop checks after provisioning before
+depending on this machine for meetings.