Setting Up Tailscale Health Monitoring with Uptime Kuma

A comprehensive guide to monitoring your Tailscale network health using Uptime Kuma and a custom bash script.

If you're running Tailscale in your homelab, you know how crucial it is to ensure your network stays healthy and connected. After experiencing a few unexpected disconnections that took longer than necessary to notice, I decided to build a better monitoring solution using Uptime Kuma. What started as a simple ping check evolved into a more robust monitoring process that I've been running successfully for months.

In this guide, I'll share my complete setup for monitoring Tailscale using two complementary approaches: a custom health check script that watches your Tailscale service's vital signs, and a straightforward ping monitor that ensures continuous connectivity. I hope the effort I've put into developing and refining these monitoring solutions can help others in the homelab community who want to keep a closer eye on their Tailscale networks.

Whether you're running a small home network or managing a complex homelab setup, this monitoring solution will help you catch issues early and maintain a reliable Tailscale connection. Let's dive into how it all works.

Let's Dive In

I run two complementary monitors for my Tailscale network:

  1. A push monitor with a custom script for detailed health checks
  2. A basic ping monitor for continuous connectivity verification

Let's look at both setups:

The Monitoring Stack

The system consists of three main components:

  1. A bash script for health checks
  2. An Uptime Kuma push monitor
  3. A cron job for automated monitoring

Let's dive into each component and how they work together.

Setting Up the Health Monitor

1. Configuring the Push Monitor

In your Uptime Kuma installation, create a new monitor with these exact settings:

Monitor Type: Push
Friendly Name: Tailscale Health
Heartbeat Interval: 60 seconds
Retries: 3
Heartbeat Retry Interval: 60 seconds
Monitor Group: Security & Access Group
Tags:
  - Authentication
  - Network
  - Networking

After saving, you'll get a push URL that looks like:

https://your-uptime-kuma-instance/api/push/yourtoken?status=up&msg=OK&ping=

This URL should be called every 60 seconds. Remember that status, msg, and ping are optional parameters that our script will use.

First, we'll create a directory for our monitoring scripts:

mkdir -p ~/tailscale

Here's the complete monitoring script:

#!/bin/bash

# Configuration
PUSH_URL="YOUR_UPTIME_KUMA_PUSH_URL"
LOG_FILE="$HOME/tailscale/health.log"

