1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#+TITLE: Net Panel — Tailscale, VPN, and WireGuard Interfaces
#+AUTHOR: Craig Jennings
#+DATE: 2026-07-02
#+TODO: TODO | DONE
#+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED
* DRAFT Status
:PROPERTIES:
:ID: 79a1075a-4b56-4f25-a861-b69f120a636a
:END:
- [2026-07-02 Thu] DRAFT — initial spec from the roam capture "other network
interfaces (tailscale, VPNs, wireguard)" filed in todo.org 2026-07-02.
* Metadata
| Field | Value |
|--------+---------------------------------------------------|
| Status | draft |
|--------+---------------------------------------------------|
| Owner | Craig Jennings |
|--------+---------------------------------------------------|
| Repo | dotfiles (net module); archsetup (packages) |
|--------+---------------------------------------------------|
| Parent | Waybar network module spec (2026-06-29), V2 panel |
|--------+---------------------------------------------------|
* Problem
The net panel's Connections tab shows what NetworkManager knows: WiFi networks
and wired links. The machines also run overlay and tunnel interfaces the panel
is blind to:
- Tailscale (tailscaled, both daily drivers; the tailnet is how the machines
reach each other; not an NM device)
- WireGuard configs (assets/wireguard-config/ carries Proton VPN configs;
importable as NM connections of type wireguard or run via wg-quick)
- Commercial VPN clients (Proton VPN GTK app is installed on velox; owns its
own tunnel device)
When one of these is up it changes routing, DNS, and reachability — exactly
the things the Diagnostics tab reasons about — yet the panel neither shows nor
controls them, and the doctor can misattribute a VPN-caused failure to the
underlying link.
* Goals
1. Visibility: the Connections tab shows overlay/tunnel interfaces with live
state (up/down, address, and for tailscale the tailnet peers summary).
2. Control: bring each up or down from the panel row, same interaction shape
as Join/Disconnect on WiFi rows (no terminals — V2 contract).
3. Diagnostics awareness: diagnose/doctor know when a tunnel owns the default
route or DNS, name it in evidence rows, and stop misattributing its
failures to the physical link.
Non-goals (this iteration): installing or configuring VPN providers, tailnet
ACL management, exit-node selection UI (a "use exit node" affordance can ride
a later pass), kill-switch management (tracked separately in the spec's
failure catalog).
* Design sketch
** Data sources — one probe per backend, engine-side
New GTK-free module net/src/net/overlays.py with one probe per backend,
each returning the same small dict shape ({kind, name, state, addr, detail,
can_toggle}):
- tailscale: =tailscale status --json= (rich: self, peers, exit node, health
messages). Daemon down → state "stopped". Binary absent → backend absent.
- wireguard-nm: =nmcli -t connection show= filtered to type wireguard —
up/down via the existing nmcli wrapper (activate/deactivate connection).
- wg-quick configs outside NM (files in /etc/wireguard) — read-only listing
at most; toggling them requires root and wg-quick; probably defer.
- proton-gtk: detect its tunnel device (proton0 / ipv6leakintf) when up;
control stays with the Proton app (can_toggle false, detail points at the
app) unless Craig prefers driving it via its CLI.
** Panel
A fourth Connections group "Tunnels" (after Saved / Available now / Wired)
using the existing group-header + row machinery. Row: glyph per kind, name,
state caption; primary action Up/Down where can_toggle, else Open app.
Tailscale row detail (subtitle or tooltip): tailnet name, peer count online,
exit node if any.
** Privileged path
- tailscale up/down: needs root or operator — =tailscale set --operator= at
install time (archsetup) makes the user an operator, so no sudo needed at
runtime. Fallback: the V2 net-priv helper gains tailscale-up/down verbs.
- NM wireguard connections: no privilege needed (NM polkit default for the
active user).
** Diagnostics awareness
- diag gains an "overlay owns default route/DNS" detection step: when the
default route or resolv.conf points at a tunnel interface, evidence names
it ("default route via tailscale0") and failure classification runs the
physical-link checks against the underlying device instead.
- doctor: a tunnel-caused egress failure (VPN up but its endpoint dead)
classifies fixable with next_action "bring the tunnel down / reconnect",
not a WiFi reset.
** Bar indicator
Unchanged by default. Optional later: a small overlay badge on the net glyph
when a tunnel owns the default route.
* Decisions (Craig)
** TODO Which backends ship in the first pass?
Recommendation: tailscale + NM-managed wireguard. Proton app detection-only.
wg-quick configs deferred.
** TODO Tailscale control path: operator flag at install vs net-priv verbs?
Recommendation: =tailscale set --operator=$USER= in archsetup's tailscale
step (declarative, no sudo at runtime); net-priv verbs only if operator mode
proves insufficient (e.g. up with flags).
** TODO Does "Tunnels" belong in Connections or its own tab?
Recommendation: a Connections group. A fourth top tab dilutes the V2 nav for
three rows.
** TODO Proton VPN: detect-only or drive its CLI?
Recommendation: detect-only first; the app owns reconnect/kill-switch logic.
* Implementation phases
1. overlays.py probes (tailscale JSON, nmcli wireguard filter, proton device
detection) — pure engine, TDD with fake binaries; =net status= grows an
overlays section.
2. Panel Tunnels group + Up/Down wiring through the worker thread; AT-SPI
smoke extension.
3. Diagnose/doctor overlay awareness (route/DNS ownership step, classifier
rows, evidence text) — TDD against the diag harness.
4. archsetup: tailscale operator flag in the tailscale install step; VM test
assertion.
|