tailnet: Tailscale status & control - #373
Merged
Merged
Conversation
Tailscale status and control for Noctalia v5, ported from the v4 tailscale plugin: bar widget, panel with an online-first peer list, headless poller, up/down control-center shortcut, /tn launcher provider and a desktop widget. The core flow is host access — fuzzy-search the tailnet and copy a peer's IP or short name in one gesture. The plugin is called tailnet rather than tailscale because davemhammer/tailscale already owns the tailscale/ directory and the /ts launcher prefix; the two share no ids, state keys or prefix, and the README says what each one focuses on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three things the freshly merged davemhammer/tailscale does that this plugin did not, plus the fix its poller design suggested: - Every poll carries a generation number. Callbacks from a superseded poll are dropped, and a poll still pending after 20s is treated as lost so the next one can take over — a poll spans several subprocesses, and one callback that never fires used to wedge the poller for good. - The panel surfaces the daemon's own Health warnings, which explain most 'connected but nothing works' situations. - A row of toggles drives tailscale set: shields-up, accept-routes, the SSH server, advertise-exit-node and exit-node-allow-lan-access. Reading them back needs tailscale debug prefs, whose output also carries the node's private key; the plugin keeps the five booleans and discards the rest, which the README states. - tailscale_bin for installs that keep the binary off PATH, and an admin console button (admin_url overrides the default). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The repo README asks contributors for translations/en.json alone — other locales come back through i18n.noctalia.dev as maintainer commits, and no it.json exists anywhere in the catalog. The Italian translation stays in the local install. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The repo validator rejects en.json keys that are not single lowercase segments, so pref.shieldsUp and its four siblings never would have passed CI. Each toggle now carries its own translation key alongside the tailscale set flag, since neither can be the snapshot field name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The old one still read "Tailscale" and showed a panel header from before the rename. Regenerated with the official generator, with the current panel (preference toggle row included) and the addresses masked. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plugin
rylos/tailnetplugin.toml)This replaces #72, which I opened as
rylos/tailscalebeforedavemhammer/tailscalelanded. Renamed torylos/tailnetto leave that idalone, and reworked after @ItsLemmy's review; the launcher prefix is
/tn.What it does
Tailscale status and control from the bar: whether you are connected, who else
is on the tailnet, and the handful of actions you would otherwise reach for the
CLI to do.
the admin console, a row of five
tailscale settoggles (shields-up, acceptroutes, Tailscale SSH, advertise as exit node, LAN access while on an exit
node), any
tailscale statushealth warnings, then the peer list: onlinefirst, filterable, with per-row copy IP, copy name, ping, SSH, and an
exit-node toggle on peers that offer one.
/tn) — every host, Enter copies its IP.External dependencies
tailscale— every action shells out to it; the binary can be pointedelsewhere in settings (
tailscale_bin) for non-standard installs.ssh— only when the SSH button on a peer row is used; it opens in theconfigured terminal.
xdg-user-dir— to find the Downloads directory for Taildrop.gio/xdg-open— to open the admin console.All declared in
dependencies.Testing
In daily use on niri against my own tailnet (18 hosts, mixed
Linux/Android/OpenWrt), which is where the panel, launcher and bar widget in the
screenshots come from.
clear, ping, SSH, copy IP and name, Taildrop receive, the admin-console
button, and the filter — exercised over the course of using it.
/tn, filtering and Enter to copy, re-checked for this PR.tailscalestopped, to see thestopped and error states.
noctalia plugins lint tailnetandpython3 .github/workflows/scripts/validate-plugins.pyare clean.Since #72: the numbered callback slots @ItsLemmy asked about are gone —
every peer row passes a closure that captures its own peer (
plugin_api9), sothe list is no longer capped at 24 rows and there are no ~96 numbered globals.
curlis gone, the openers are declared, the poll is generation-counted so alate subprocess cannot overwrite a newer snapshot, and the health box, the
preference toggles,
tailscale_binand the admin-console button are new.One note on
tailscale ping: it exits 1 with "direct connection notestablished" when a peer only answers over a DERP relay, even though the pongs
arrive. The plugin reports that as reachable-via-relay rather than as an error.
Screenshots / Videos
Panel — the toggle row is under the node card; Tailscale IPs are masked:
Launcher,
/tn(IPs masked, one hostname replaced):Bar widget — the Tailscale dots, next to the Syncthing arrows:
Checklist
idafter the/inplugin.tomlexactly.plugin.toml,README.md,thumbnail.webp, andtranslations/en.json.README.mdfollows theREADME template, documents
every entry id and dependency, and includes exact panel IPC commands and launcher prefixes where applicable.
thumbnail.webpwith the thumbnail generator.versionfollows semver and is bumped in this PR;plugin_apiis the oldest API level this plugin requires.understand that language well enough to review and maintain it (no unreviewed machine/LLM translations).
catalog.toml; CI generates it.Code review attestation
Plugins run as trusted, unsandboxed Luau in the user's session. Confirm:
licensedeclared inplugin.toml.