| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
| |
AddressRandomization=network: iwd generates a deterministic per-SSID
random MAC. Hardware MAC is never exposed on Wi-Fi; reconnects to the
same network reuse the same MAC, so DHCP leases, WPA-EAP creds and
captive portals stay stable.
EnableNetworkConfiguration=false keeps systemd-networkd authoritative
for IP — the existing 30-wifi-bond0.network setup is unaffected and
the wlan interface still gets enslaved into bond0.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two narrow defence-in-depth rules:
- 52-systemd-local-only: org.freedesktop.systemd1.* requires both
subject.local and subject.active. Wheel-via-sudo-rs is on a different
path (sudoers) and is not affected. Stops a non-active or remote
polkit caller from start/stop/restart of system units.
- 53-udisks-system-mount: filesystem-mount-system and modify-system
require subject.active. The everyday USB auto-mount path uses
filesystem-mount (no -system suffix) and is unaffected.
Audited against current workflow (virt-manager, networkctl, USB mount,
bluetoothctl, fwupdmgr) — none of these break.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds standard KSPP-style sysctl hardening that does not interfere with
the existing dev workflow:
- kptr_restrict=2, unprivileged_bpf_disabled=1, bpf_jit_harden=2
- kexec_load_disabled=1 (no kexec in use)
- fs.suid_dumpable=0
- ICMP broadcast/bogus-error ignores
- tcp_timestamps=0 (BBR+cake do not need RFC1323 timestamps)
- IPv6 RA disabled at kernel layer (systemd-networkd is authoritative)
- explicit tcp_syncookies=1
Drops 'kernel.yama.ptrace_scope = 0' so the kernel default 1 (parent
only) applies. Debugging own builds via 'gdb ./a.out', 'lldb -- ./bin',
'rust-gdb' still works; only attach-by-PID now needs sudo, accepted
trade-off.
Intentionally kept dev-permissive:
kernel.sysrq=1, kernel.dmesg_restrict=0, kernel.perf_event_paranoid=-1
|
| | |
|
| |
|
|
|
|
|
|
| |
Upstream tuicr commit 5b19712 migrated from the legacy
`defaultPackage.<system>` flake output to the standard
`packages.<system>.default`, which broke `nix-update` with:
error: attribute 'defaultPackage' missing
|
| |
|
|
|
|
|
|
|
|
| |
Mirror the libvirt pattern by accepting DHCP+DNS on waydroid0 so the
Android container's DhcpClient can lease an IP from dnsmasq.
Remove the manual ip nat MASQUERADE table: waydroid-container installs
its own MASQUERADE rule via iptables-nft compat, so the explicit table
is redundant (and was clobbering anything else in ip nat via the
destroy table).
|
| | |
|
| |
|
|
|
|
|
| |
waydroid-container ships only the iptables-legacy code path for adding
its POSTROUTING MASQUERADE; on a host with pure nftables the rule
never lands and the Android container has no outbound NAT. Declare it
explicitly in our nftables.conf for determinism.
|
| |
|
|
| |
This reverts commit eca1a71fc486690489f7aef671d7beccc2ec3f25.
|
| |
|
|
|
|
|
| |
waydroid (and libvirt with finicky guests) need the host to route
between their NAT bridge and the upstream NIC. libvirtd usually
enables this on demand but it doesn't persist, so the container has
no internet on a fresh boot until something else flips the bit.
|
| |
|
|
|
|
|
|
|
|
| |
Name= negation list was failing in practice — veth/waydroid interfaces
were still being enslaved into bond0, taking down host networking.
Switch to positive matching: Path=pci-*|platform-* AND Name=en* AND
Type=ether. Virtual interfaces (veth, virbr, waydroid0, docker0, ...)
have no udev ID_PATH and never start with 'en', so they're cleanly
excluded by the AND of all three keys.
|
| |
|
|
|
|
|
|
|
| |
systemd-networkd's Type=ether matcher was enslaving waydroid0 into
bond0 the moment 'waydroid session start' ran, taking down the host's
default route. Mirror the libvirt/docker negation pattern.
Also mirror the existing virbr0 forward accepts for waydroid0 so the
Android container can actually reach the internet through MASQUERADE.
|
| | |
|
| |
|
|
|
|
| |
Add dot_config/tuicr/config.toml with theme = "gruvbox-dark".
Symlinked from nix/vm.nix per the symlink invariant so the same
config applies on both host (via chezmoi) and VM (via home-manager).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously every new login retargeted ~/.ssh/agent.sock to its own
per-connection forwarded socket. That broke a multi-connection setup
when the most-recent connection (which 'won' the symlink) dropped:
all surviving connections' panes would point at a dead socket until a
fresh login from a surviving connection re-ran zprofile.
zprofile: only retarget when the existing symlink target is dead
(sshd unlinks the per-connection socket on disconnect, so [[ -S ]] on
the resolved path is a reliable liveness probe). First connection
seeds the symlink, subsequent logins keep using it.
ssh-agent-refresh: scan /tmp/ssh-*/agent.* for any live forwarded
socket and retarget to the first that responds to ssh-add. Lets the
surviving connection recover without waiting for a new login shell.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Switching to nix's zsh on the Arch host left two functional gaps the
Arch zsh package used to fill:
1. /usr/share/zsh/site-functions in fpath: pacman, paru, systemctl,
journalctl, flatpak, docker, kubectl, makepkg etc. drop their
completions there. nix zsh's compiled-in fpath doesn't include
/usr/share so we lose all of them silently. Added that path (and
vendor-completions for the VM's apt-installed completions) to the
existing fpath loop, guarded by [[ -d ]].
2. HELPDIR for the run-help / help-alias machinery: needed so 'help cd'
etc. find the per-builtin help docs. Pick the first existing version
dir, preferring nix-profile so it matches the running zsh version.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
tuicr's upstream flake uses the legacy 'defaultPackage.<system>' output
schema, not 'packages.<system>.default' — fixes the home-manager switch
error 'attribute packages missing' at nix/flake.nix:28.
zsh: removing the system zsh package took /etc/zsh/zprofile with it,
which used to 'source /etc/profile' and pull in /etc/profile.d/*.sh
(flatpak.sh, nix.sh, etc.). Reconstruct XDG_DATA_DIRS in dot_zprofile
defensively, including per-user + system flatpak exports + nix-profile
share, so 'flatpak update' stops warning and desktop entries from
flatpak/nix-installed apps work in launchers (fuzzel).
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Waybar (and other user services) was inheriting the bare pre-login
PATH from systemd --user, missing ~/.nix-profile/bin and ~/.local/bin.
Modules that call nix-provisioned binaries (pass, python3, ncat from
common.nix) silently picked up system copies instead — symptom was
waybar showing different output from the same script when invoked
manually (thunderbird tb-unread.sh, wifi-status.sh).
Also propagate GNUPGHOME and GPG_TTY so pinentry / pass-otp inside
user services behave the same as in the interactive shell.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Forwarded SSH_AUTH_SOCK lives at /tmp/ssh-XXX/agent.NNN — a
per-connection path that disappears on disconnect, leaving every
long-running zellij pane (and its children: claude-code, nvim, …)
pointing at a dead socket. Reattaching after reconnect doesn't help:
the env was captured when zellij first started.
Fix: maintain ~/.ssh/agent.sock as a symlink, re-aimed at the live
forwarded socket on every login (zprofile). Export the stable path so
processes inherit a value that survives reconnects — git fetch /
commit signing keep working in re-attached zellij panes with zero
per-pane re-export.
Adds 'ssh-agent-refresh' helper for transitional panes still holding
the dead per-connection path: re-exports SSH_AUTH_SOCK to the stable
symlink and validates with ssh-add -l. Already-running children
(claude-code) must still be restarted since env is inherited, not
observed.
|
| |
|
|
|
|
|
|
| |
Make it explicit that adding, removing, or renaming any chezmoi-deployed
config requires a matching update to nix/vm.nix's xdg.configFile /
home.file blocks when the corresponding binary is in common.nix.
Drives the audit performed in the previous commit.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The VM doesn't run chezmoi, so every config the host gets via chezmoi
must reach the VM via a nix symlink. Audit found gaps for tools whose
binary IS in common.nix but whose dot_config tree was unlinked:
bat, lsd, yazi, ripgrep, fd, wget, npm, ipython,
gdb, clangd, ccache
Plus the new tuicr claude-code skill (under ~/.claude/skills/tuicr/,
NOT ~/.config — uses home.file instead of xdg.configFile).
Reorganises the block by category and adds an INVARIANT comment
pointing at the rule in .github/copilot-instructions.md.
GUI/wayland-only tools (sway/mako/waybar/fuzzel/mpv/zathura/etc) stay
unlinked: the VM is headless.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Adapts upstream agavra/tuicr's tmux-based wrapper to zellij:
- Detects $ZELLIJ instead of $TMUX
- Spawns child via 'zellij action new-pane --floating' (or --direction
with TUICR_PANE_MODE=split / TUICR_SPLIT_DIR=down)
- Replaces tmux 'wait-for' with a mkfifo / printf done sentinel
- Uses 'pgrep -x tuicr' for the cross-pane already-running probe
(zellij has no list-panes equivalent)
SKILL.md updated for zellij keybinds and a nix install path note.
|
| |
|
|
|
|
| |
tuicr (TUI git-change reviewer) isn't packaged in nixpkgs, so pull it
as a flake input with an overlay exposing pkgs.tuicr. The companion
claude-code skill lives in dot_claude/skills/tuicr/ (separate commit).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
zsh now lives in nix/common.nix instead of meta/base.txt. Removing the
pacman zsh package leaves /etc/passwd dangling at /usr/bin/zsh, so new
login terminals die with 'shell not found'.
Mirror the chsh logic from nix/bootstrap.sh (which only runs on the VM
during first-time provisioning) into the nix-switch recipe so every
`just sync` / `just init` re-asserts the login shell — and the
host gets the same treatment as the VM.
Idempotent: skips when the shell already matches, skips when
~/.nix-profile/bin/zsh is missing (pre-bootstrap state).
|
| |
|
|
|
|
|
|
|
| |
Now that meta/*.txt is conventionally required to list installed
package names (not virtual providers — see preceding commit dropping
ttf-font-awesome in favour of the already-declared otf-font-awesome),
the intersection with pacman -Qq is unnecessary. Failing loudly on a
virtual-provider entry is actually useful: it surfaces a data-entry
mistake instead of silently masking it.
|
| |
|
|
|
|
|
| |
ttf-font-awesome is a virtual provided by otf-font-awesome (already
declared on the line above) — paru resolves the former to the latter,
so listing both adds nothing and confuses the mark-explicit step in
pkg-apply.
|
| |
|
|
|
|
|
|
|
|
| |
paru may resolve a declared name to a provider with a different package
name (e.g. ttf-font-awesome -> otf-font-awesome). Calling
`pacman -D --asexplicit` on the declared name then fails with
'could not find or read package' and aborts the recipe.
Intersect the declared list with `pacman -Qq` before bumping reasons;
names not present in the local DB are silently skipped.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`paru -S --needed` skips packages already on disk, so anything pulled
in transitively first and *later* added to meta/*.txt stays marked as
'installed as a dependency' in the local pacman DB — and keeps showing
up under `pacopt`.
After each install pass, force the declared set to 'explicitly
installed' via `pacman -D --asexplicit`. This treats meta/*.txt as
the source of truth for install reason: anything listed there is
explicit, anything else is a transitive dep.
Idempotent on already-explicit packages (pacman just prints 'install
reason is already explicit', which we discard).
|
| |
|
|
|
|
|
|
| |
Root filesystem is btrfs; the userspace tools are needed for routine
maintenance (scrub, balance, subvolume management) and inspection
(`btrfs filesystem usage` — the only honest reporter on btrfs since
plain `df` doesn't account for metadata/profiles/unallocated). Also
used by the mkinitcpio btrfs hook at boot.
|
| |
|
|
|
|
| |
Interactive python REPL. Uses python3Packages.ipython so only the
`ipython` binary lands on PATH — no stray system `python`/`python3`,
preserving the 'tools managed by uv per-project' policy in common.nix.
|
| |
|
|
|
|
|
|
|
| |
linux: previously installed only as an Optional Dep of base. Promote to
an explicit declaration so it stops showing up under pacopt.
dosfstools: required by udisks2 (and libblockdev-fs) for mounting FAT
volumes — USB sticks, the EFI system partition, etc. Universally useful
on any desktop install.
|
| |
|
|
|
|
|
|
|
|
|
| |
Promote pacopt from a plain alias to a function. In addition to listing
packages that remain installed solely as someone's optional dependency,
each package is now annotated with its parent(s) and the upstream
reason text from the parent's Optional Deps field.
Implementation is pacman-only (no expac): one awk pass over 'pacman -Qi'
builds a reverse index of every (parent, optdep, reason) edge in the
local DB, then per leaf package the index is filtered for matching deps.
|
| |
|
|
| |
Stops the 'X news items unread' banner on every home-manager switch.
|
| |
|
|
|
|
|
|
| |
Delta's hyperlink resolution shells out to git rev-parse for every
blob to build clickable file links, which is fine on bare metal but
death-by-fork on a slow VM — 'git diff' could take many seconds
while 'git diff | cat' returns instantly. Turn hyperlinks off; we
get clickable nothing but visible-everything-fast diffs.
|
| |
|
|
|
|
|
|
|
|
|
| |
Mirror the drop-in already in place for protonmail-bridge. The
default ~/.password-store doesn't exist on this system (store lives
under $XDG_DATA_HOME); without this, pass-secret-service throws
PassNotInitialized when the service is started outside a context
that already exported PASSWORD_STORE_DIR (e.g. D-Bus activation
before sway has imported env). That cascades into protonmail-bridge
failing to persist its IMAP creds and Thunderbird seeing ephemeral
passwords with 'no such user' errors.
|
| |
|
|
|
|
| |
Unused; the pass entry doesn't exist on most machines, so login emitted
'Error: copilot/firecrawl-api-key is not in the password store' on every
shell start. Easier to drop than to gate.
|
| |
|
|
|
|
| |
Just's formatter inserts a blank line so only the immediately-adjacent
comment serves as the recipe's doc string. Pre-existing drift, surfaced
when CI added 'just check-fmt' to the pipeline.
|
| |
|
|
|
|
|
|
| |
Older shellcheck (Ubuntu's in CI) flags '[ test ] && cmd || true'
as SC2015 because, despite the intent, A && B || C is not
equivalent to if-then-else (C runs when A is true but B fails).
Replace with explicit 'if … fi' or split into two 'A || continue'
guards. Functionally identical, lint-clean across versions.
|
| |
|
|
|
|
|
| |
The doctor recipe checks for basedpyright (used by 'just lint' for
Python type-checking), but the CI workflow wasn't installing it,
causing every run since the recipe was added to fail at the doctor
step. Install it via pipx like ruff.
|
| |
|
|
|
|
| |
host.nix reads HOME/USER via builtins.getEnv, which returns "" under
pure-eval (nix run's default). just-nix-switch already passes --impure;
match it here.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The standalone 'home-manager' command defaults to the legacy
~/.config/home-manager/home.nix and errors out for flake users. The
wrapper auto-selects the host/vm profile by /etc/os-release ID and
points at whichever dotfiles checkout exists on the machine.
Usage:
hm news
hm switch
hm generations
|
| | |
|
| |
|
|
|
|
| |
Refreshes flake.lock (nixpkgs + home-manager) and re-activates the
profile. Plugged into the existing 'just update' aggregate so a weekly
'just update' bumps pacman/AUR + flatpak + nix in one go.
|
| |
|
|
|
|
|
| |
Upstream rewrote the derivation in 1.0.43+ to fetch a prebuilt binary
from the copilot-cli releases (autoPatchelf + makeBinaryWrapper) instead
of buildNpmPackage, sidestepping the /var/empty/.cache EACCES that
blocked 1.0.40.
|
| |
|
|
|
| |
- zsh: remove ~/.local/share/nvim/mason/bin from PATH
- justfile: update comments to reflect Mason removal
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Per user decision: on the Arch host, chezmoi remains the single deployer
of $HOME dotfiles. nix/common.nix's xdg.configFile + sshConfig
activation + .zshenv home.file block was causing home-manager to fight
chezmoi on every nix-switch, materializing .backup files for nvim,
zellij, zsh, git, ghostty, direnv.
Resolution:
- nix/common.nix: drop the entire deployment block, drop the
my.dotfilesPath option, drop the let..in dotfiles/link helpers.
Module is now deployment-agnostic: only installs packages.
- nix/host.nix: drop my.dotfilesPath; explicit comment that chezmoi
owns dotfile deployment on the host.
- nix/vm.nix: gains everything previously in common.nix's deployment
block — xdg.configFile (nvim/zellij/zsh/git/ghostty/direnv),
home.activation.sshConfig, home.file.".zshenv". The 'dotfiles'
let-binding (= $HOME/.local/share/dotfiles) and 'link' helper move
here too, since they're vm-only now.
Host runbook unchanged (`just sync`); first run after pulling will
just be a no-op nix-switch instead of a backup-file storm.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- common.nix hardcoded the runtime dotfiles checkout to
~/.local/share/dotfiles, which is correct for the remote-dev VM but
not the Arch host (where the canonical clone lives at ~/dotfiles).
ssh activation was failing with 'cannot stat
/home/sommerfeld/.local/share/dotfiles/private_dot_ssh/config' on
every host nix-switch.
Promote the path to a typed option (config.my.dotfilesPath) and set
it from each profile:
nix/host.nix -> $HOME/dotfiles
nix/vm.nix -> $HOME/.local/share/dotfiles
common.nix now wraps its config in 'config = { ... }' so the
options can sit alongside.
- dockerfile-language-server-nodejs was renamed in nixpkgs to
dockerfile-language-server; pick up the new name to silence the
evaluation warning (the rename will eventually become a hard error).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
github-copilot-cli (broken)
nodePackages was removed wholesale from nixpkgs; everything that lived
under it must be referenced via its top-level name or dropped.
- prettier: moved nodePackages.prettier -> prettier (top-level alias).
- jsonlint: not available at top level. Dropped from nix/common.nix
AND from the nvim-lint and conform-nvim configs in
dot_config/nvim/lua/plugins/lsp.lua. jsonls already provides
schema-aware diagnostics; jq still handles formatting. The
jsonlint redundancy is acceptable to lose.
- github-copilot-cli (1.0.40 in nixpkgs): buildNpmPackage derivation
doesn't redirect HOME during npm postinstall, so it fails with
EACCES on /var/empty/.cache on Determinate nix. Removed; install
manually from https://github.com/github/copilot-cli into
/usr/local/bin/ as before (current host already has it there).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
in nix-switch
- gh-actions-language-server is an npm package (lttb/gh-actions-language-server)
not packaged in nixpkgs. Removed from nix/common.nix and from the
vim.lsp.enable list in dot_config/nvim/lua/plugins/lsp.lua. Restore
later via a per-project flake.nix if working on a workflows-heavy repo.
- just runs recipes with a sanitized env where $USER may be unset;
home-manager's activation script dereferences it unconditionally
and fails with 'USER: unbound variable'. Export USER (and HOME for
symmetry) at the top of the nix-switch recipe.
|