Files
dotfiles/docs/superpowers/plans/2026-05-13-networkmanager-activation.md
T
funman300 b57d134c2b docs: implementation plan for NetworkManager activation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:44:57 -07:00

294 lines
9.5 KiB
Markdown

# NetworkManager Activation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Activate NetworkManager (with iwd as wifi backend) so the existing nm-applet, networkmanager_dmenu, and waybar `network` widget actually work.
**Architecture:** One tracked drop-in (`NetworkManager/conf.d/wifi-backend.conf`) deployed by `install.sh`. Re-add the package and the niri spawn-at-startup line that were removed when nm-applet was useless. Document the one-time `systemctl` swap in README. iwd keeps running as wifi backend; systemd-networkd is disabled by the user via the documented commands.
**Tech Stack:** NetworkManager 1.56, iwd, niri, systemd, install(1).
**Spec:** `docs/superpowers/specs/2026-05-13-networkmanager-activation-design.md`
**Verification model:** Bash syntax checks + `niri validate` for static correctness. Functional checks (NetworkManager active, wifi connected, tray icon present) require the live session — controller verifies after the README's manual systemctl commands run.
---
## File Structure
| File | Role |
|---|---|
| `NetworkManager/conf.d/wifi-backend.conf` | New tracked dotfile. One-line `[device]` block telling NetworkManager to use iwd as wifi backend. |
| `install.sh` | Modified: append one `sudo install -Dm644` line to deploy the drop-in. |
| `packages.txt` | Modified: re-add `network-manager-applet`. |
| `niri/config.kdl` | Modified: re-add `spawn-at-startup "nm-applet" "--indicator"`. |
| `README.md` | Modified: append `### One-time NetworkManager activation` subsection under `## Setup`. |
---
## Task 1: Tracked drop-in + install.sh deploy
After this task, the repo carries the wifi-backend drop-in and `install.sh` deploys it. The system file `/etc/NetworkManager/conf.d/wifi-backend.conf` lands when install.sh runs. NetworkManager isn't enabled yet — Task 4 (manual user step) does that.
**Files:**
- Create: `NetworkManager/conf.d/wifi-backend.conf`
- Modify: `install.sh` (append after the existing `sleep/hibernate-delay.conf` line at line 73)
- [ ] **Step 1: Create the directory and drop-in file**
```bash
mkdir -p NetworkManager/conf.d
```
Write `NetworkManager/conf.d/wifi-backend.conf` with this exact content:
```ini
[device]
wifi.backend=iwd
```
- [ ] **Step 2: Verify file contents**
```bash
cat NetworkManager/conf.d/wifi-backend.conf
```
Expected: exactly the two lines above.
- [ ] **Step 3: Add deploy line to `install.sh`**
Find the existing suspend/hibernate deploy block in `install.sh` (lines 71-73):
```bash
echo "==> Deploying suspend/hibernate config"
sudo install -Dm644 "$(pwd)/logind/lid.conf" /etc/systemd/logind.conf.d/lid.conf
sudo install -Dm644 "$(pwd)/sleep/hibernate-delay.conf" /etc/systemd/sleep.conf.d/hibernate-delay.conf
```
Immediately *after* the second `sudo install -Dm644` line (the sleep one), insert:
```bash
echo "==> Deploying NetworkManager config"
sudo install -Dm644 "$(pwd)/NetworkManager/conf.d/wifi-backend.conf" /etc/NetworkManager/conf.d/wifi-backend.conf
```
(Leading blank line for visual separation between the two deploy blocks.)
- [ ] **Step 4: Bash-syntax-check install.sh**
```bash
bash -n install.sh && echo "syntax ok"
```
Expected: `syntax ok` and exit 0.
- [ ] **Step 5: Confirm the new line is in place**
```bash
grep -n "wifi-backend" install.sh
```
Expected output:
```
sudo install -Dm644 "$(pwd)/NetworkManager/conf.d/wifi-backend.conf" /etc/NetworkManager/conf.d/wifi-backend.conf
```
- [ ] **Step 6: Commit**
```bash
git add NetworkManager/conf.d/wifi-backend.conf install.sh
git commit -m "NetworkManager: track wifi-backend.conf and deploy via install.sh"
```
---
## Task 2: Re-add `network-manager-applet` to packages.txt
After this task, `network-manager-applet` is back in the package manifest. Anyone setting up the system fresh installs the applet binary (currently still on this user's machine — uninstalling wasn't part of the earlier removal — but the manifest needs to match reality).
**Files:**
- Modify: `packages.txt` (re-add one line)
- [ ] **Step 1: Add `network-manager-applet` back to `packages.txt`**
Open `packages.txt`. The list isn't strictly alphabetical, but `networkmanager` is on line 17 (existing), so insert the applet on line 18 right after it:
Current lines 17-18:
```
networkmanager
xdg-desktop-portal-wlr
```
Becomes:
```
networkmanager
network-manager-applet
xdg-desktop-portal-wlr
```
- [ ] **Step 2: Verify the entry is present exactly once**
```bash
grep -c "^network-manager-applet$" packages.txt
```
Expected: `1`.
- [ ] **Step 3: Commit**
```bash
git add packages.txt
git commit -m "packages: re-add network-manager-applet (now functional)"
```
---
## Task 3: Re-add `nm-applet` spawn-at-startup in niri
After this task, `nm-applet --indicator` runs at niri start. Combined with the working SNI watcher (waybar's built-in), the network connection icon will appear in the tray once NetworkManager is enabled (Task 5, manual).
**Files:**
- Modify: `niri/config.kdl` (insert one spawn-at-startup line)
- [ ] **Step 1: Find the right insertion point**
The existing spawn-at-startup block is around lines 34-46 (after the env block, before `binds {`). It currently does NOT contain `nm-applet`. Insertion goes anywhere in that block; placing it logically with other applet-style spawns (after `awww-daemon` which is line 36) keeps it grouped with desktop-startup helpers.
- [ ] **Step 2: Insert the line**
Find lines 36-37:
```kdl
spawn-at-startup "awww-daemon"
spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
```
Insert between them:
```kdl
spawn-at-startup "nm-applet" "--indicator"
```
Result (lines 36-38):
```kdl
spawn-at-startup "awww-daemon"
spawn-at-startup "nm-applet" "--indicator"
spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
```
- [ ] **Step 3: Validate niri config**
```bash
niri validate 2>&1 | tail -2
```
Expected: a final line `INFO niri: config is valid`. Non-zero exit means a syntax issue.
- [ ] **Step 4: Confirm the line is in place**
```bash
grep -n 'nm-applet' niri/config.kdl
```
Expected: one match, `spawn-at-startup "nm-applet" "--indicator"`.
- [ ] **Step 5: Commit**
```bash
git add niri/config.kdl
git commit -m "niri: re-add nm-applet --indicator spawn-at-startup"
```
---
## Task 4: README — One-time NetworkManager activation subsection
After this task, the README documents the one-time `systemctl` swap so a fresh-install reader knows the manual step required after `install.sh` deploys the config.
**Files:**
- Modify: `README.md` (append a subsection after the existing "One-time hibernation enablement")
- [ ] **Step 1: Append the new subsection**
Open `README.md`. The last subsection is `### One-time hibernation enablement` (added previously). After its closing line, append:
````markdown
### One-time NetworkManager activation
After `install.sh` deploys the NetworkManager 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` (tray icon) or `networkmanager_dmenu` (waybar network widget click).
````
(The outer fence above is four backticks because the block contains a triple-backtick code block — paste the inner content verbatim, no enclosing 4-backtick fence.)
- [ ] **Step 2: Verify the section was added**
```bash
grep -A 6 "One-time NetworkManager activation" README.md
```
Expected: the new subsection prints, including the `sudo systemctl enable --now NetworkManager` line.
- [ ] **Step 3: Commit**
```bash
git add README.md
git commit -m "docs: document one-time NetworkManager activation"
```
---
## Final verification (controller, post-merge)
These run on the live system, after merging all four task commits and running the README's manual systemctl commands.
- [ ] **Run install.sh to deploy the config**
```bash
bash install.sh
# Expects "==> Deploying NetworkManager config" to appear in output
ls -la /etc/NetworkManager/conf.d/wifi-backend.conf
```
Expected: the file exists, mode 644, owned by root, content matches the repo file.
- [ ] **Run the documented systemctl swap (one-time, requires sudo)**
```bash
sudo systemctl disable --now systemd-networkd
sudo systemctl enable --now NetworkManager
```
Expected: both succeed; wifi briefly drops then reconnects within ~5-10 s.
- [ ] **Verify NetworkManager is the active connection manager**
```bash
systemctl is-active NetworkManager # active
systemctl is-active systemd-networkd # inactive
nmcli general status # prints connectivity status
nmcli connection show --active # shows the wifi connection
```
- [ ] **Verify nm-applet appears in the tray**
After a niri restart (or `niri msg action spawn -- nm-applet --indicator` if niri's spawn IPC supports it), the nm-applet tray icon should appear in waybar:
```bash
busctl --user get-property org.kde.StatusNotifierWatcher \
/StatusNotifierWatcher org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems
```
Expected: includes `:.../org/ayatana/NotificationItem/nm_applet` (or similar nm_applet entry).
- [ ] **Verify the waybar network widget click works**
Click the network module in waybar — `networkmanager_dmenu` should pop up a wofi-style picker listing available networks. Selecting one should connect.