Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tailscale/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ noctalia msg plugin davemhammer/tailscale:service all toggle

## Notes

- Shells out to `tailscale status --json | jq …` (same Mullvad-exit filter as text `status`; those nodes stay on the Exit tab via `exit-node list`), `tailscale debug prefs | jq …` (safe field projection), `tailscale exit-node list`, `tailscale set …`, `tailscale up` / `down`, optional `tailscale ping` / `tailscale ssh` in a terminal, and `xdg-open` for the admin URL. A raw `--json` dump on a Mullvad-enabled tailnet is large enough to trip Noctalia's plugin CPU budget and auto-disable the service.
- Shells out to `tailscale status --json | jq …` (same Mullvad-exit filter as text `status`, then only the fields the service reads; unused Mullvad nodes stay on the Exit tab via `exit-node list`), `tailscale debug prefs | jq …` (safe field projection), `tailscale exit-node list`, `tailscale set …`, `tailscale up` / `down`, optional `tailscale ping` / `tailscale ssh` in a terminal, and `xdg-open` for the admin URL. A raw `--json` dump on a Mullvad-enabled tailnet is large enough to trip Noctalia's plugin CPU budget and auto-disable the service.
- Advertise-exit state is read from prefs `AdvertiseRoutes` (`0.0.0.0/0` / `::/0`), not only `ExitNodeOption`.
- Network: only through the Tailscale CLI/daemon (no separate HTTP client in the plugin).
- Filesystem: no plugin-written credentials; uses local Tailscale state via the CLI.
Expand Down
2 changes: 1 addition & 1 deletion tailscale/plugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

id = "davemhammer/tailscale"
name = "Tailscale"
version = "1.0.6"
version = "1.0.7"
plugin_api = 10
author = "davemhammer"
license = "MIT"
Expand Down
17 changes: 15 additions & 2 deletions tailscale/service.luau
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,24 @@ end

-- Same rule as `tailscale status` (text): unused Mullvad exits belong on
-- `exit-node list`, not in Peer. `--json` does not apply this, and the raw
-- dump is large enough to trip Noctalia's 25ms plugin CPU budget.
-- dump is large enough to trip Noctalia's 25ms plugin CPU budget. After the
-- Peer filter, drop unused fields (sshHostKeys, CapMap, …) so decode stays small.
local function statusJsonCommand(bin)
local jq = [[
.Peer |= with_entries(select(
(.value.ExitNodeOption != true)
or (.value.ExitNode == true)
or ((.value.DNSName // "") | endswith("mullvad.ts.net.") | not)
))
| {
BackendState, Version, TailscaleIPs, MagicDNSSuffix, Health,
CurrentTailnet, ExitNodeStatus,
Self: ((.Self // {}) | {ID, HostName, DNSName, Online, OS, Relay, ExitNodeOption, TailscaleIPs}),
Peer: ((.Peer // {}) | with_entries(.value |= {
ID, HostName, DNSName, Online, Active, OS, Relay,
ExitNode, ExitNodeOption, TailscaleIPs, RxBytes, TxBytes, LastSeen
}))
}
]]
return shellCommand({ bin, "status", "--json" }) .. " | jq -c " .. shellQuote(jq)
end
Expand Down Expand Up @@ -518,6 +528,7 @@ local function applyBag(statusData, prefsData, exitStdout, errors)
refreshStartedAt = 0
noctalia.setUpdateInterval(refreshIntervalMs())

local prevRev = snapshot.revision
updateRevision(table.concat({
snapshot.backendState,
snapshot.ipv4,
Expand All @@ -528,7 +539,9 @@ local function applyBag(statusData, prefsData, exitStdout, errors)
asString(snapshot.runSSH),
asString(snapshot.advertiseExitNode),
}, "|"))
publishSnapshot()
if snapshot.revision ~= prevRev then
publishSnapshot()
end
end

refreshAll = function()
Expand Down
Loading