idols-ai and aquamarine stop preserving ~/.qwen; its existing data stays under /persistent until deleted by hand.
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* chore(aquamarine): take the NPU stack from nixos-unstable-small
* refactor(aquamarine): load the NPU driver via hardware.cpu.intel.npu
Assisted-by: DeepSeek Harness (claude-opus-5-5)
Home Manager now owns ~/.config/gh/config.yml on agent hosts; activation moves an existing one to
config.yml.home-manager.backup.
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* feat(nixpak): sandbox Steam and Heroic in ~/Gaming
idols-ai stops preserving ~/.local/share/Steam, ~/.steam, ~/.config/heroic
and their game data, which must be moved into ~/Gaming before deploying.
Assisted-by: DeepSeek Harness (deepseek-flash)
* refactor(nixpak): replace steam-fix.nu with sandboxed protontricks
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* fix(nixpak): hide host documents and GTK config from game sandboxes
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* docs(ai): locate the Steam library under ~/Gaming
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* fix(umu-game): confine writes to ~/Gaming and keep foreign entries
Assisted-by: DeepSeek Harness (claude-opus-5-5)
* fix(nixpak): keep Steam and Heroic in the application launcher
The wrappers only carried bin/, so neither launcher had a desktop entry
after replacing programs.steam.
Assisted-by: DeepSeek Harness (deepseek-flash)
* fix(nixpak): give the game sandboxes a fontconfig that sees CJK fonts
Steam rendered Chinese as tofu: the FHS layers build their own /etc/fonts,
whose config lists only DejaVu and the XDG font directory, so neither the
host fonts nor the FHS /usr/share/fonts were ever scanned. Point
FONTCONFIG_FILE at a small config that includes /usr/share/fonts, and ship
WenQuanYi Zen Hei and Noto Sans CJK in all three FHS layers.
Assisted-by: DeepSeek Harness (deepseek-flash)
* fix(nixpak): grant the game launchers a StatusNotifier tray icon
Steam and Heroic register a tray icon over D-Bus, and the game sandboxes
granted no StatusNotifierWatcher access, so the desktop shell had nothing
to show for them. Enable desktopIntegration.tray for all three launchers
and teach the policy suites to expect it.
Assisted-by: DeepSeek Harness (deepseek-flash)
* fix(nixpak): drop the duplicate host CJK font and tidy the font overrides
Steam reads the fonts inside its own FHS layer, so the system-wide wqy_zenhei
added for it no longer serves any sandbox. Give gaming-policy its own comment
for FONTCONFIG_FILE instead of leaving it under the compat-tool one, make the
desktop-base value a default, and note the SNI tray grant in the README table.
Assisted-by: DeepSeek Harness (deepseek-flash)
* feat(nixpak): sandbox umu-launcher with ~/Games as its home
umu-run, winetricks and bbe leave the host PATH, so umu launchers
generated before this stop working until rewritten with
`umu-install.nu <name> - <launcher> <gameid>`.
Assisted-by: Claude Agent SDK (claude-opus-5-5)
* refactor(nixpak): mount ~/Gaming as the game sandbox home
idols-ai now preserves ~/Gaming instead of ~/Games, so existing games
vanish from the host after deploy until the preserved ~/Games is moved
to ~/Gaming/Games.
Assisted-by: Claude Agent SDK (claude-opus-5-5)
* docs(nixpak): record umu runtime validation
Assisted-by: Claude Agent SDK (claude-opus-5-5)
Assisted-by: DeepSeek Harness (deepseek-flash)
Use the CanoKey for daily authentication on idols-ai and shoukei, with
the existing passwords, passphrases and per-host SSH keys as fallback.
- sudo: pam_u2f with a shared origin (pam://ryan4yin) and a Nix-store
authfile built from myvars.canokeyU2fKeys; the primary key is
registered and touch-to-sudo works on idols-ai.
- SSH: one resident ed25519-sk key (application=ssh:ryan4yin) exported
to ~/.ssh/id_ed25519_sk; GitHub tries it before the per-host key.
- shoukei LUKS: fido2-device=auto with token-timeout=10s. Update
nixos-apple-silicon (linux-asahi 7.2.14), whose initrd adds
thunderbolt_apple and reset_apple_cio so USB-C comes up before unlock.
- GPG: scdaemon disable-ccid so it uses pcscd.
- docs/security-keys.md: setup, PINs, enrollment, backup key and
recovery; deduplicate the FIDO notes left by #515.
Assisted-by: Claude Code (claude-opus-5-5)
Preserve ~/.raft across reboots so Raft Computer keeps its enrollment, machine identity, agent state and app data. ~/.local/bin and ~/.config/gh were already persisted.
Assisted-by: DeepSeek Harness (deepseek-flash)
* feat(agents): align ruby and kana computer-use support
Assisted-by: DeepSeek Harness (deepseek-flash)
* test(agents): keep one full-host test for ruby and kana
Both guests run the same agent configuration, so a second full-host test
does not add coverage.
Assisted-by: DeepSeek Harness (deepseek-flash)
* fix(computer-use): disable cua-driver telemetry before start
The i3 init hook did not reliably disable the default-on setting, so both
hosts could start the daemon with telemetry enabled.
Assisted-by: DeepSeek Harness (deepseek-flash)
- Add the agent profile (modules/nixos/agent.nix: rootless Podman, linger,
nix-ld) with home/linux/tui.nix as its home role; ruby, kana and
aquamarine use it, so hosts no longer import from hosts/idols-ruby.
- Gate nushell's ~/.secrets source behind modules.shell.secrets.enable,
off on agent hosts.
- Persist the TUI home state on aquamarine's tmpfs root.
- Document host profiles in hosts/README.md; add tests/agent-profile and
drop the x86_64 colmena-parity test, which needs mysecrets.
Assisted-by: Claude Code (claude-opus-5-5)
Move standalone repository docs from the root into docs/ and add a documentation index that links the moved docs and the code-local runbooks.
Update Markdown links, source comments, and the root entry points to the new locations. Keep README.md and AGENTS.md at the root as required entry points.
Assisted-by: DeepSeek Harness (deepseek-flash)
Add a dedicated IPython module with startup helpers for JSON, YAML, TOML, and CSV plus a small set of common standard-library imports for interactive use.
Disable SQLite history and stop preserving ~/.ipython: interactive sessions can contain credentials and other sensitive data, so that profile state must not survive reboots implicitly.
Assisted-by: DeepSeek Harness 0.2.2-alpha.2 (deepseek-flash)
The Mystic Light controller drops its LED state on S3 resume without
re-enumerating, so no udev event fires and openrgb.service keeps running
without reloading the profile. Reapply it from a unit ordered after
suspend.target, through the running server.
Assisted-by: Claude Code (claude-opus-5-5)
At boot whisper-asr could start before the LAN address was configured and
fail with "could not bind on any address". Let whisper-asr.socket bind it
with FreeBind and have uvicorn take fd 3, like the exporters.
Assisted-by: Claude Code (claude-opus-5-5)
A default-node hook selects wivrn.sink/wivrn.source whenever they exist,
so the polling wivrn-audio.nu unit, its saved state and `just vr-audio`
go away. Streams follow via linking.follow-default-target.
Assisted-by: Claude Code (claude-opus-5-5)
myNurPkgs evaluated a second nixpkgs just for four packages. Apply the
NUR repo's own overlay instead, so they come from the host's pkgs.
Darwin's pkgs now gets nixpkgsConfig too: it set nixpkgs.pkgs, which
ignores nixpkgs.config, so only myNurPkgs carried the npm mirror there.
Assisted-by: Claude Code (claude-opus-5-5)
Both only touch pkgsStatic builds, which nothing on this host pulls in
since qemu-user binfmt was removed; the toplevel drvPath is unchanged.
Assisted-by: Claude Code (claude-opus-5-5)
hardware.amdgpu.opencl.enable also adds clr, whose OpenCL 2.2 libOpenCL.so.1
lands in /run/opengl-driver/lib, first in OpenVINO's RUNPATH, and shadows the
ocl-icd loader the GPU plugin links. With clr.icd alone the plugin finds
ocl-icd, so the wrapper and WA-038 go.
Assisted-by: Claude Code (claude-opus-5-5)
The data dir is the module's own DynamicUser StateDirectory (already
/var/lib/victoriametrics -> private/victoriametrics on youko), so the
victoriametrics-data group, its tmpfiles rule and SupplementaryGroups
did nothing. stateDir was set to its default.
Assisted-by: Claude Code (claude-opus-5-5)
Root is tmpfs, so the backing dirs must exist before the /data bind
mounts. initrd tmpfiles rules on /sysroot do that before switch-root,
replacing the activation script.
Assisted-by: Claude Code (claude-opus-5-5)
services.homepage-dashboard runs the nixpkgs package with DynamicUser,
replacing the :latest container, its system user and the activation
script that rsynced the YAML into place. The YAML stays as is and is
linked into /etc/homepage-dashboard.
Assisted-by: Claude Code (claude-opus-5-5)
A tmpfiles L+ symlink to the store path replaces the activation script
that rsynced it on every switch. Files that were removed upstream no
longer linger.
Assisted-by: Claude Code (claude-opus-5-5)
NixOS's libvirtd-config copies default.xml but never creates its
autostart link, and shoryu has no networks/autostart directory at all,
so virbr0 never starts and the oneshot had nothing to disable.
Assisted-by: Claude Code (claude-opus-5-5)
USB_QUIRK_RESET_RESUME ("b") makes usbcore reset the camera instead of
resuming it, and uvcvideo implements reset_resume, so the resume hook
that ran usbreset after S3 is no longer needed.
Assisted-by: Claude Code (claude-opus-5-5)
Apply hdparm -B 255 -S 0 whenever a disk appears, which also covers the
re-add after a bridge reset, instead of a boot oneshot plus an hourly
timer. Drop -J 0: hdparm has always aborted it without
--please-destroy-my-drive, and wdidle3 already reads disabled on both
disks (it is persistent firmware state).
This was the last user of mylib.systemdHardening.privilegedOneshot, so
remove the preset and its test group.
Assisted-by: Claude Code (claude-opus-5-5)
macsmc-battery's "add" uevent fires before the supply accepts writes
(power_supply_register bumps use_cnt after device_add); its deferred
register work then emits "change". Match both instead of polling for 30 s
from a oneshot.
Assisted-by: Claude Code (claude-opus-5-5)
amdgpu registers power1_cap with its hwmon device, so a rule on each
card's hwmon add event replaces the oneshot that polled /sys/class/hwmon
for 60 s waiting for both cards to probe.
Assisted-by: Claude Code (claude-opus-5-5)
A 2024 formatter pass turned `{{…}}` into a YAML flow map, the variable
was never passed to the container, and no widget uses it.
Assisted-by: Claude Code (claude-opus-5-5)
It was a precaution for the R9700 links, never an observed problem, and
on BIOS 1013 the FADT already disables ASPM ("ACPI FADT declares the
system doesn't support PCIe ASPM"), so the parameter did nothing.
Assisted-by: Claude Code (claude-opus-5-5)
89d7a9bd made systemd-tmpfiles-setup RequiresMountsFor the five nofail
USB-disk mounts. One failed mount then skipped every tmpfiles rule on the
host, and sysinit.target waited for the disks and the LUKS unlock even on
success.
Leave the boot-wide pass as upstream ships it and add data-tmpfiles:
`systemd-tmpfiles --prefix=/data` with WantsMountsFor on the /data mounts,
ordered before the services that use them.
Assisted-by: Claude Code (claude-opus-5-5)
Each of these overrode a value nothing else set at a higher priority:
- qemu-guest: btrbk, hardwareTools and cloud-init have no competing
definition on the guests.
- mdns: nixpkgs' sunshine module sets avahi.publish.* with mkDefault.
- computer-use: i18n now sets the time zone with mkDefault.
- darwin terminal: the shared ghostty/kitty font sizes are now mkDefault.
- shoukei: sunshine is mkDefault false in remote-desktop.nix, zram's
memoryPercent is mkDefault 50; supportedFilesystems now merges instead
of discarding the fsType entries other modules add.
- youko: nothing enables docker.
- nixpak: pasta.enable and sockets.pipewire are mkDefault in the shared
modules, sockets.pulse already was.
Every NixOS host's toplevel drvPath is unchanged; on fern and frieren the
terminal font sizes and time zone evaluate to the same values.
Assisted-by: Claude Code (claude-opus-5-5)
bb899876 moved the proxy gateway to fake-IP for IPv6 and removed
aquamarine's getaddrinfo precedence table, so the row's removal condition
has been met since 2026-10-14; only the row and a comment pointer lingered.
Assisted-by: Claude Code (claude-opus-5-5)
drivers/nvme/host/core.c defaults default_ps_max_latency_us to 100000, so
the "relaxed" APST cap on ai and its copy on aquamarine set the value the
kernel already uses. Keep ai's history and rollback recipe as a comment,
and stop the aquamarine pcie_aspm=off comment from citing WA-008, which
never covered it. Removes WA-008.
Assisted-by: Claude Code (claude-opus-5-5)
hardware.nvidia.modesetting.enable makes nixpkgs' nvidia module add
nvidia-drm.modeset=1 and, for drivers >= 545, nvidia-drm.fbdev=1 to
moduleParams, which reach modprobe via extraModprobeConfig (evaluated:
"options nvidia-drm fbdev=1 modeset=1" on ai with 595.x).
Assisted-by: Claude Code (claude-opus-5-5)
Enable the existing remote-builder module on shoryu, shushou and
youko, and authorize their SSH host keys on aquamarine.
Kana and Ruby are VM guests with no need to build; leave their local
store and build behavior unchanged.
Assisted-by: DeepSeek Harness (deepseek-flash)
Run nginx on youko as a loopback pull-through HTTP cache for
cache.nixos.org and cache.numtide.com, exposed by Caddy at
https://nix-cache.writefor.fun.
Assisted-by: DeepSeek Harness (deepseek-flash)
systemd-tmpfiles-setup only orders itself after local-fs.target, but the nofail /data submounts can complete later. It then sees /data as the read-only fallback tmpfs and fails to create the Transmission, Immich, RustFS and restic directories at boot.
Add RequiresMountsFor for the data mounts and cover the generated unit dependency with an eval test.