aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-07-02 11:35:35 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-07-02 11:35:35 +0100
commitf0c626059451e1f8621600e610240739d5633560 (patch)
tree4dc71f10a68b2c273ed2107f8af4a20c08894a2d
parent694cd2fc4680ccea939c9569f0a76cf1deaa5d2d (diff)
downloaddotfiles-f0c626059451e1f8621600e610240739d5633560.tar.gz
dotfiles-f0c626059451e1f8621600e610240739d5633560.tar.bz2
dotfiles-f0c626059451e1f8621600e610240739d5633560.zip
Prune stale dotfiles commentary
-rw-r--r--AGENTS.md13
-rw-r--r--dot_config/containers/storage.conf.tmpl23
-rw-r--r--dot_config/nvim/lua/plugins/lsp.lua4
-rw-r--r--dot_config/nvim/lua/plugins/session.lua4
-rw-r--r--dot_config/zsh/dot_zprofile9
-rw-r--r--dot_config/zsh/dot_zshrc21
-rw-r--r--etc/nftables.conf15
-rw-r--r--etc/pacman.conf2
-rw-r--r--etc/systemd/logind.conf.d/10-ignore-power-key.conf12
-rw-r--r--etc/systemd/logind.conf.d/20-lid-ac.conf14
-rw-r--r--etc/systemd/network/30-ethernet-bond0.network4
-rw-r--r--meta/base.txt94
-rw-r--r--nix/common.nix104
-rw-r--r--nix/host.nix128
-rw-r--r--nix/vm.nix10
-rwxr-xr-xrun_onchange_after_deploy-etc.sh.tmpl26
-rw-r--r--run_onchange_after_deploy-tb-eer.sh.tmpl15
17 files changed, 110 insertions, 388 deletions
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 <target-cmd> <alias>=<target> [<alias>=<target>...]
_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, ... }:
+{
+ 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.
+# 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/<name> 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.
+ playerctl # MPRIS over session bus
+ pulsemixer # TUI for PipeWire/PulseAudio
- # ── General CLIs migrated off pacman ──────────────────────────────────────
+ # ── 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" \