Schedule icon
Request icon
Return icon
Switch icon
Log icon
SlackIncomingWebhook icon
OutputValues icon

Headscale Tailnet Node Health and Expiry Sentinel

Audit Headscale self-hosted Tailscale control plane node health, monitor machine key expiry timestamps, detect offline peers, and alert Slack via Kestra.

Categories
Infrastructure

Continuously audits Headscale self-hosted Tailscale control planes by querying REST APIs, monitoring WireGuard mesh node connectivity, detecting impending machine key expiration deadlines, and routing escalation alerts to Slack.

How it works

  1. probe_headscale_health checks /health on the Headscale control plane server to verify daemon process vitality and HTTP API responsiveness.
  2. probe_headscale_nodes queries /api/v1/node using a Bearer token to inspect all enrolled tailnet machines, IP addresses, connectivity statuses, and key expiration dates.
  3. probe_headscale_users queries /api/v1/user to verify registered namespace accounts and multi-tenant domain integrity.
  4. classify_tailnet_status evaluates node attributes through a Pebble expression:
    • Flags machines whose authentication keys expire within days_to_expiry_threshold and categorizes the state as EXPIRED_NODES_CRITICAL.
    • Flags disconnected nodes (online: false) when alert_on_offline_nodes is active and categorizes the state as OFFLINE_NODES_WARNING.
    • Confirms all enrolled nodes are connected with valid keys to categorize the state as HEALTHY.
    • Detects unreachable endpoints or non-200 responses to classify state as CONTROL_PLANE_UNREACHABLE or PROBE_FAILED.
  5. route_by_tailnet_status branches workflow execution based on the classification:
    • HEALTHY: Logs active node tallies, registered users, and key health status.
    • OFFLINE_NODES_WARNING: Dispatches a Slack notification naming disconnected tailnet nodes and assigned IP addresses.
    • EXPIRED_NODES_CRITICAL: Posts an urgent escalation alert to Slack naming machines approaching key expiration before mesh connectivity drops.
    • CONTROL_PLANE_UNREACHABLE: Alerts operations that the Headscale server is completely unreachable.
  6. log_audit_summary produces structured outputs recording node tallies, online/offline ratios, and expiration metrics for security auditing.
  7. errors catches unexpected task exceptions and posts a diagnostic notice to Slack.

What you get

  • Automated, continuous surveillance of self-hosted Tailscale overlay mesh networks without third-party monitoring agents.
  • Early warning before node keys expire, preventing sudden tunnel collapse and communication outages across databases, CI runners, and internal servers.
  • Immediate Slack alerts detailing machine hostnames, given names, assigned Tailscale IPs, and expiry timestamps.
  • Centralized audit tracking of network mesh health, node capacity, and user counts.
  • Automated scheduled daily auditing coupled with manual on-demand execution support.

Who it's for

  • Platform Engineers and Site Reliability Engineers managing self-hosted Headscale / Tailscale mesh infrastructure.
  • Network Administrators and Security Engineers operating zero-trust overlay networks for internal service communication.
  • DevSecOps teams responsible for maintaining high availability across distributed hybrid-cloud and edge nodes.

Why orchestrate this with Kestra

Headscale manages zero-trust network connectivity between critical infrastructure components. When an enrolled machine's authentication key expires, WireGuard tunnels silently drop, severing database replication, monitoring, and administrative access. Kestra provides declarative, reproducible orchestration with built-in scheduling, centralized secret management, granular failure classification, and auditable history across all network peers.

Prerequisites

  • A running Headscale control plane instance with HTTP port 8080 accessible from the Kestra worker.
  • A Headscale API key generated using headscale apikeys create.
  • An incoming Slack webhook URL for alert delivery.

Secrets

  • HEADSCALE_API_KEY: API token used for Bearer authentication against Headscale /api/v1/ endpoints.
  • SLACK_WEBHOOK: Incoming Slack webhook URL used by alert_offline_nodes_slack, alert_expired_nodes_slack, alert_probe_failed_slack, alert_unreachable_slack, and the errors handler.

Quick start

  1. Generate an API key on your Headscale instance:
    headscale apikeys create --expiration 90d
    
  2. Configure HEADSCALE_API_KEY and SLACK_WEBHOOK as secrets in your Kestra namespace.
  3. Start a local Headscale test instance using Docker:
    docker run -d --name headscale -p 8080:8080 headscale/headscale:latest headscale serve
    
  4. Execute this flow manually in Kestra setting headscale_host: "localhost" or "headscale".
  5. The workflow queries enrolled nodes, verifies key expiry, classifies HEALTHY, and records audit outputs.
  6. Enable the daily_morning_audit trigger to automate continuous daily morning monitoring.

How to extend

  • Add automated key renewal commands using the Kestra Docker or SSH plugin to re-authenticate expiring nodes.
  • Integrate with PagerDuty for EXPIRED_NODES_CRITICAL states affecting production database primary or replica nodes.
  • Route separate alerts to Slack channels partitioned by Headscale user namespaces.
  • Track node IP allocation drift against IPAM records by integrating with the Kestra NetBox or phpIPAM plugins.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.