diff --git a/docs/superpowers/specs/2026-05-13-networkmanager-activation-design.md b/docs/superpowers/specs/2026-05-13-networkmanager-activation-design.md new file mode 100644 index 0000000..02d45d8 --- /dev/null +++ b/docs/superpowers/specs/2026-05-13-networkmanager-activation-design.md @@ -0,0 +1,133 @@ +# NetworkManager Activation Design + +**Date:** 2026-05-13 +**Status:** Approved + +## Summary + +Activate NetworkManager (already installed but disabled) and configure it to use `iwd` as its wifi backend. Disables `systemd-networkd` (the current connection manager) to avoid conflicts. Re-enables `nm-applet` and `networkmanager_dmenu` paths that were dead because NM wasn't running. + +## Current Behaviour + +- `iwd` is running — manages wifi at the protocol level +- `systemd-networkd` is running — handles DHCP and link config +- `NetworkManager.service` is installed but **disabled** (inactive/dead) +- `nm-applet` runs at no-op (no dbus peer to connect to) +- `networkmanager_dmenu` (waybar `network` module's on-click) errors with "NetworkManager is not running" + +End result: connectivity works, but the entire NM-based UI ecosystem (applet, dmenu picker, nmcli) is non-functional. + +## Target Behaviour + +- `iwd` continues running, now as NM's wifi backend +- `NetworkManager` runs as the connection manager +- `systemd-networkd` stopped and disabled +- `nm-applet` shows connection state in the waybar tray (works because the SNI watcher chain works) +- `networkmanager_dmenu` opens a wofi-style picker that lists/connects to known networks +- Existing wifi profiles preserved (NM reads iwd's known-networks via the backend interface) + +## Implementation + +### Tracked dotfile + +**`NetworkManager/conf.d/wifi-backend.conf`** (new file in repo, deployed to `/etc/NetworkManager/conf.d/`): + +```ini +[device] +wifi.backend=iwd +``` + +This is the only file NM needs. It tells NM to delegate wifi to iwd (which is already running) instead of spawning its own `wpa_supplicant`. Modern, well-supported configuration on Arch. + +### `install.sh` + +Append one block in the existing system-deploy section (after the hibernate `sleep.conf.d` line): + +```bash +sudo install -Dm644 "$(pwd)/NetworkManager/conf.d/wifi-backend.conf" \ + /etc/NetworkManager/conf.d/wifi-backend.conf +``` + +`install -Dm644` creates `/etc/NetworkManager/conf.d/` if it doesn't exist (it usually does, since the NM package ships an empty stub) and sets mode 644. + +### `packages.txt` + +Re-add `network-manager-applet` (removed in commit `4303562` when nm-applet was non-functional). Insertion can go anywhere — alphabetical-ish near the existing `networkmanager`-related lines. + +### `niri/config.kdl` + +Re-add the spawn-at-startup line (removed in same earlier commit): + +```kdl +spawn-at-startup "nm-applet" "--indicator" +``` + +Position: with the other applet/daemon spawns, alphabetical order doesn't matter. + +### One-time service swap (manual, with sudo) + +Documented in README, not scripted. Two commands run once: + +```bash +sudo systemctl disable --now systemd-networkd +sudo systemctl enable --now NetworkManager +``` + +Why not script it: systemd unit state is persistent. Once flipped, it stays. Doesn't need to be in `install.sh` (which runs frequently). A one-time README instruction matches the existing pattern for `enable-hibernation.sh`. + +### `README.md` + +Append a subsection under `## Setup`, alongside the existing "One-time hibernation enablement": + +```markdown +### One-time NetworkManager activation + +After `install.sh` deploys the NM config, swap from systemd-networkd to NetworkManager (one-time, persistent across reboots): + +\`\`\`bash +sudo systemctl disable --now systemd-networkd +sudo systemctl enable --now NetworkManager +\`\`\` + +Wifi will drop for a few seconds and reconnect via iwd's stored profiles. If reconnection fails, re-enter the wifi password via `nm-applet` or `networkmanager_dmenu`. +``` + +## Files Touched + +| File | Action | +|---|---| +| `NetworkManager/conf.d/wifi-backend.conf` | created | +| `install.sh` | append one `sudo install -Dm644` line | +| `packages.txt` | re-add `network-manager-applet` | +| `niri/config.kdl` | re-add `spawn-at-startup "nm-applet" "--indicator"` | +| `README.md` | append "One-time NetworkManager activation" subsection | + +## Verification + +After `install.sh` + the two systemctl commands: + +```bash +systemctl is-active NetworkManager # active +systemctl is-active systemd-networkd # inactive +nmcli general status # prints connectivity status +nmcli -f WIFI-PROPERTIES.WPA general status # confirms iwd backend is alive +nmcli connection show --active # shows the wifi connection +busctl --user get-property org.kde.StatusNotifierWatcher \ + /StatusNotifierWatcher org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems + # should include nm-applet's tray entry +``` + +Behavioural checks: +1. Wifi stays connected (after a brief drop during the swap). +2. Click waybar's network widget — `networkmanager_dmenu` opens with available networks. +3. The nm-applet tray icon shows current connection state. + +## Out of Scope + +- **Migrating iwd profiles to NM-format files** — not needed; NM reads iwd's known-networks via the backend interface. +- **Removing `iwd`** — kept as the wifi backend. +- **Removing the `networkmanager` package** — already installed; we just enable the service. +- **DNS / dispatcher / split-tunnel / VPN config** — beyond scope; default NM behaviour is fine. +- **Wired-only fallback** — out of scope; NM handles ethernet automatically when present. +- **Deleting the obsolete `nm-applet` removal commit from history** — keep history honest. +- **Auto-running the systemctl commands from `install.sh`** — out of scope; service-state changes are one-time and persistent.