From f0c626059451e1f8621600e610240739d5633560 Mon Sep 17 00:00:00 2001 From: sommerfeld Date: Thu, 2 Jul 2026 11:35:35 +0100 Subject: Prune stale dotfiles commentary --- AGENTS.md | 13 ++ dot_config/containers/storage.conf.tmpl | 23 +--- dot_config/nvim/lua/plugins/lsp.lua | 4 +- dot_config/nvim/lua/plugins/session.lua | 4 +- dot_config/zsh/dot_zprofile | 9 +- dot_config/zsh/dot_zshrc | 21 +--- etc/nftables.conf | 15 +-- etc/pacman.conf | 2 - etc/systemd/logind.conf.d/10-ignore-power-key.conf | 12 +- etc/systemd/logind.conf.d/20-lid-ac.conf | 14 +-- etc/systemd/network/30-ethernet-bond0.network | 4 +- meta/base.txt | 94 +++------------ nix/common.nix | 104 ++++------------ nix/host.nix | 132 ++++++--------------- nix/vm.nix | 10 +- run_onchange_after_deploy-etc.sh.tmpl | 26 +--- run_onchange_after_deploy-tb-eer.sh.tmpl | 15 +-- 17 files changed, 112 insertions(+), 390 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b7da485 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,13 @@ +# Agent Notes + +- Keep comments in config files operational. Prefer section labels and short + purpose notes; avoid migration history or explanations that only justify an + old decision. +- Package placement: pacman owns system-coupled pieces; Home-Manager owns + user-leaf tools; project compilers/linkers belong in per-project Nix dev + shells via direnv. +- Do not add global Home-Manager packages that shadow the system build + toolchain (`gcc`, `clang`, `ld`, `make`, `pkg-config`, language runtimes, + etc.) unless the user explicitly asks for that tradeoff. +- On the Arch host, keep GPU/OpenGL Wayland apps in pacman unless they have + been smoke-tested from Nix against the host graphics stack. diff --git a/dot_config/containers/storage.conf.tmpl b/dot_config/containers/storage.conf.tmpl index 62dd35c..c304b02 100644 --- a/dot_config/containers/storage.conf.tmpl +++ b/dot_config/containers/storage.conf.tmpl @@ -1,31 +1,14 @@ {{- $machineRole := default "host" (index . "machineRole") -}} {{- if eq $machineRole "vm" -}} -# Rootless podman storage configuration. -# -# The VM uses ext4, so use the kernel overlay driver. runroot/graphroot default -# to $XDG_RUNTIME_DIR/containers and $XDG_DATA_HOME/containers/storage. +# Rootless podman storage configuration: VM ext4. [storage] driver = "overlay" [storage.options.overlay] -# Kernel >=5.13 supports rootless overlay natively on the VM, so leave -# mount_program unset and avoid fuse-overlayfs. {{- else -}} -# Rootless podman storage configuration. -# -# Uses the native kernel btrfs graph driver — much faster than fuse-overlayfs -# (especially `podman commit`) because layers are real btrfs subvolumes with -# CoW snapshots, no FUSE userspace round-trip. -# -# Switching driver requires a one-time `podman system reset --force`; the -# overlay/fuse-overlay on-disk layout is incompatible. See the migration -# helper at the dotfiles repo root (migrate-podman-to-btrfs.sh). -# -# graphroot/runroot left at defaults: -# graphroot = $XDG_DATA_HOME/containers/storage -# runroot = $XDG_RUNTIME_DIR/containers -# both are on btrfs in this setup (root fs is btrfs). +# Rootless podman storage configuration: host btrfs. +# Changing storage drivers requires `podman system reset --force`. [storage] driver = "btrfs" diff --git a/dot_config/nvim/lua/plugins/lsp.lua b/dot_config/nvim/lua/plugins/lsp.lua index 51c8a2d..3f2f11c 100644 --- a/dot_config/nvim/lua/plugins/lsp.lua +++ b/dot_config/nvim/lua/plugins/lsp.lua @@ -10,9 +10,7 @@ pcall(vim.lsp.enable, "tblgen_lsp_server") require("fidget").setup({}) -- LSPs come from Home-Manager (see nix/common.nix). lspconfig ships the --- default configs; we just opt-in per server. (Previously this was driven --- by mason-lspconfig handlers; phase p6 of the nix migration removed --- Mason entirely.) +-- default configs; we just opt in per server. vim.lsp.enable({ "autotools_ls", "basedpyright", diff --git a/dot_config/nvim/lua/plugins/session.lua b/dot_config/nvim/lua/plugins/session.lua index 30d5767..e7c28ef 100644 --- a/dot_config/nvim/lua/plugins/session.lua +++ b/dot_config/nvim/lua/plugins/session.lua @@ -1,6 +1,4 @@ --- overseer.nvim removed task bundles (commit "refactor!: task bundles get --- the axe"), so auto-session no longer persists tasks. Only DAP breakpoints --- are preserved across sessions below. +-- Persist DAP breakpoints across auto-session saves. require("auto-session").setup({ use_git_branch = true, diff --git a/dot_config/zsh/dot_zprofile b/dot_config/zsh/dot_zprofile index 9150382..cc92558 100644 --- a/dot_config/zsh/dot_zprofile +++ b/dot_config/zsh/dot_zprofile @@ -20,13 +20,8 @@ export XDG_DATA_HOME="$HOME/.local/share" export XDG_STATE_HOME="$HOME/.local/state" export XDG_CACHE_HOME="$HOME/.cache" -# Pull in /etc/profile + /etc/profile.d/*.sh. The Arch zsh package used -# to ship /etc/zsh/zprofile doing exactly this, but we removed system -# zsh in favour of nix's zsh, so we replicate it here. This is how -# flatpak (XDG_DATA_DIRS for app launchers), nix-daemon, locale, etc. -# inject themselves into login shells. Sourced AFTER our PATH setup so -# `typeset -U path` keeps nix-profile/bin + ~/.local/bin at the front -# even if /etc/profile.d snippets try to prepend duplicates. +# Pull in distro profile snippets for XDG_DATA_DIRS, nix-daemon, locale, etc. +# Sourced after PATH setup so user-managed bins stay first. [[ -r /etc/profile ]] && emulate sh -c 'source /etc/profile' # Home Manager writes host-specific session variables here. Keep this after diff --git a/dot_config/zsh/dot_zshrc b/dot_config/zsh/dot_zshrc index 113955c..d432e45 100644 --- a/dot_config/zsh/dot_zshrc +++ b/dot_config/zsh/dot_zshrc @@ -43,11 +43,7 @@ PROMPT='%B%{$fg[green]%}%n%{$reset_color%}@%{$fg[cyan]%}%m%{$reset_color%}:%b%{$ # ── Completion ──────────────────────────────────────────────────────────────── fpath=($XDG_DATA_HOME/zsh/completion $fpath) -# Pull in completions from both nix-installed packages AND the system -# package manager (pacman on Arch host, apt on Ubuntu VM). nix zsh's -# default fpath only includes its own nix-store dirs, so without these -# entries we miss completions for pacman, systemctl, flatpak, -# docker, kubectl, etc. on the host, and apt/snap on the VM. +# Pull in completions from the Nix profile and distro packages. for _d in "$HOME/.nix-profile/share/zsh/site-functions" \ "$HOME/.nix-profile/share/zsh/vendor-completions" \ /usr/share/zsh/site-functions \ @@ -437,13 +433,7 @@ alias gdbr='gdb -ex start --args' alias copilot='gh copilot --autopilot --enable-all-github-mcp-tools --yolo --resume' # ── Alias completions ───────────────────────────────────────────────────────── -# Guard each compdef on the target's completion function actually being -# loaded; otherwise zsh prints `compdef: unknown command or service: foo` -# on every login (the binary being present isn't enough — the zsh -# completion file `_foo` must be in fpath and registered by compinit). -# Notably triggers on the remote-dev VM where nix-installed packages -# ship completions into /home/.../share/zsh/site-functions but Ubuntu's -# system zsh doesn't add that path to fpath by default. +# Guard compdef calls on registered completion functions. # Usage: _dot_compdef = [=...] _dot_compdef() { (( $+_comps[$1] )) && compdef "${@:2}" } _dot_compdef git g=git @@ -454,9 +444,7 @@ _dot_compdef lsd l=lsd la=lsd lt=lsd unfunction _dot_compdef # ── GPG agent ───────────────────────────────────────────────────────────────── -# Interactive shells can outlive the login environment that spawned them -# (notably inside zellij). If they inherited an old forwarded-agent socket, -# switch back to the machine-local gpg-agent SSH socket. +# Prefer the machine-local gpg-agent SSH socket. if [[ -z "$SSH_AUTH_SOCK" || "$SSH_AUTH_SOCK" == /tmp/ssh-* || "$SSH_AUTH_SOCK" == "$HOME/.ssh/agent.sock" ]]; then SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" export SSH_AUTH_SOCK @@ -490,8 +478,7 @@ _fzf_compgen_path() { fd --hidden --follow --exclude ".git" . "$1" } _fzf_compgen_dir() { fd --type d --hidden --follow --exclude ".git" . "$1" } # ── Plugins (must be sourced last) ──────────────────────────────────────────── -# Plugin locations: ~/.nix-profile (Home-Manager) first, Arch system path as -# fallback for un-bootstrapped states. +# Plugin locations: Nix profile first, system path second. _source_first() { local f for f in "$@"; do diff --git a/etc/nftables.conf b/etc/nftables.conf index e4f68ed..355465a 100644 --- a/etc/nftables.conf +++ b/etc/nftables.conf @@ -1,8 +1,7 @@ #!/usr/bin/nft -f # vim:set ts=2 sw=2 et: -# IPv4/IPv6 Simple & Safe firewall ruleset. -# More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/. +# IPv4/IPv6 default-deny firewall ruleset. destroy table inet filter table inet filter { @@ -22,12 +21,6 @@ table inet filter { iifname "virbr0" udp dport { 53, 67 } accept comment "libvirt: DHCP+DNS from guests" iifname "virbr0" tcp dport 53 accept comment "libvirt: DNS over TCP from guests" - # Waydroid's NAT bridge: same pattern as libvirt. The Android container's - # DhcpClient broadcasts DHCPDISCOVER on waydroid0; without this rule it's - # dropped before dnsmasq sees it and the container never gets an IP. - iifname "waydroid0" udp dport { 53, 67 } accept comment "waydroid: DHCP+DNS from container" - iifname "waydroid0" tcp dport 53 accept comment "waydroid: DNS over TCP from container" - pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited counter } @@ -44,11 +37,5 @@ table inet filter { # load before libvirtd has created virbr0 at boot. iifname "virbr0" accept comment "libvirt: guest egress" oifname "virbr0" ct state established,related accept comment "libvirt: guest return" - - # Waydroid's NAT bridge: same pattern as libvirt. Waydroid's container - # service installs MASQUERADE itself via iptables-nft compat, so no - # explicit nat table is needed here -- only the forward-chain accepts. - iifname "waydroid0" accept comment "waydroid: guest egress" - oifname "waydroid0" ct state established,related accept comment "waydroid: guest return" } } diff --git a/etc/pacman.conf b/etc/pacman.conf index aaa7fef..f6e7e64 100644 --- a/etc/pacman.conf +++ b/etc/pacman.conf @@ -22,8 +22,6 @@ HoldPkg = pacman glibc Architecture = auto # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup -# llama.cpp-vulkan: formerly pinned as an AUR package because every upstream -# commit triggered a 1-2 hour rebuild. Kept as a reminder if it returns. #IgnorePkg = #IgnoreGroup = diff --git a/etc/systemd/logind.conf.d/10-ignore-power-key.conf b/etc/systemd/logind.conf.d/10-ignore-power-key.conf index 1ca4cc3..5b1dc15 100644 --- a/etc/systemd/logind.conf.d/10-ignore-power-key.conf +++ b/etc/systemd/logind.conf.d/10-ignore-power-key.conf @@ -1,14 +1,4 @@ [Login] -# Ignore KEY_POWER from any source. Misbehaving USB devices (cheap -# keyboards, KVM switches, headset dongles) sometimes emit KEY_POWER on -# enumeration, hot-plug, or for unrelated buttons -- and some emit a -# press without a matching release, which logind classifies as a -# long-press and acts on after 5s. Ignoring both short and long press -# is the only reliable policy without per-device evdev filtering. -# -# Real shutdowns: `systemctl poweroff` or GUI menus. The laptop's -# physical power button also emits KEY_POWER and is now a no-op for -# clean shutdowns; a very long hold (~10s) still triggers a firmware -# force-off as a last resort. +# Ignore KEY_POWER events, including long-press handling. HandlePowerKey=ignore HandlePowerKeyLongPress=ignore diff --git a/etc/systemd/logind.conf.d/20-lid-ac.conf b/etc/systemd/logind.conf.d/20-lid-ac.conf index 08e5014..6865232 100644 --- a/etc/systemd/logind.conf.d/20-lid-ac.conf +++ b/etc/systemd/logind.conf.d/20-lid-ac.conf @@ -1,14 +1,4 @@ [Login] -# Suspend policy: closing the lid suspends ONLY when on battery. When -# AC is connected the lid switch is ignored entirely. The rationale is -# simple and matches user mental model -- if you don't want the -# machine to sleep, plug it in. -# -# This obsoletes the previous SSH/zellij-aware inhibit machinery: any -# long-running task (build, download, SSH session, server) just needs -# AC and will never be suspended out from under itself. -# -# `HandleLidSwitch` (default = suspend) still applies on battery. -# `HandleLidSwitchDocked` (default = ignore) still applies when an -# external monitor / dock is attached. +# On AC, closing the lid does not suspend. Battery/docked behavior uses +# logind defaults. HandleLidSwitchExternalPower=ignore diff --git a/etc/systemd/network/30-ethernet-bond0.network b/etc/systemd/network/30-ethernet-bond0.network index 31f14a2..f58f7bd 100644 --- a/etc/systemd/network/30-ethernet-bond0.network +++ b/etc/systemd/network/30-ethernet-bond0.network @@ -1,7 +1,7 @@ # Match only real, physical ethernet via Path= (PCI + USB) and udev's # predictable name pattern. This is more robust than Type=ether + Name= negation: -# negations on Name= matched veth/virbr/waydroid interfaces in practice, which -# enslaved them into bond0 and broke host networking (waydroid, libvirt, etc.). +# negations on Name= matched virtual interfaces in practice, which enslaved +# them into bond0 and broke container/VM networking. # # Path=pci-* covers built-in PCIe NICs (enpXsY, ethN). # Path=platform-* covers SoC-attached NICs (none on x86 laptops but harmless). diff --git a/meta/base.txt b/meta/base.txt index 60a4a8a..b468783 100644 --- a/meta/base.txt +++ b/meta/base.txt @@ -1,12 +1,4 @@ -# --- core --- -# Leaf CLI / editor / multiplexer / git stack / json+yaml / system viewers / -# net / debug+trace / docs / secrets — all provisioned via Home-Manager -# from nix/common.nix and live under ~/.nix-profile/bin (first in PATH). -# What stays on pacman in this section is the pieces tightly coupled to -# the distro, the system runtime (sudo-rs, base), and things needed -# pre-bootstrap or by other system packages transitively. User-leaf -# CLIs/daemons/docs (chezmoi, man-db/man-pages, qrencode, torsocks, -# lshw, xdg-utils, syncthing) now come from nix. +# --- core system --- acpid arch-audit base @@ -25,9 +17,7 @@ lostfiles nfs-utils nftables ocl-icd -# Provides paccache for the repo-owned cache cleanup hook under -# etc/pacman.d/hooks/. -pacman-contrib +pacman-contrib # paccache for etc/pacman.d/hooks/pacman-cache-cleanup.hook reflector sbctl smartmontools @@ -45,21 +35,11 @@ ell # --- thunderbolt --- bolt -# --- nix (multi-user daemon mode for hermetic per-project dev shells via -# `nix develop` + direnv `use flake`. Not a replacement for pacman, -# not home-manager, not NixOS — just a sandboxed second package manager -# that gives every project a reproducible toolchain pinned in its own -# flake.lock. Pairs with: systemd-units/system.txt (enables -# nix-daemon.socket), etc/nix/nix.conf, dot_config/direnv/direnvrc, -# dot_config/nix/templates/. nix-direnv itself is loaded at runtime via -# direnv's source_url with a content hash, so no extra package needed.) --- +# --- nix daemon --- nix -# --- dev (system-coupled runtime only). No base-devel: AUR/makepkg is not -# part of the normal system, and project toolchains come from direnv + nix -# devShells. Build orchestrators, debuggers, and user CLIs live in -# nix/common.nix. --- -perf # links against running kernel ABI; must match kernel pkg +# --- kernel-coupled dev/debug --- +perf # running-kernel ABI # --- sound --- alsa-utils @@ -79,86 +59,42 @@ ttf-noto-nerd woff2-font-awesome # --- wayland session --- -# Compositor (ships /usr/share/wayland-sessions/sway.desktop — login-manager -# coupled, must stay on pacman). The user-leaf session tools — waybar, -# fuzzel, wofi, mako, swayidle, swayr, inhibridge, bemoji, grim, -# slurp, wf-recorder, wtype, wl-clipboard, cliphist, wob, -# poweralertd, playerctl, pulsemixer — now come from nix/host.nix. sway -# GPU/OpenGL & EGL apps kept on pacman (not nix/host.nix): nix-built GL apps -# on a non-NixOS host can't find the system Mesa/DRI driver and die with -# "missing OpenGL context". On pacman they link against system Mesa. -ghostty # GPU/OpenGL terminal -imv # OpenGL image viewer -wl-mirror # EGL output mirror +ghostty # GPU/OpenGL terminal +imv # OpenGL image viewer +wl-mirror # EGL output mirror xdg-desktop-portal-wlr xdg-desktop-portal-gtk qt5-wayland qt6-wayland -# Notifications: libnotify provides the system shared lib that other -# pacman packages link against; the user-facing mako daemon is nix. libnotify -# Lock screen (setuid; PAM-coupled) +# --- lock screen --- swaylock -# Ships ZSA's upstream udev rules (50-oryx.rules, 50-wally.rules) to -# /usr/lib/udev/rules.d/ so VID 3297 hidraw nodes get TAG+=uaccess. -# Required for VIA / usevia.app (WebHID) and Wally flashing of the -# ErgoDox EZ / Moonlander / Voyager. +# --- hardware access rules --- zsa-udev -# QR (system lib used by zbarcam; the qrencode CLI is in nix/host.nix) +# --- QR camera --- zbar -xorg-xwayland # needed for zbarcam's X11 preview +xorg-xwayland # zbarcam preview -# Document viewer is the org.pwmt.zathura flatpak (see meta/flatpak.txt) so -# PDFs handed off from the browser/mail sandbox stay sandboxed. - -# Misc +# --- desktop helpers --- brightnessctl -# Userspace sandbox helper (firejail-less). Used by ~/.local/bin wrappers -# for mpv/yt-dlp/streamlink to hide secrets from network parsers; also -# pulled transitively by flatpak. bubblewrap libfido2 qt5ct qt6ct xdg-user-dirs -# --- mail (host-side bits the org.mozilla.thunderbird flatpak depends on) --- -# protonmail-bridge now comes from nix/host.nix (the bridge binary + its -# repo-owned user unit dot_config/systemd/user/protonmail-bridge.service). -# git-send-email support is provided by nix/common.nix's git package, which -# wraps git-send-email with the needed SMTP/SASL Perl libraries. -# (External Editor Revived's native-messaging host is installed via nix -# on the host — see nix/host.nix — so we don't pay the AUR variant's -# hard `thunderbird` dependency. The bridge into the TB flatpak is -# wired up by run_onchange_after_deploy-tb-eer.sh.tmpl.) - -# --- media (mpv is the io.mpv.Mpv flatpak in meta/flatpak.txt; streamlink -# and yt-dlp now come from nix/host.nix and pipe/launch into the flatpak -# mpv via `flatpak run io.mpv.Mpv`, see dot_config/streamlink/config. -# Bitcoin wallet comes from nix/host.nix.) --- - # --- desktop extras --- udisks2 tor -# Flatpak runtime (apps tracked in meta/flatpak.txt) +# --- flatpak runtime --- flatpak -# Smartcard stack (cartão de cidadão reader + PKCS#11 bridge into flatpak -# browsers). pcscd.socket is enabled by systemd-units/system.txt. pcsclite -# itself is also needed by Home-Manager's gnupg/scdaemon (see nix/host.nix's -# scdaemon.conf — points scdaemon at /usr/lib/libpcsclite.so.1). +# --- smartcards --- pcsclite ccid - -# --- OCR + STT moved to nix/host.nix --- -# tesseract (+ eng/por language data merged via override) and whisper-cpp -# (+ vulkan support, + inline ggml-base.bin model derivation) now come -# from nix/host.nix. The ~/.local/bin/dictate script defaults to -# ~/.nix-profile/share/whisper-cpp-models/ggml-base.bin (overridable via -# WHISPER_MODEL). diff --git a/nix/common.nix b/nix/common.nix index 7290395..c256aa2 100644 --- a/nix/common.nix +++ b/nix/common.nix @@ -1,31 +1,12 @@ -{ config, pkgs, lib, dotfilesRoot, ... }: +{ + config, + pkgs, + lib, + dotfilesRoot, + ... +}: -# Shared Home-Manager module: ONLY package installation. Dotfile deployment is -# owned by chezmoi on both the Arch host and the remote-dev VM. Keeping this -# module deployment-agnostic prevents home-manager from conflicting with -# chezmoi-owned files (which would otherwise materialize as `.backup` files on -# every `nix-switch`). -# -# Policy: this profile carries leaf CLI tools, editor/AI-agent runtimes -# (node, uv), and build *orchestrators* (cmake, ninja, ccache, sccache). -# It must NEVER carry actual compilers or linkers — those would shadow -# the system's and silently link projects against nixpkgs glibc/libstdc++ -# instead of the system sysroot. -# -# Forbidden on PATH from this module: cc, c++, gcc, g++, clang, clang++, -# ld, ld.lld, ar, nm, objcopy, make, meson, pkg-config, autoconf, -# automake, libtool, python, python3, pip, cargo, rustc, go. -# -# Allowed: orchestrators that delegate to whatever compiler is in PATH -# (cmake, ninja, ccache, sccache), instrumentation/analysis that hooks -# at the syscall/library boundary (valgrind, gdb, lldb, strace), and -# source-only tooling (doxygen, clang-tools — clangd/clang-format/ -# clang-tidy, no compiler driver). Project-specific compilers/linkers -# go in project-local flake.nix + direnv `.envrc`, NOT here. -# -# Editor/AI runtimes: node, npm, npx (via `nodejs`), uv, uvx (via `uv` -# — manages its own python interpreters under XDG, doesn't install a -# system python3). +# Shared Home-Manager package profile. Chezmoi owns dotfile deployment. { home.stateVersion = "25.05"; @@ -53,8 +34,6 @@ glow # Git stack - # Includes git-send-email: nixpkgs wraps it with the SMTP/SASL Perl deps - # it needs, so we don't carry distro Perl modules just for email support. (git.override { sendEmailSupport = true; }) gh delta @@ -94,19 +73,15 @@ openssh mosh - # Debug / trace / profile — moved off pacman. User policy: only - # used against own builds, so glibc/kernel version skew vs the - # system isn't an issue. Only `perf` stays system (it links against - # the running kernel ABI; pacman's matches the kernel package). + # Debug / trace / profile gdb - lldb # also brings lldb-dap (used by dap.lua via type="lldb") + lldb # also brings lldb-dap (used by dap.lua via type="lldb") strace samply t-rec valgrind - # Build orchestrators — these only delegate to whatever compiler is - # in PATH; they don't ship cc/c++/ld themselves, so no shadowing. + # Build orchestrators cmake ninja ccache @@ -123,19 +98,12 @@ pandoc # Secrets — `pass-otp` is wired as an extension so `pass otp ...` - # works against the same store. `pass` from pacman is removed. + # works against the same store. gnupg pinentry-curses (pass.withExtensions (exts: [ exts.pass-otp ])) - # C/C++ source tooling (no compiler driver in PATH). - # clang-tools ships clangd/clang-format/clang-tidy and most of the - # python helpers (git-clang-format, clang-format-diff, clang-tidy-diff) - # but skips run-clang-tidy because the symlink loop in nixpkgs' - # clang-tools derivation gates on the +x bit and run-clang-tidy - # loses it during the multi-output split. Re-expose it ourselves - # from clang-unwrapped's `python` output (tries both the modern - # bin/ layout and the legacy share/clang/ layout). + # C/C++ source tooling clang-tools (runCommand "run-clang-tidy" { } '' mkdir -p $out/bin @@ -151,49 +119,33 @@ exit 1 '') - # CI runner (drives podman; act itself is just a Go binary) + # CI runner act # ── Rootless podman ───────────────────────────────────────────────────── - # Moved off pacman so the host and VM run the same nix-pinned stack. - # The nix `podman` is wrapped to find these helpers via /nix/store - # paths, so we don't need a containers.conf for `helper_binaries_dir`. - # Per-user containers config (registries/storage/policy) lives under - # chezmoi at `dot_config/containers/`. podman - crun # OCI runtime (lighter than runc; default for rootless) - conmon # container monitor process - netavark # default network stack on podman 4+ + crun # OCI runtime (lighter than runc; default for rootless) + conmon # container monitor process + netavark # default network stack on podman 4+ aardvark-dns # DNS for netavark networks - slirp4netns # rootless user-mode networking - passt # pasta backend (slirp4netns successor; podman picks it up) + slirp4netns # rootless user-mode networking + passt # pasta backend (slirp4netns successor; podman picks it up) podman-compose - # `docker` shell shim → podman. nixpkgs has no top-level - # `podman-docker` attr (Arch ships one as a convenience pkg); the - # NixOS option `virtualisation.podman.dockerCompat` exists but isn't - # reachable from home-manager, so we ship a one-line writer instead. + # `docker` shell shim → podman. (writeShellScriptBin "docker" ''exec ${podman}/bin/podman "$@"'') - # Editor/AI agent runtimes — NOT for project builds (see policy above) + # Editor/AI agent runtimes nodejs_24 # copilot-language-server requires Node 24 (see ai.lua) - uv # for project tooling that asks for `uv`/`uvx`; brings no python + uv # for project tooling that asks for `uv`/`uvx`; brings no python python3Packages.ipython # interactive REPL; pulls its own python, only `ipython` lands on PATH # AI coding agents claude-code - codex # OpenAI Codex CLI (rust rewrite); replaces pacman openai-codex-bin + codex # OpenAI Codex CLI github-copilot-cli # `copilot`; prebuilt-binary derivation since 1.0.43 tuicr # interactive git-change reviewer; flake input, see nix/flake.nix. Skill: dot_claude/skills/tuicr/ # ── LSPs / formatters / linters / DAPs ───────────────────────────────── - # Replaces Mason entirely (phase p6 of the nix migration rips out - # mason-tool-installer). The set tracks the previous - # `ensure_installed` list in dot_config/nvim/lua/plugins/lsp.lua, with - # five niche tools dropped: groovy-language-server (Mason-only build, - # upstream stale), npm-groovy-lint, nginx-language-server, - # nginx-config-formatter, systemdlint (all rarely-edited domains; - # losing them is acceptable). - # LSPs actionlint autotools-language-server @@ -208,7 +160,7 @@ systemd-language-server taplo typescript-language-server - vscode-langservers-extracted # cssls + html + jsonls + eslint + vscode-langservers-extracted # cssls + html + jsonls + eslint yaml-language-server # Formatters @@ -228,13 +180,7 @@ typos yamllint - # DAPs / debuggers — `lldb-dap` ships in pkgs.lldb (declared in the - # debug/trace block above). dap configs in plugins/debug.lua target - # it via `type = "lldb"`. - - # Zsh and plugins (loaded from $HOME/.nix-profile/share/... by the - # shared zshrc; nix-profile path is preferred, system path is the - # fallback for un-bootstrapped states). + # Zsh and plugins zsh zsh-completions zsh-syntax-highlighting diff --git a/nix/host.nix b/nix/host.nix index 5a3d8a9..c44319e 100644 --- a/nix/host.nix +++ b/nix/host.nix @@ -1,28 +1,14 @@ -{ config, pkgs, lib, dotfilesRoot, ... }: - -# Arch host Home-Manager profile. Layered on top of `common.nix`; adds -# only host-specific concerns that don't make sense on the VM (wayland -# session tools, Yubikey, host-only CLIs / GUIs). -# -# Dotfile deployment on the host is owned entirely by **chezmoi** (run -# via `just apply` / `just sync`). Home-Manager here only installs -# binaries and writes the host-only smartcard config below. -# -# Migration policy: a tool lives here iff nixpkgs ships a working -# equivalent AND it has no tight system coupling (no setuid, no -# /usr/lib/systemd/system unit, no udev rule, no system D-Bus -# activation, no /usr/share/wayland-sessions entry, no shared lib that -# other pacman pkgs link, no system fontconfig path, no PAM, no Qt -# plugin search path, no kernel/firmware/initramfs touchpoint). -# User-scope systemd units are NOT system coupling — nix drops them in -# ~/.nix-profile/share/systemd/user/ and systemd picks them up. +{ + config, + pkgs, + lib, + dotfilesRoot, + ... +}: + +# Arch host Home-Manager package profile. let - # Whisper.cpp base model — packaged inline because nixpkgs doesn't - # ship the .bin blobs. Sourced from the upstream huggingface mirror - # (same URL the AUR `whisper.cpp-model-base` uses). The dictate script - # at dot_local/bin/executable_dictate defaults to - # ~/.nix-profile/share/whisper-cpp-models/ggml-base.bin. whisper-cpp-model-base = pkgs.stdenvNoCC.mkDerivation rec { pname = "whisper-cpp-model-base"; version = "1.0"; @@ -70,10 +56,12 @@ let mainProgram = "pass-secret-service"; }; }; - arkenfox-userjs-profile = pkgs.runCommand "arkenfox-userjs-profile-${pkgs.arkenfox-userjs.version}" { } '' - install -Dm644 ${pkgs.arkenfox-userjs}/user.js $out/share/arkenfox-userjs/user.js - install -Dm644 ${pkgs.arkenfox-userjs}/user.cfg $out/share/arkenfox-userjs/user.cfg - ''; + arkenfox-userjs-profile = + pkgs.runCommand "arkenfox-userjs-profile-${pkgs.arkenfox-userjs.version}" { } + '' + install -Dm644 ${pkgs.arkenfox-userjs}/user.js $out/share/arkenfox-userjs/user.js + install -Dm644 ${pkgs.arkenfox-userjs}/user.cfg $out/share/arkenfox-userjs/user.cfg + ''; in { imports = [ ./common.nix ]; @@ -81,58 +69,29 @@ in home.username = builtins.getEnv "USER"; home.homeDirectory = builtins.getEnv "HOME"; - # Keep Nix's compiler out of PATH, but make it available to host Neovim for - # nvim-treesitter parser builds. The Nix-provided Neovim loads these parser - # .so files, so using the Nix compiler wrapper is the coherent ABI choice. + # Used by nvim-treesitter parser builds without adding a compiler to PATH. home.sessionVariables.NVIM_TREESITTER_CC = "${pkgs.stdenv.cc}/bin/cc"; home.packages = with pkgs; [ # ── Thunderbird helpers ─────────────────────────────────────────────────── - # external-editor-revived is the native-messaging host that lets the - # Thunderbird addon hand a composing draft to $EDITOR. We run TB as the - # org.mozilla.thunderbird flatpak; the AUR package would drag in system - # `thunderbird` as a hard dep, so we take it from nixpkgs here instead - # (the nix derivation has no mailer dep). The bridge wiring lives in - # run_onchange_after_deploy-tb-eer.sh.tmpl; it auto-detects the binary - # under ~/.nix-profile and the manifest gets relocated into the TB - # flatpak sandbox. external-editor-revived # ── Mail: ProtonMail Bridge ─────────────────────────────────────────────── - # Headless IMAP/SMTP gateway (127.0.0.1:1143/1025) consumed by the - # Thunderbird flatpak and `git send-email`. No system coupling: it's a - # pure user daemon with a repo-owned user unit at - # dot_config/systemd/user/protonmail-bridge.service (run --noninteractive, - # pass-backed vault via PASSWORD_STORE_DIR). Replaces the AUR - # `protonmail-bridge-core`. protonmail-bridge # ── Secrets portal ──────────────────────────────────────────────────────── - # Grimsteel's Rust org.freedesktop.secrets provider backed by pass. This is - # not nixpkgs' Python `pass-secret-service`; the repo-owned user unit at - # dot_config/systemd/user/pass-secret-service.service uses the Rust binary - # name and the PASSWORD_STORE_DIR drop-in. pass-secret-service-rust # ── Wayland session: bars, launchers, notifiers, daemons ────────────────── - # Pure user-session GUIs/daemons — no system unit, no D-Bus activation - # file under /usr/share/dbus-1, no login-manager session entry. The - # corresponding user-scope systemd units live under - # dot_config/systemd/user/ and reference these binaries by an absolute - # %h/.nix-profile/bin/ path. (Bare names do NOT work: systemd's - # ExecStart binary resolution does not use the imported/environment.d - # PATH of the --user manager, so a bare name fails with 203/EXEC even - # though `systemctl --user show-environment` shows the nix profile on - # PATH. The %h specifier expands to $HOME at unit-load time.) waybar mako fuzzel - wofi # used by bemoji + mako-history.sh + wofi # used by bemoji + mako-history.sh swayidle - swayr # auto-tiling + window switcher - inhibridge # browser idle-inhibit bridge → systemd-inhibit - bemoji # emoji picker (wofi backend) - wob # volume/brightness OSD + swayr # auto-tiling + window switcher + inhibridge # browser idle-inhibit bridge → systemd-inhibit + bemoji # emoji picker (wofi backend) + wob # volume/brightness OSD poweralertd # ── Wayland: capture + clipboard + image viewing ───────────────────────── @@ -140,70 +99,47 @@ in slurp wf-recorder wtype - wl-clipboard # wl-copy + wl-paste - cliphist # clipboard history (used by cliphist-{text,image} units) + wl-clipboard # wl-copy + wl-paste + cliphist # clipboard history (used by cliphist-{text,image} units) # ── Media control ──────────────────────────────────────────────────────── - playerctl # MPRIS over session bus - pulsemixer # TUI for PipeWire/PulseAudio - - # NOTE: GPU/OpenGL & EGL apps (ghostty, imv, wl-mirror) are - # intentionally NOT here — they stay on pacman/AUR. Nix-built GL apps on - # a non-NixOS host can't locate the system Mesa/DRI driver (the FHS - # /usr/lib drivers don't match nix's search paths) and fail at startup - # with "missing OpenGL context". On pacman they link against system Mesa. - # ghostty/imv/wl-mirror live in meta/base.txt. Sparrow is JavaFX-based and - # runs correctly from nix on the host. - - # ── General CLIs migrated off pacman ────────────────────────────────────── + playerctl # MPRIS over session bus + pulsemixer # TUI for PipeWire/PulseAudio + + # ── General CLIs ───────────────────────────────────────────────────────── qrencode torsocks lshw yt-dlp streamlink - xdg-utils # xdg-open, used by yazi/linkhandler/OPENER + xdg-utils # xdg-open, used by yazi/linkhandler/OPENER # ── File sync ─────────────────────────────────────────────────────────────── - # Package-only migration from pacman. The boot-time system service is the - # repo-owned syncthing@sommerfeld.service tracked in systemd-units/system.txt - # and backed by etc/systemd/system/syncthing@.service. syncthing # ── Work VPN ────────────────────────────────────────────────────────────── - # Check Point VPN client. The command-mode system service is repo-owned at - # etc/systemd/system/snx-rs.service and exposes the daemon that snxctl uses. snx-rs # ── Bitcoin wallet ─────────────────────────────────────────────────────── - # Replaces the former AUR wallet package after host GUI + BitBox smoke - # testing. sparrow # ── Browser hardening ──────────────────────────────────────────────────── - # Upstream Arkenfox user.js from nixpkgs, re-exposed under share/ so the - # chezmoi Firefox/LibreWolf deploy hook can render it with - # firefox/user-overrides.js into the Flatpak profile. arkenfox-userjs-profile # ── OCR ────────────────────────────────────────────────────────────────── - # Override merges eng + por language data into a single derivation, - # replacing three pacman packages (tesseract, tesseract-data-eng, - # tesseract-data-por). - (tesseract.override { enableLanguages = [ "eng" "por" ]; }) + (tesseract.override { + enableLanguages = [ + "eng" + "por" + ]; + }) # ── Speech-to-text (dictate script) ────────────────────────────────────── - # whisper.cpp with Vulkan acceleration. `mainProgram = "whisper-cli"` - # matches the binary the dictate script invokes. The base model below - # is a separate derivation so we can drop the AUR `whisper.cpp-model-base`. (whisper-cpp.override { vulkanSupport = true; }) whisper-cpp-model-base ]; # ── Smartcard (Yubikey) ──────────────────────────────────────────────────── - # Nix's gnupg ships its own scdaemon. Delegate to the system pcscd - # service instead of letting nix's scdaemon open the USB device - # directly (which would race with pcscd). `pcsclite` provides the - # shared library at the path below and stays in `meta/base.txt`. home.file.".gnupg/scdaemon.conf".text = '' disable-ccid pcsc-driver /usr/lib/libpcsclite.so.1 diff --git a/nix/vm.nix b/nix/vm.nix index 39bf52d..9e6352f 100644 --- a/nix/vm.nix +++ b/nix/vm.nix @@ -1,8 +1,6 @@ { ... }: -# VM-only Home-Manager profile (Ubuntu remote-dev box). This installs the -# shared tool profile and VM session variables only; dotfile deployment is -# owned by chezmoi, matching the Arch host. +# VM-only Home-Manager package profile. { imports = [ ./common.nix ]; @@ -10,14 +8,8 @@ home.homeDirectory = builtins.getEnv "HOME"; home.sessionVariables = { - # Ubuntu 20.04-derived hosts still default to cgroups v1; podman 5 - # warns on every invocation. Flipping to v2 is a host-level reboot - # and only matters for --memory/--cpus, so silence the warning. - # (Arch host is on cgroups v2, so this isn't set in common.nix.) PODMAN_IGNORE_CGROUPSV1_WARNING = "1"; }; - # No extra packages — the rootless podman stack now lives in - # `common.nix` so the host and VM share the same nix-pinned versions. home.packages = [ ]; } diff --git a/run_onchange_after_deploy-etc.sh.tmpl b/run_onchange_after_deploy-etc.sh.tmpl index 742ef82..50b0d98 100755 --- a/run_onchange_after_deploy-etc.sh.tmpl +++ b/run_onchange_after_deploy-etc.sh.tmpl @@ -38,36 +38,12 @@ fi # sudo-rs: /etc/pam.d/sudo-i is a symlink to /etc/pam.d/sudo sudo ln -sfT sudo /etc/pam.d/sudo-i -sudo rm -f /etc/systemd/system-sleep/50-snx-rs - -# Clean up sleep-target masks from the earlier hardened-suspend -# workaround. Now that mem_sleep_default=s2idle resolves the wake hang, -# suspend is enabled again. Remove any leftover /dev/null symlinks. -for target in sleep.target suspend.target hibernate.target \ - hybrid-sleep.target suspend-then-hibernate.target; do - link="/etc/systemd/system/$target" - if [ -L "$link" ] && [ "$(readlink "$link")" = "/dev/null" ]; then - sudo rm -f "$link" - fi -done +# Pick up changes to repo-managed systemd units and drop-ins under /etc. sudo systemctl daemon-reload # Reload systemd-logind so changes under /etc/systemd/logind.conf.d/ # (e.g. HandlePowerKey overrides) take effect without dropping sessions. sudo systemctl kill -s HUP systemd-logind - -# Old sudo-rs migration used /usr/local/bin to shadow classic sudo globally. -# Current policy keeps those shims user-scoped via ~/.local/bin/symlink_*. -for link in /usr/local/bin/sudoedit /usr/local/bin/su /usr/local/bin/visudo; do - target=$(readlink "$link" 2>/dev/null || true) - case "$target" in - /usr/bin/sudo-rs|/usr/bin/su-rs|/usr/bin/visudo-rs) sudo rm -f "$link" ;; - esac -done -target=$(readlink /usr/local/bin/sudo 2>/dev/null || true) -if [ "$target" = /usr/bin/sudo-rs ]; then - sudo rm -f /usr/local/bin/sudo -fi {{- else -}} #!/usr/bin/env dash # /etc deployment is host-only. diff --git a/run_onchange_after_deploy-tb-eer.sh.tmpl b/run_onchange_after_deploy-tb-eer.sh.tmpl index add406b..d48b8f7 100644 --- a/run_onchange_after_deploy-tb-eer.sh.tmpl +++ b/run_onchange_after_deploy-tb-eer.sh.tmpl @@ -1,9 +1,8 @@ #!/usr/bin/env dash # Bridge the External Editor Revived native messaging host into the -# org.mozilla.thunderbird flatpak. The host binary stays installed via -# pacman (`external-editor-revived`); we relocate the manifest into the -# sandbox and replace its binary path with a wrapper that re-enters the -# host via flatpak-spawn. +# org.mozilla.thunderbird flatpak. The host binary comes from the Nix +# profile; this script relocates the manifest into the sandbox and points it +# at a flatpak-spawn wrapper. # # Idempotent. Re-runs on script changes or whenever the host-side manifest # content changes. @@ -16,9 +15,7 @@ TB_APP=org.mozilla.thunderbird MANIFEST_NAME=external_editor_revived.json WRAPPER_NAME=external_editor_revived.sh -# Locate the EER binary. nixpkgs is the preferred source (see nix/host.nix) -# because it has no thunderbird dep; the AUR package is the fallback for -# hosts where nix isn't set up yet. +# Locate the EER binary. Prefer the Nix profile, but tolerate system installs. HOST_BINARY= for candidate in \ "$HOME/.nix-profile/bin/external-editor-revived" \ @@ -32,8 +29,8 @@ done flatpak info --user "$TB_APP" >/dev/null 2>&1 || exit 0 -# Locate the host-side manifest. Different packagings (nix, AUR variants) -# use different install dirs; check the common ones. +# Locate the host-side manifest. Different packagings use different install +# dirs; check the common ones. HOST_MANIFEST= for candidate in \ "$HOME/.nix-profile/lib/mozilla/native-messaging-hosts/$MANIFEST_NAME" \ -- cgit v1.3.1