A GTK4 + libadwaita graphical front-end and system-tray controller for
ZeroTier. Join and leave networks, flip routing
options — including the default route (full tunnel), managed routes, global
IP assignments and pushed DNS — name your peers, and start/stop the service, all
from a window or the tray, without memorising zerotier-cli flags.
Sibling project to Wayhelm — same stack, same tray-first philosophy.
Networks tab
- A prominent node card: your ZeroTier address (one-click copy), a colored status pill (Online / Offline / Access needed / Stopped), ZeroTier version, service state, peer count, and a Start / Stop service button.
- Join a network — paste a 16-digit network ID and go.
- A row per network with a big status pill (Connected / Requesting… / Access
denied …) and assigned IPs, expanding to:
- toggles for Allow managed IP & routes, Allow global IP assignments, Default route (full tunnel) and Allow DNS configuration;
- detail rows: assigned addresses, managed routes, pushed DNS, and link info (type / interface / MTU / MAC / broadcast);
- Disconnect (leave but remember for later) and Forget (leave for good).
- Disconnected networks stay listed with a Reconnect button that re-joins and re-applies their saved routing toggles.
Peers tab
- A table of every ZeroTier node yours is talking to — Node (with an editable
friendly name shown as
name (id)), role (leaf / planet / moon), latency, version, and the active path (IP:port, or relayed). - Click the pencil to give a peer a friendly name; names are stored locally and persist.
Settings tab
- Close-to-tray, start-hidden-on-autostart, notifications, XDG autostart toggle.
- API access — grant Zerohelm read access to the control token (see below).
Advanced tab
- Diagnostics (installed / service active / token readable / backend / online / peers), live state as JSON, and a service-journal viewer.
Tray icon (StatusNotifierItem — waybar tray, swaync, Plasma, GNOME…)
- Color-coded so the state reads at a glance: grey (stopped), red (needs access), amber (up, idle), green (connected). A header line and tooltip spell it out.
- Right-click: Show, Grant access (when needed), a submenu per network (status, Default route toggle, Disconnect, Forget), a submenu per disconnected network (Reconnect / Forget), Start/Stop service, Refresh, Quit.
Zerohelm auto-detects the best backend each poll:
- Local control API (
http://127.0.0.1:9993,X-ZT1-Authtoken) — preferred. zerotier-cli— fallback (used when Zerohelm runs as root).
The control token at /var/lib/zerotier-one/authtoken.secret is root-only. When
Zerohelm needs it, click Grant access (or the prompt on launch); a single
pkexec reads the token straight into process memory — a zeroizing buffer
that is wiped on drop — and it is kept only for the lifetime of the running app.
- The token is never written to disk and never logged.
- Quit Zerohelm and the access is gone; the next session prompts again.
- If Zerohelm is run as root (or the file is otherwise readable to it), it reads the token directly with no prompt.
Starting/stopping the system zerotier-one.service always uses pkexec systemctl.
Each privileged action is a short-lived, narrowly-scoped pkexec call — Zerohelm
itself runs entirely unprivileged and never holds root.
Runtime
zerotier-one(the daemon being managed)gtk4,libadwaita,dbusshared libraries- A StatusNotifierItem-aware tray host (for the tray icon)
polkit/pkexec(for service control and reading the token)systemctl(service control),journalctl(optional journal viewer)
Once published to the AUR:
yay -S zerohelm # stable
yay -S zerohelm-git # latest commitUntil then, build the PKGBUILD locally:
git clone https://github.com/NetNinjaCorp/ZeroHelm.git
cd ZeroHelm/packaging
makepkg -sinix run github:NetNinjaCorp/ZeroHelm
# or add to your inputs and use packages.x86_64-linux.defaultBuild prerequisites (Arch names; substitute your distro's): rust, cargo,
gtk4, libadwaita, dbus, pkgconf.
git clone https://github.com/NetNinjaCorp/ZeroHelm.git
cd ZeroHelm
make build
sudo make install PREFIX=/usrLaunch from your application menu or run zerohelm. Click Grant access so it
can read the control token into memory for this session (one pkexec prompt per
run). Then join a network by pasting its ID, toggle routing per network, and use
Disconnect/Reconnect to come and go without losing your settings. zerohelm --hidden starts tray-only (used by the autostart entry).
| Path | Purpose |
|---|---|
~/.config/zerohelm/settings.json |
Zerohelm's own preferences, remembered networks, and peer friendly names (mode 0600) |
~/.config/autostart/zerohelm.desktop |
XDG autostart entry (when enabled) |
/var/lib/zerotier-one/ |
ZeroTier's own state, incl. the root-only authtoken.secret (read into memory only) |
The control token is never persisted by Zerohelm — it lives only in memory while the app runs.
cargo build --release
./target/release/zerohelmCI builds release artifacts on every tag push (.github/workflows/release.yml).
MIT. See LICENSE.
v0.1.0 — initial release, known to work on Arch/CachyOS + Hyprland with zerotier-one 1.16. Bug reports and PRs welcome.