# Function to URL encode
urlencode() {
    local string="${1}"
    local strlen=${#string}
    local encoded=""
    local pos c o

    for (( pos=0 ; pos<strlen ; pos++ )); do
        c=${string:$pos:1}
        case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               printf -v o '%%%02x' "'$c"
        esac
        encoded+="${o}"
    done
    echo "${encoded}"
}

# Initialize log file
exec 1> >(tee -a "$LOG_FILE") 2>&1
echo "=== Health check started at $(date) ==="

# Debug output
echo "Checking Tailscale status..."
SYSTEMCTL_STATUS=$(systemctl status tailscaled)
echo "$SYSTEMCTL_STATUS"

# Check Tailscale status
STATUS="down"
MESSAGE="Tailscale issues detected"

# Perform health checks with debug output
if systemctl is-active --quiet tailscaled; then
    echo "Tailscale daemon is active"
    TAILSCALE_IP=$(tailscale ip -4 2>/dev/null)
    if [ ! -z "$TAILSCALE_IP" ]; then
        echo "Tailscale IP found: $TAILSCALE_IP"
        if echo "$SYSTEMCTL_STATUS" | grep -q "Status.*Connected"; then
            echo "Tailscale shows connected status"
            STATUS="up"
            MESSAGE="Tailscale healthy - IP: $TAILSCALE_IP"
        else
            echo "Tailscale not showing connected status in systemctl"
        fi
    else
        echo "No Tailscale IP found"
        MESSAGE="Tailscale issues detected - No IP assigned"
    fi
else
    echo "Tailscale daemon is not active"
    MESSAGE="Tailscale issues detected - Daemon not active"
fi

# URL encode the message
ENCODED_MESSAGE=$(urlencode "$MESSAGE")

# Construct and send the push request
FINAL_URL="${PUSH_URL}?status=${STATUS}&msg=${ENCODED_MESSAGE}"
echo "Sending request to: $FINAL_URL"
curl -s "$FINAL_URL"

# Log completion
echo "Status: $STATUS"
echo "Message: $MESSAGE"
echo "=== Health check completed at $(date) ==="
echo "----------------------------------------"

Save this script as check-tailscale.sh and make it executable:

chmod +x check-tailscale.sh

The script performs several key checks:

  • Verifies the Tailscale daemon is running
  • Checks for a valid IP assignment
  • Confirms the connection status
  • Logs all activities for debugging
  • Pushes status updates to Uptime Kuma

2. Configuring Uptime Kuma

In your Uptime Kuma installation:

  1. Create a new monitor with these settings:

    Monitor Type: Push
    Friendly Name: Tailscale Health
    Heartbeat Interval: 60 seconds
    Heartbeat Retry Interval: 60 seconds
    Retries: 3
    
  2. After saving the monitor, Uptime Kuma will generate a unique push URL. It will look something like:

    https://your-uptime-kuma-instance/api/push/xxxxxxxx
    
  3. Copy this push URL - you'll need to update the script with it:

    • Open the script in your editor
    • Replace YOUR_UPTIME_KUMA_PUSH_URL with the URL you just copied
    • Save the script

This push URL is unique to this monitor and acts as an authentication token. Keep it secure, as anyone with this URL can push status updates to your monitor.

3. Setting Up the Cron Job

To run the check every minute, add this to your crontab:

crontab -e

Add the line:

* * * * * ~/tailscale/check-tailscale.sh

Monitoring Details

The script provides comprehensive monitoring of your Tailscale installation:

  • Daemon Status: Ensures the Tailscale service is running
  • IP Assignment: Verifies your node has a valid Tailscale IP
  • Connection State: Checks if you're properly connected to the Tailscale network
  • Overall Health: Combines multiple checks for a complete health status

Logging

The script maintains a detailed log file at ~/tailscale/health.log. You can view recent logs with:

tail -f ~/tailscale/health.log

Troubleshooting Guide

If you run into issues, here's a systematic way to troubleshoot:

  1. Test Script Execution:

    ./check-tailscale.sh
    
  2. Verify Cron Service:

    systemctl status cron
    
  3. Check Script Permissions:

    ls -l check-tailscale.sh
    
  4. Review Recent Logs:

    tail -n 50 ~/tailscale/health.log
    

Expected Behavior

When everything is working correctly, you'll see:

Status: up
Message: Tailscale healthy - IP: [Your Tailscale IP]

If issues are detected:

Status: down
Message: Tailscale issues detected - [specific issue]

Maintenance Tips

Regular maintenance tasks to keep in mind:

  1. Monitor Log Size:

    du -h ~/tailscale/health.log
    
  2. Set Up Log Rotation: Create a logrotate configuration at /etc/logrotate.d/tailscale-monitor

  3. Regular Status Checks:

  • For Tailscale: tailscale status
  • For the daemon: systemctl status tailscaled

Setting Up the Connectivity Monitor

In addition to the health check, I run a basic ping monitor to continuously verify connectivity. This provides a simpler, more direct check of the Tailscale network.

Create a new monitor in Uptime Kuma with these settings:

Monitor Type: Ping
Friendly Name: Tailscale Basic Connectivity
Hostname: YOUR_TAILSCALE_IP  # Your Tailscale IP address
Heartbeat Interval: 60 seconds
Retries: 0
Heartbeat Retry Interval: 60 seconds
Packet Size: 57
Monitor Group: Security & Access Group
Tags:
  - Authentication
  - Network
  - Networking
  - Security

This monitor provides a different perspective on your Tailscale network:

  • While the health check monitors the service and daemon status
  • The ping monitor verifies actual network connectivity
  • Together, they provide comprehensive monitoring coverage

Notifications

I have both monitors configured to send notifications through a personal Discord bot. This setup ensures I'm immediately aware of any issues with either:

  • The Tailscale service itself (from the health monitor)
  • The actual network connectivity (from the ping monitor)

You can configure notifications in Uptime Kuma to use various channels:

  • Discord
  • Email
  • Telegram
  • Slack
  • And many others

Getting Help

If you run into issues:

  1. Check Tailscale's official documentation
  2. Verify Uptime Kuma's push monitor settings
  3. Review script logs for specific errors
  4. Ensure all permissions are set correctly

This setup has been running in my homelab for months now, providing peace of mind that my Tailscale network is healthy and functioning as expected.


This post is part of my homelab documentation series. Check out my other posts for more networking and monitoring tips!