Guides · Tailscale
Get a Mac notification when a Tailscale node joins, leaves or its key is about to expire
Tailscale's admin console can post tailnet events, a node added, removed or approved, a key about to expire, to a webhook. Every one becomes a notification on your Mac and a count for the month.
Needs: the free EventBar app on your Mac, an EventBar account, and a Tailscale account with permission to add webhooks. About five minutes. Generic JSON.
Steps
- Create the webhook URL. In the EventBar dashboard, open the Webhooks tab, pick the group this belongs to (one group per site or app is the usual shape), choose the provider Generic JSON, name it, and press Create. Copy the URL; it stays visible and can be rotated any time.
- Paste it into Tailscale. In the Tailscale admin console: Settings, then Webhooks, then Add endpoint. Paste the hook URL and tick the events (nodes created, deleted and approved; key expiring and expired). Tailscale shows a signing secret; you can skip it. Create the EventBar hook as Generic JSON with default type
tailscale: Tailscale wraps each delivery in a JSON array, and the generic preset reads an array as one text body, so a type field has nothing to find. For a separate switch per kind of event, add a second endpoint in Tailscale with only the key-expiry events ticked, pointed at a second hook with default typetailscale_keys. - Trigger one. Most services offer a test delivery; otherwise do the real thing once. It shows up in the dashboard's Events tab within a second and in the menu bar, as an undefined type named after the event. That first one is your proof the wiring works.
- Make it read well. Press Define on the new type and give it a title and a body template. Fields come from the payload, nested ones with dots. The table below is a starting point.
What you'll see
| Type | Title | Body template |
|---|---|---|
tailscale | Tailnet event | {message} |
tailscale_keys | Key expiry | {message} |
Every type has its own switch in the menu bar, so a noisy one can be quiet on this Mac and still counted. Counts cover the last hour, 24 hours, 7 days, 30 days and all time.
Worth knowing
{message}is the whole delivery as text. Each element in it has atype(nodeCreated,nodeDeleted,nodeApproved,nodeKeyExpiringInOneDay,nodeKeyExpired), a one-linemessageand adataobject naming the node; you read them in the text rather than as separate fields. If you want a switch per event kind, a few lines of Worker between Tailscale and the hook can unwrap the array and forward each element on its own.- Tailscale signs with
Tailscale-Webhook-Signature; the generic preset doesn't check it. The URL is the secret. - The endpoint's menu in the admin console can send a test event; it counts once and proves the wiring.
The full contract, including how each preset reads a payload and what the answers mean, is in the API docs. Something about Tailscale's payload changed? Tell us and we'll fix the guide.