Commit Graph
615 Commits
Author SHA1 Message Date
ryan4yin | 二花 0dcbbb02e9 feat(canokey): enroll new CanoKeys and retire per-host SSH keys (#524)
Hosts now accept only the two CanoKeys' resident SSH keys for ryan, plus the romantic recovery key for root; per-host user keys stop working. Darwin builds work again: the shared base no longer sets nixpkgs.config next to nix-darwin's nixpkgs.pkgs.

Assisted-by: DeepSeek Harness (claude-opus-5-5)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-11 01:38:12 +08:00
Ryan Yin 7c2f52c9d5 fix(mihomo): proxy the Google Play CN API
Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-11-10 08:31:35 +08:00
ryan4yin | 二花 abda12c00a feat(canokey): accept a key touch in polkit prompts (#522)
Assisted-by: DeepSeek Harness (claude-opus-5-5)
2026-11-09 08:13:30 -06:00
Ryan Yin a7787198ce fix(shells): disable the nushell welcome banner without Home Manager
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-07 18:01:01 +08:00
Ryan Yin 35155906c1 feat(nix-cache): proxy ustc and cachix, prefer the LAN cache
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-06 17:27:18 +08:00
ryan4yin | 二花 7cfda39c2c feat: log in and sudo over SSH with a CanoKey touch
The CanoKey resident SSH key (`ryan@canokey-moe`, the backup once a new primary key is enrolled) is now authorized for ryan and root on every host, and sudo on server and agent hosts accepts its touch through the forwarded agent (`pam_rssh`). Without the key or a forwarded agent, sudo asks for the password and login falls back to the file keys. Only `canokeySshKeys` can satisfy sudo.

Risks to weigh:

- Colmena deploys need one touch per host connection, since the agent offers the CanoKey key first.
- Desktops now forward the agent to every `hostsAddr` alias, as they already did for `192.168.*`; while a session is open, root there can request signatures, each needing a touch.

### Verification

- `just test` exits 0; CI passed on the first commit.
- Evaluated: sudo PAM stack `rssh` → `unix` → `deny` on shoryu, kana, akane and k3s-test-1-master-1, ai-niri keeps `pam_u2f`; shoryu root and ryan list `ryan@canokey-moe`.
- Not yet verified on a running host.

### Manual step after merge

Deploy the servers, then `just niri`; close old multiplexed connections (`ssh -O exit <host>`) and try `sudo true` over SSH.

AI assistance: DeepSeek Harness (claude-opus-5-5).

Assisted-by: DeepSeek Harness (claude-opus-5-5)
2026-11-06 03:26:59 -06:00
ryan4yin | 二花 b726c28c14 feat(nixpak): sandbox Steam and Heroic in ~/Gaming (#520)
* 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)
2026-11-06 02:18:33 -06:00
ryan4yin | 二花 08d2ff7578 feat(nixpak): sandbox umu-launcher with ~/Gaming as its home (#519)
* 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)
2026-11-05 22:39:48 -06:00
ryan4yin | 二花 a69ef122dc feat(canokey): announce touch requests with a toast and a sound (#518)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-06 10:22:09 +08:00
Ryan Yin dfa53c71d7 fix(nix): take NUR packages from ryan4yin.cachix.org
58d1af8f dropped the cache while adding the pull-through caches. Without
it a NUR bump rebuilds its npm deps here, and dsh's npmDepsFetcherVersion
2 fixed output includes the packuments the Huawei npm mirror rewrites, so
the build fails NUR's hash check instead of reusing its CI-built output.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-05 11:45:51 +08:00
Ryan Yin c4a00e507c fix(nixpak): pass the session TZ through to sandboxes
ICU takes the zone name from the /etc/localtime symlink target path. A bind
mount turns it into a plain file, which keeps the TZif data but loses the
path, so the only identifier left is the ambiguous "CST" abbreviation that
ICU reads from the file and maps to America/Chicago.

Export TZ from time.timeZone and pass TZ/TZDIR through the nixpak env
allowlist.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-04 21:38:18 +08:00
ryan4yin | 二花 13d95daa36 fix(remote-builders): serve x86_64 only, drop aquamarine binfmt (#517)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-04 17:28:30 +08:00
ryan4yin | 二花 71fa928254 feat(canokey): sudo, SSH, LUKS and OpenPGP setup for daily use (#516)
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)
2026-11-04 01:50:21 -06:00
ryan4yin | 二花 2cf3a58028 feat(nixpak): pass FIDO2 keys to Firefox, Chromium and Chrome (#515)
* feat(nixpak): pass FIDO2 keys to Firefox, Chromium and Chrome

Assisted-by: DeepSeek Harness (deepseek-flash)

* feat(nixpak): support FIDO2 hotplug via udev-maintained node directory

Replace launch-time hidraw discovery with host udev rules that hard-link
FIDO-tagged hidraw nodes into /dev/fido-hidraw and remove them on unplug.
The sandbox dev-binds that directory and gets static /dev/hidrawN symlinks
into it, so keys plugged in after launch work and no stale node survives a
reused hidraw minor.

Narrow the extra mounts from whole /sys and /run/udev to /sys/class/hidraw,
/run/udev/data and /run/udev/control; the policy suite now forbids the
broad mounts and checks the wrapper and bind follow the fido2 option.

Assisted-by: Claude Code (claude-opus-5-5)

* refactor(nixpak): rewrite FIDO2 bwrap wrapper in Python

The bash argument loop was hard to follow. Python inserts the /dev/hidrawN
symlinks before "--" with a single list splice, and the header now explains
the whole host-udev -> bind -> symlink chain step by step.

Assisted-by: Claude Code (claude-opus-5-5)

* docs(canokey): document phone-only management policy

PCs only use the CanoKey; CanoKey Console management stays in the phone
app and the Admin PIN is never typed on a PC. Record what the config
enforces (sandboxed browsers get no raw USB/CCID, no vendor WebUSB udev
rule) and what it does not (uaccess on the raw USB node, PC/SC access to
the Admin applet, CTAP management from browsers).

Assisted-by: Claude Code (claude-opus-5-5)

* docs(canokey): separate management from use, link CanoKey docs

Assisted-by: Claude Code (claude-opus-5-5)

* fix(nixpak): create /dev/fido-hidraw from the udev rule

NixOS applies /dev tmpfiles entries only at boot; switch-to-configuration
runs systemd-tmpfiles-resetup with --exclude-prefix=/dev. After a switch
without reboot the directory was missing and every `ln` failed with exit
code 1, so no browser saw the key. The add rule now runs `mkdir -p` first.

Also fix the documented trigger command: `udevadm trigger` defaults to
`change`, which the add-only rule ignores.

Assisted-by: Claude Code (claude-opus-5-5)

* refactor(nixpak): keep tmpfiles as the only creator of /dev/fido-hidraw

The /dev tmpfiles units run before systemd-udevd on every boot, so the
directory always exists before coldplug. The mkdir in the udev rule only
covered the first switch without reboot and duplicated the tmpfiles rule;
drop it and document the one-time `systemd-tmpfiles --prefix` command.

Assisted-by: Claude Code (claude-opus-5-5)

* docs(nixpak): record FIDO2 hardware validation in Firefox and Chrome

After a reboot on ai with the CanoKey present at boot, udev linked only
the FIDO interface and WebAuthn works in Firefox and Chrome. Chromium and
plugging the key in after launch remain pending.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-04 13:38:32 +08:00
ryan4yin | 二花 d8b298019a refactor(shells): use native Home Manager Nushell and Nushell login on non-desktop hosts (#513)
* refactor(shells): use native Home Manager Nushell environment

Replace the Bash login-shell wrapper and hand-maintained Nushell PATH with programs.nushell.loadSessionVariables and home.sessionPath. Launch Nushell directly from Kitty, Ghostty, and Zed, with the macOS config-home override and Ghostty's vendor autoload directory.

Upstream feature: https://github.com/nix-community/home-manager/pull/9666

Assisted-by: DeepSeek Harness (deepseek-flash)

* feat(hosts): use Nushell as login shell on Ruby and Kana

Set the per-user shell explicitly and add Nushell to the system shell list. The system default shell and root remain unchanged.

Assisted-by: DeepSeek Harness (deepseek-flash)

* fix(ssh): preserve tuios session marker across SSH

Forward TUIOS_SESSION and accept it on NixOS sshd, so an SSH session opened from inside tuios does not auto-attach a nested remote tuios.

Assisted-by: DeepSeek Harness (deepseek-flash)

* feat(nixos): use Nushell login shell on non-desktop hosts

Enable the Nushell login shell through a shared module imported by the server and agent profiles. Desktop profiles continue to use Bash.

Assisted-by: DeepSeek Harness (deepseek-flash)

* fix(tuios): skip auto-attach in SSH sessions

Remote interactive shells now stay plain Nushell instead of starting a nested TUIOS when the SSH client is already inside a local TUIOS session. Local TUIOS auto-start is unchanged.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-03 22:31:24 +08:00
ryan4yin | 二花 9a307b313d refactor: host profiles; give ruby, kana and aquamarine the TUI home (#512)
- 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)
2026-11-03 04:57:06 -06:00
ryan4yin | 二花 eb6f6c34f0 chore(gaming): inline the nix-gaming tunables and drop the input (#511)
Assisted-by: Claude Code (claude-opus-5-5)
2026-11-03 14:49:25 +08:00
Ryan Yin 4470b3d014 docs: centralize documentation under docs/
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)
2026-11-02 17:48:57 +08:00
Ryan Yin 179b20a42c fonts: add Japanese and Korean locale fallbacks
Keep SC as the default and select JP/KR glyphs for lang=ja/ko.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-02 12:06:29 +08:00
Ryan Yin f9ece8167d fonts: prefer Noto CJK family names
Noto CJK and Source Han share the same glyphs; Noto names are more common in Linux.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-02 11:45:12 +08:00
Ryan Yin be592ae75c refactor(mihomo): link geodata from nixpkgs instead of seeding it by hand
`just mihomo-geo` copied geodata into the state dir so a cold start never
fetched it. tmpfiles now links v2ray-rules-dat and the DB-IP lite mmdbs
there, so geo-auto-update moves to the gateway config only.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:55:14 -06:00
Ryan Yin 3789a2a282 chore(nixos): guard the nix and xdg-desktop-portal-wlr pins at eval time
WA-023 warns once nixVersions.stable reaches 2.35; WA-046 fails the build
once nixpkgs' xdg-desktop-portal-wlr is no longer the broken 0.8.4, so both
pins get revisited instead of lingering.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:55:14 -06:00
Ryan Yin fe280d8fa2 refactor(ssh): drop no-op openFirewall
It is already the sshd module default, and the shared firewall forces
allowedTCPPorts to [ ] anyway; toplevel drvPaths are unchanged.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:55:14 -06:00
Ryan Yin 04a8438bd3 refactor(canokey): rely on systemd uaccess rules instead of custom udev
systemd's 60-fido-id.rules marks the FIDO hidraw node and the CCID USB
device as security tokens, and 70-uaccess.rules grants them to the
active seat. Drop the hand-written rules and the plugdev membership.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:55:14 -06:00
Ryan Yin ce49b03014 fix(monitoring): socket-activate LAN exporters with FreeBind
Exporters raced networkd for the LAN address at boot; drop the
network-online ordering and unlimited-restart hack and let a FreeBind
socket unit hold the port, passed in via --web.systemd-socket.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:55:14 -06:00
Ryan Yin f8ca25a03b refactor(power-monitoring): grant RAPL read access from a udev rule
The boot-time oneshot only fixed the zones present when it ran, and
node_exporter had to Require it. A powercap add rule covers every zone
whenever it appears; the collector reads at scrape time, so no ordering
is needed.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 11:42:57 -06:00
Ryan Yin 7c0b5fc0b8 fix(mihomo): keep the proxy up when the resolved hook times out
On shoukei a DNS takeover that timed out failed mihomo.service, and the
nixpkgs unit has no Restart=, so the proxy stayed down. Prefix the hook
with '-' (fail open, like ai's hook). Also switch the dashboard title
patch to --replace-fail.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 10:51:51 -06:00
Ryan Yin 8b22aec1bb fix(restic): drop a stale btrfs snapshot before taking a new one
Cleanup runs as ExecStopPost, which a power loss mid-backup skips; the
leftover @restic-snapshot then failed every later run.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 10:51:51 -06:00
Ryan Yin 905c3c6e1f docs(workarounds): retire WA-017, clarify WA-026, refresh WA-023
- WA-017: keyd(1) documents `control = layer(control)` etc. as the
  default modifier bindings, so a keyd bump will never keep right-hand
  modifiers distinct; the passthrough is intentional config. Say so in
  peripherals.nix and drop the row.
- WA-026: installOnHost + restarting microvm@<guest> is the fallback
  microvm.nix's own deploy.rebuild uses; only the in-place sshSwitch is
  broken, so the removal condition is now about that.
- WA-023: locked versions are 2.35.3 (latest) and 2.34.9 (stable).

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 10:14:27 -06:00
Ryan Yin e4c2548a93 refactor: replace redundant mkForce with plain values and mkDefault
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)
2026-11-01 10:14:27 -06:00
Ryan Yin 4bd428776e fix(darwin): pass the Homebrew mirror env through onActivation.extraEnv
nix-darwin runs `brew bundle` as `sudo --preserve-env=PATH ... env ...`,
so the variables the mkBefore'd activation snippet exported never reached
brew; activation was using the default upstream endpoints. Set them via
homebrew.onActivation.extraEnv, which nix-darwin puts on the `env` command
line (evaluated on fern), and drop the snippet.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 10:14:27 -06:00
Ryan Yin 455c03d1fd chore(security): drop the Comodo AAA root blacklist both platforms now carry
nixpkgs' security/ca.nix and nix-darwin's security/pki module both append
"Comodo AAA Services root" to the cacert blacklist themselves, so the
explicit entry only duplicated it. Removes WA-040.

Assisted-by: Claude Code (claude-opus-5-5)
2026-11-01 10:14:27 -06:00
ryan4yin | 二花 0888f87075 feat(power): monitor homelab power and reduce aquamarine idle draw (#501)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-01 20:53:41 +08:00
ryan4yin | 二花 58d1af8f9d feat(youko): add pull-through cache for two Nix upstreams (#499)
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)
2026-11-01 18:27:43 +08:00
Ryan Yin af084f1eb4 feat(npm): use npmmirror for npm fetches
Set the user-level npm/pnpm registry to npmmirror, and make Nix builds use the same mirror through nixpkgs' npmRegistryOverrides and rewriteURL. The configured Nixpkgs policy is also applied to myNurPkgs and Colmena's nodeNixpkgs so NUR packages such as dsh use the mirror while preserving Colmena parity.
2026-11-01 16:57:57 +08:00
ryan4yin | 二花 1a939e2c9a fix(nixpak): use host fontconfig in sandboxes (#496)
Reuse the host fontconfig for Nixpak GUI apps so host and sandboxed apps resolve fonts consistently.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-11-01 11:26:25 +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
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
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 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 add8ad9796 chore(home): remove VS Code 2026-10-28 13:51:16 +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 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 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 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
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
Ryan Yin 52573278bd feat(base): install python313 on every NixOS host
Hosts without Home Manager (aquamarine, the VM hosts, k3s guests) had no
interpreter. The system profile is separate from the per-user one, so desktops
keep their Home Manager copy in PATH.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-20 00:20:12 +08:00