fix(ai): match the wired NIC by prefix, not by name

Assisted-by: DeepSeek Harness (deepseek-flash)
This commit is contained in:
Ryan Yin authored and ryan4yin | 二花 committed 2026-10-14 20:15:01 +08:00
1 parent 55b7741108
commit 492dcb13fe
6 files changed
+46 -9

No files matched your search

+2 -1
View File
@@ -34,7 +34,8 @@ in
xdg.configFile."niri/niri-hardware.kdl".source =
mkSymlink "${config.home.homeDirectory}/nix-config/hosts/idols-ai/niri-hardware.kdl";
# Keep Noctalia's network widgets on the physical uplink, not the Mihomo TUN.
# Keep Noctalia's network widgets on the physical uplink, not the Mihomo TUN
# (the interface name is in ./idols-ai/noctalia.toml and `hostsAddr.ai.iface`).
xdg.configFile."noctalia/host-ai.toml".source = ./idols-ai/noctalia.toml;
# The desktop speakers are already loud, so use the broadcast-standard -23 dB.
+5 -2
View File
@@ -1,6 +1,9 @@
# The default total counts packets on both Mihomo's TUN and the physical uplink.
# Noctalia matches an exact name and takes no pattern, so the wired NIC is named
# here and in `hostsAddr.ai.iface`; `idols-ai-net` asserts each widget separately.
# networkd itself matches the `en*` prefix.
[widget.net_rx]
interface = "enp130s0"
interface = "enp4s0"
[widget.net_tx]
interface = "enp130s0"
interface = "enp4s0"
+4 -4
View File
@@ -47,10 +47,10 @@ Some tests iterate over every configuration, so a new host is covered automatica
them. Others name specific hosts — or a name prefix, like `k3s-api-endpoint`, which covers every
`k3s-test-1-*` configuration — and only cover a new host if you add it.
| Kind | Tests |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Every configuration | `hostname`, `kernel`, `nix-system-features`, `security-apparmor`, `security-container-groups`, `security-exporters`, `security-firewall`, `security-k3s-kubeconfig`, `security-k3s-pod-firewall`, `security-kernel`, `security-ssh-x11` |
| Named hosts only | `btrbk`, `home-manager`, `home-manager-xdg`, `computer-use-headless`, `k3s-api-endpoint`, `k3s-node-home-manager`, `idols-ai-gpu`, `idols-ai-voice-input`, `idols-aquamarine`, `security-postgres-auth`, `youko-metrics`, `ups-metrics`, `shoukei-logind` |
| Kind | Tests |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Every configuration | `hostname`, `kernel`, `nix-system-features`, `security-apparmor`, `security-container-groups`, `security-exporters`, `security-firewall`, `security-k3s-kubeconfig`, `security-k3s-pod-firewall`, `security-kernel`, `security-ssh-x11` |
| Named hosts only | `btrbk`, `home-manager`, `home-manager-xdg`, `computer-use-headless`, `k3s-api-endpoint`, `k3s-node-home-manager`, `idols-ai-gpu`, `idols-ai-net`, `idols-ai-voice-input`, `idols-aquamarine`, `security-postgres-auth`, `youko-metrics`, `ups-metrics`, `shoukei-logind` |
`hostname` expects each configuration's `networking.hostName` to equal its name. Niri desktop
configurations are the exception (`ai-niri` → `ai`, `shoukei-niri` → `shoukei`) and are listed in
@@ -0,0 +1,4 @@
{
staticAddressMatchesWiredInterface = true;
noctaliaReadsHostIface = true;
}
@@ -0,0 +1,27 @@
{
lib,
myvars,
outputs,
...
}:
let
cfg = outputs.nixosConfigurations.ai-niri.config;
hm = cfg.home-manager.users.${myvars.username};
inherit (myvars.networking.hostsAddr.ai) iface ipv4;
# Read the file that actually gets installed, not the path in the repository.
noctalia = builtins.readFile hm.xdg.configFile."noctalia/host-ai.toml".source;
in
{
# A board or PCIe change renames the wired NIC with the PCIe topology, so networkd
# matches the `en*` prefix; a name-based match left the host off the LAN.
staticAddressMatchesWiredInterface =
builtins.elem "${ipv4}/24" cfg.systemd.network.networks."10-lan".networkConfig.Address
&& cfg.systemd.network.networks."10-lan".matchConfig.Name == [ "en*" ];
# The two consumers that need one exact name — mihomo's DNS hook and Noctalia's
# net-speed widgets — take it from `hostsAddr.ai.iface`; each widget is asserted
# on its own, so a drift in either one fails.
noctaliaReadsHostIface =
lib.hasInfix "[widget.net_rx]\ninterface = \"${iface}\"" noctalia
&& lib.hasInfix "[widget.net_tx]\ninterface = \"${iface}\"" noctalia;
}
+4 -2
View File
@@ -44,8 +44,10 @@ rec {
# monitoring skip those entries.
hostsAddr = {
ai = {
# Desktop PC
iface = "enp130s0";
# Desktop PC. `iface` is only for the two consumers that need one exact name
# — mihomo's DNS takeover hook and the Noctalia net-speed widget; networkd
# matches the wired interface by its `en*` prefix (hosts/idols-ai/default.nix).
iface = "enp4s0";
ipv4 = "192.168.5.100";
ipv6 = "fe80::10"; # Link-local Address
};