Commit Graph
2806 Commits
Author SHA1 Message Date
Ryan Yin 7a00fead7d fix(tuios): force xterm-kitty inside panes 2026-11-01 09:43:04 +08:00
Ryan Yin 9152e82916 chore(niri): remove pyclipsync clipboard bridge
WeChat and QQ now use native Wayland, so the X11/Wayland clipboard bridge
is no longer needed. Remove the flake input, home-manager module wiring,
lock entries, and stale documentation reference.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-01 09:37:15 +08:00
Ryan Yin 87b7a23cf3 docs(nixpak): consolidate runtime validation notes
Merge the three runtime-validation files into one concise record, update the interactive browser and Zoom results, and document the intentional Chromium host-loopback and Brave/Edge no-media exceptions. Tighten the remaining cookie-crypto workaround and the smoke-test prerequisites.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-01 09:24:23 +08:00
ryan4yin | 二花 ccffddc864 feat(wechat): native nixpkgs package with app-scoped data (#492)
Switch to the native deb package from nixpkgs-patched (#560225), remove the AppImage/FHS bwrap layer, and enable native Wayland while keeping the X11 fallback.

Keep only WeChat state under one app-scoped HOME and bind the host Documents and Downloads directories like the other desktop apps. User-selected files also go through the XDG FileChooser portal. Remove the launcher, activation script, and compatibility symlinks.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-01 00:09:27 +08:00
Ryan Yin 30cb22500f fix(niri): route Zoom screen sharing through xdg-desktop-portal-wlr 0.8.2
niri 26.04 exposes DMA-BUF only, which Zoom 7.2.1 rejects. xdg-desktop-portal-wlr 0.8.2 provides the working SHM path; 0.8.4 regresses Zoom SelectSources.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-31 22:44:16 +08:00
ryan4yin | 二花 818965a11f feat(nixpak): unify desktop app sandboxes (#491)
* refactor(nixpak): unify desktop app sandboxes

Move common GUI, portal, and network policy into reusable modules and migrate browsers plus Zoom/WeChat/QQ/Telegram to the same boundary.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-31 22:27:58 +08:00
ryan4yin | 二花 707da35996 feat(nixpak): clear env, drop system bus, isolate network (#490)
* fix(nixpak): stop exposing the system D-Bus to apps
* fix(nixpak): bind only the PulseAudio socket
* feat(nixpak): run apps in a new session tied to the launcher
* feat(nixpak): start apps from an allowlisted environment
* feat(nixpak): isolate app networking with pasta
* fix(nixpak): keep Firefox on the host network

Assisted-by: Claude Code (claude-opus-5-5)
2026-10-31 16:39:25 +08:00
ryan4yin | 二花 3a6f03814e Merge pull request #489 from ryan4yin/harden-incident-110
feat(security): harden homelab SSH, service sandboxing and audit trail
2026-10-31 01:12:55 +08:00
Ryan Yin 56edac8252 fix(transmission): grant the AppArmor lock permission
nixpkgs' transmission 4.1.4 profile grants rw on the daemon's config directory
but not k, while 4.1.4 takes a fcntl lock on
~/.config/transmission-daemon/lock, so the daemon exited at startup with
"Another process is already using". Include rwk for that one file only.

WA-044, drop once the nixpkgs profile carries the permission.

Assisted-by: Claude Code (claude-opus-5-5)
2026-10-31 01:09:16 +08:00
Ryan Yin 560a6cc2d8 fix(preservation): mount /etc/ssh in initrd so key changes apply on boot
NixOS copies mode-carrying /etc entries such as authorized_keys.d during
stage-2 activation, which runs before systemd starts. preservation mounted the
persisted /etc/ssh from preservation.target afterwards and hid that copy, so a
key change only took effect on `switch`: revoking a key and rebooting silently
restored the old one.

Prepare the mount in initrd, before activation runs, and cover it with a VM
test that seeds a stale authorized_keys file, reboots, and asserts the declared
key replaced it. The same test fails on that assertion with inInitrd disabled.

Verified on all four hosts: /persistent/etc/ssh/authorized_keys.d/root is now
rewritten at boot instead of keeping the timestamp of the last switch.

Assisted-by: Claude Code (claude-opus-5-5)
2026-10-31 01:09:16 +08:00
Ryan Yin 7dc4e7a39f feat(security): harden homelab SSH, services and audit trail
The homelab hosts accept root SSH with long-lived file keys, run several
exposed services with almost no systemd sandboxing, and keep no audit trail of
privileged actions. Close those three gaps, weighing each measure against its
cost instead of adopting a policy wholesale.

SSH
- Turn off KbdInteractiveAuthentication: nixpkgs defaults it to true and PAM
  then still accepts the Unix password despite PasswordAuthentication = false.
- authorizedKeysInHomedir = false: only keys declared in Nix take effect;
  youko keeps Gitea's forced-command file through `Match User gitea`.
- Pin aquamarine's passphrase-free remote-builder keys to
  `restrict,command="nix-daemon --stdio --store daemon"`, so builds run in the
  system daemon instead of an audited root login session.

systemd sandboxing
- Add the mylib.systemdHardening preset and apply it to the exposed, weakly
  sandboxed services: caddy 7.8 -> 1.5, vmalert 8.2 -> 1.4, rustfs 6.6 -> 1.4,
  whisper-asr 7.7 -> 1.6. An eval test pins the key restrictions.
- Rejected: a global all-keys policy (<=0.2 score gains on services nixpkgs
  already sandboxes) and per-service confinement (bind paths to maintain).

auditd on all four hosts, reusing nixpkgs' loader and unit
- Audit login sessions only: a first `-a never,task -F auid=unset` rule keeps
  services out of the per-syscall audit path. A compromised service is
  therefore unrecorded until it opens a session.
- Record root commands, credential and host-key access, writes to SSH, account,
  PAM, Nix-trust and audit configuration, module loads and session denials.
- Rejected: global denial logging, service-UID watches and
  --loginuid-immutable (the kernel already records loginuid changes).

Verified on all four hosts after deployment: zero failed units, k3s 6/6 Ready,
and the exposed services healthy.

Assisted-by: Claude Code (claude-opus-5-5)
2026-10-31 01:09:15 +08:00
Ryan Yin 0376697cef docs(agents): record why rules omit principle names 2026-10-30 18:59:09 +08:00
Ryan Yin def7d8f754 feat(niri): enable on-demand VRR for games
Turn on adaptive sync at the output only when a game window opts in, keeping desktop compositing fixed-rate to avoid idle/low-load VRR flicker. The Steam/Proton game rule enables VRR alongside the fullscreen rule.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-30 00:47:51 +08:00
Ryan Yin 005627d883 fix(niri): let untitled Proton windows go fullscreen
XWayland/Proton windows can commit before they set a title. Excluding empty titles made Phantom Blade Zero miss the fullscreen rule and stay composited. Keep excluding the launcher announcement popup by title.

VRR is intentionally not enabled here: on-demand VRR caused display corruption in this game and is tracked separately.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-30 00:46:22 +08:00
ryan4yin | 二花 e8e9691f2d chore(nix): update nixpkgs to e62746b and refresh flake inputs (#488)
* chore(nix): update nixpkgs to e62746b and fix 26.11 breakage

Bump nixpkgs to e62746b and preservation to 00be7f7, then adapt to the removals and renamed options in the new revision: drop the removed boot.initrd.systemd.enable settings, trim the stale emSign CA blacklist on Linux while keeping it for the older Darwin input, and migrate Avahi publishing to settings.publish. Work around sunshine still setting the legacy Avahi options and keep dsh-nu on its tested Nushell 0.115.1. Patch NUR dsh's pnpm call to pass nodejs = null, and update pyclipsync for the stdenv.hostPlatform.system rename.

* chore(nix): refresh flake inputs for 26.11

- update nixpkgs-darwin to the same e62746b revision as nixpkgs
- make dsh-nu follow main nixpkgs and patch its testedWith manifest for the resolved Nushell
- refresh floating inputs; update lanzaboote, tuios, and ponytail
- drop the nixpkgs-2505 and rust-overlay workarounds
- keep pyclipsync on main and simplify the cross-platform CA blacklist
- adopt home-manager's Nushell loadSessionVariables default

* fix(gitea): use ROOT_URL for nixpkgs 26.11

nixpkgs removed the legacy settings.server.DOMAIN option; the existing ROOT_URL already carries the public URL.

* chore(nix): update dsh-nu to 0.7.0

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-30 00:39:01 +08:00
Ryan Yin 4fcdb79719 docs(agents): answer challenges before continuing work
A user question or challenge is the current task; resolve it before doing unrelated work.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-29 21:40:46 +08:00
Ryan Yin ba1515f094 docs(agents): ask for SSH access instead of falling back
A missing GitHub SSH key is a credential boundary, not a reason to switch transports silently.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-29 21:39:16 +08:00
Ryan Yin 13afe01441 docs(agents): prefer upstream fixes over local workarounds
Clarify that minimality means the smallest best-practice change, not a local patch around an upstream defect.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-29 21:37:41 +08:00
Ryan Yin 7e579d6aca fix(monitoring): order nvidia exporter after network-online
The nvidia exporter binds the host's static LAN IPv4, but unlike the node and smartctl exporters it was not ordered after network-online.target. On boot it lost the race with networkd, hit the systemd start limit, and stayed failed until manually restarted.
2026-10-29 21:28:08 +08:00
Ryan Yin 01d2e76410 chore(secrets): refresh mysecrets and follow agenix-rules rename
Update the mysecrets lock to 7f93490, which renames secrets.nix to agenix-rules.nix, drops the deprecated ./ key prefixes for agenix 0.18, and re-encrypts the access-token secret. Update the docs and agenix skill to the new filename and path convention.
2026-10-29 21:28:08 +08:00
Ryan Yin 38d1d85e85 feat(home): re-add gitleaks
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-29 17:04:39 +08:00
Ryan Yin 8a6cc86664 docs(agents): stop on credential failure
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-29 15:55:30 +08:00
Ryan Yin add8ad9796 chore(home): remove VS Code 2026-10-28 13:51:16 +08:00
Ryan Yin bd41cca5c6 fix(grafana): correct alertmanager dashboard description typo 2026-10-28 13:51:16 +08:00
Ryan Yin b334336cd9 feat: idols-ai - persistent ~/models 2026-10-24 17:16:20 +08:00
Ryan Yin c562f47049 docs(workarounds): drop WA-043 now that the bootstrap fix is live
k8s-gitops#54 merged and reconciled, a full cold start of all six guests
brought the VIP back without manual action, and a probe from a pod shows
2379 denied while 2381 stays open. SECURITY.md records the fix and the
probe; the workaround row and its TODO entry are gone.

Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-24 14:26:53 +08:00
Ryan Yin 8affae69d6 docs(security): record the 2026-10-22 audit follow-up and WA-043
Baseline sysctls, exporter binds and the #399/#400/#401 rules verified
live on 13 hosts; kiali self-escalation and the list-vs-get probe blind
spot recorded; WA-043 registers the k3s-test-1 Cilium/kube-vip bootstrap
cycle (WA-040 is the Root CA blacklist row); the TODO table gains the
cluster-recovery line. The same section records the manual recovery and
its fix in k8s-gitops, plus the 2026-10-24 full cold start that brought
the VIP back without manual action; WA-043 drops when #54 merges.

Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-24 14:16:14 +08:00
Ryan Yin 5088535ac3 fix(ai): bind the nvidia GPU exporter to the static LAN IPv4
The 2026-10-22 audit found the live socket on *:9835: #373 bound
node/smartctl in monitoring.nix, but the nvidia exporter enabled in
hardware-nvidia.nix kept the nixpkgs default, so the socket-level
defence-in-depth layer never existed for 9835.

Extend the security-exporters eval check to every enabled exporter's
listenAddress so a future exporter without a bind fails the test.

Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-24 14:16:14 +08:00
Ryan Yin d4aa25d368 fix(k3s): deny pod sources the etcd client port 2379
The etcd client API listens on the masters' static LAN address, and the
pod-source deny lists omitted it. Add 2379 to both nft drop lines and
assert it in the security-k3s-pod-firewall eval test. 2381 (etcd
metrics, scraped by in-cluster monitoring) stays reachable by design.

Pairs with the matching Cilium egressDeny port in k8s-gitops.

Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-24 14:16:14 +08:00
Ryan Yin f564807ac5 fix(preservation): persist OpenRGB settings and profiles
Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-23 11:29:45 +08:00
Ryan Yin cfafc94666 chore(modules): drop the riscv64 module, which belongs to nixos-config-sbc
Nothing imported it and the riscv64 output was already commented out; riscv64 hosts live in ryan4yin/nixos-config-sbc.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin cf34f52af0 flake.lock: Update
Flake lock file updates:

• Updated input 'dsh-nu':
    'github:ryan4yin/dsh-nu/c7c0b2ca8fcd6fd5791823d6ed2a8f37e817b275?narHash=sha256-Ua5VKHzb7iobq%2B6P7Q8t/2U8t%2BheFmdXl5zIQB4hJGI%3D' (2026-10-21)
  → 'github:ryan4yin/dsh-nu/405e24541f8ea1c99bde545689e3d22819efe4ac?narHash=sha256-K95TJliFJrD3ssB9jMEqEQ3R7qJtK5wd6tK9oy5ZZ9E%3D' (2026-10-21)
2026-10-22 00:54:27 +08:00
Ryan Yin 75a98e5f66 docs(agents): say that pushes need authorization
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin b5a6a5e81b chore(home): drop a duplicate fzf and a no-op gpg setting
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin d421a89bd9 fix(tailscale): drop a duplicate CLI install and a stale comment
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin 267ccd9d34 fix(firewall): note the one port that is open to the Internet
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin 6dea887202 fix(home): open tg: links with the Telegram desktop entry
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin 9b68cfdb8a feat(backup): alert when the last successful backup goes stale
The backup unit publishes `restic_backup_last_success_timestamp_seconds` for the node_exporter textfile collector, and a rejected alert now fails the notify unit instead of exiting 0.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-22 00:54:27 +08:00
Ryan Yin d2b11840d0 flake.lock: Update dsh-nu to 0.6.0
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-21 22:56:37 +08:00
ryan4yin | 二花 4e78fd964a fix(outputs): keep microvm-guest-parity from forcing guest config (#484)
Reading the host's install script evaluated each guest, which pulls the private secrets input, so
CI could not evaluate the suite at all.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-21 21:49:07 +08:00
ryan4yin | 二花 de6a66ccd4 fix(microvm): run k3s guests from their nixosConfigurations entry (#483)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 21:32:56 +08:00
ryan4yin | 二花 41f6db32ed docs(workarounds): record the Colmena version override (#482)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 21:13:52 +08:00
Ryan Yin 1324131c6d docs: correct statements that no longer match the configuration
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 20:59:07 +08:00
Ryan Yin a3c75250c4 fix(restic): catch up backups missed while a host was off
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 20:59:07 +08:00
Ryan Yin 92f59df25a fix(youko): date restic store snapshots by name, not mtime
On its next run the unit deletes every snapshot whose name stamp is older than 14 days, whatever
its mtime.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 20:59:07 +08:00
Ryan Yin 3b3992468b fix(colmena): deploy the systems nixosConfigurations evaluates
Colmena deployments now ship the same toplevel as nixosConfigurations: nodes gain the nixpkgs
registry, nixPath and dated version, and akane no longer gets the x86_64 dsh.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 20:59:07 +08:00
ryan4yin | 二花 9a3cf189cd fix(hypridle): keep displays awake during gamepad use (#480)
Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-21 16:17:59 +08:00
Ryan Yin a8d47e30cf fix(ai): pin the 4K monitor at 144 Hz and record the OSD wake workaround
The DPMS wake failure is the monitor no-signal auto power-off (HPD cycling during idle), not the refresh rate: the 120 Hz pin did not fix it. Disabled in the OSD and recorded as WA-041; pin 144.000 explicitly so niri stops silently falling back.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-21 13:56:01 +08:00
Ryan Yin 169a87f3b9 fix(ai): pin the 4K monitor to its real 120 Hz mode
The 4090 reports the panel 120 Hz mode as 119.880, not 120, so niri fell back to 144 Hz; that DSC link stays dark after a DPMS wake.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-21 12:03:40 +08:00
ryan4yin | 二花 0dcf547d1f fix(pki): distrust roots with compromised eMudhra intermediates (#479)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (gpt-6.1-sol)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-20 23:49:52 +08:00