Files
portainer-core/scripts/setup-kuma-monitors.py
T

248 lines
7.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Automated Uptime Kuma Monitor Setup for tower-of-joy Infrastructure
This script automatically creates monitors for all infrastructure services in Uptime Kuma.
It is idempotent - safe to run multiple times without creating duplicates.
Usage:
source .venv/bin/activate
python3 scripts/setup-kuma-monitors.py
Environment Variables:
KUMA_URL: Uptime Kuma URL (default: http://192.168.86.149:3001)
KUMA_USERNAME: Uptime Kuma admin username (will prompt if not set)
KUMA_PASSWORD: Uptime Kuma admin password (will prompt if not set)
"""
import os
import sys
from getpass import getpass
try:
from uptime_kuma_api import UptimeKumaApi, MonitorType
except ImportError:
print("\033[0;31mError: uptime-kuma-api package not installed\033[0m")
print("\nInstall dependencies:")
print(" source .venv/bin/activate")
print(" pip install -r requirements.txt")
sys.exit(1)
# Configuration
KUMA_URL = os.getenv("KUMA_URL", "http://192.168.86.149:3001")
# Service definitions
MONITORS = [
{
"name": "Portainer",
"url": "http://192.168.86.149:8001",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Container management interface"
},
{
"name": "Nginx Proxy Manager",
"url": "http://192.168.86.149:81",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Reverse proxy admin interface"
},
{
"name": "Ollama API",
"url": "http://192.168.86.149:11434",
"interval": 60,
"type": MonitorType.HTTP,
"description": "ML model API endpoint"
},
{
"name": "Headscale",
"url": "http://192.168.86.149:8085/health",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Mesh VPN control server"
},
{
"name": "Uptime Kuma",
"url": "http://192.168.86.149:3001",
"interval": 120,
"type": MonitorType.HTTP,
"description": "Service monitoring (self-check)"
},
{
"name": "Netdata",
"url": "http://192.168.86.149:19999",
"interval": 60,
"type": MonitorType.HTTP,
"description": "System metrics dashboard"
},
{
"name": "Heimdall",
"url": "http://192.168.86.149:8888",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Application dashboard"
},
{
"name": "Organizr",
"url": "http://192.168.86.149:9999",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Unified dashboard"
},
{
"name": "Jellyfin",
"url": "http://192.168.86.149:8096",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Media streaming server"
},
]
def print_color(text, color="reset"):
"""Print colored text"""
colors = {
"red": "\033[0;31m",
"green": "\033[0;32m",
"yellow": "\033[1;33m",
"blue": "\033[0;34m",
"cyan": "\033[0;36m",
"reset": "\033[0m"
}
print(f"{colors.get(color, '')}{text}{colors['reset']}")
def get_credentials():
"""Get credentials from environment or prompt user"""
username = os.getenv("KUMA_USERNAME")
password = os.getenv("KUMA_PASSWORD")
if not username:
print_color("\nUptime Kuma credentials required", "yellow")
username = input("Username: ").strip()
if not password:
password = getpass("Password: ").strip()
return username, password
def setup_monitors():
"""Configure all monitors in Uptime Kuma"""
print_color("╔════════════════════════════════════════════╗", "blue")
print_color("║ Uptime Kuma Automated Monitor Setup ║", "blue")
print_color("╚════════════════════════════════════════════╝", "blue")
print()
print(f"Target: {KUMA_URL}")
print(f"Monitors to configure: {len(MONITORS)}")
print()
# Get credentials
username, password = get_credentials()
# Connect to Uptime Kuma
print_color("\nConnecting to Uptime Kuma...", "blue")
try:
api = UptimeKumaApi(KUMA_URL)
api.login(username, password)
print_color("✓ Connected successfully", "green")
except Exception as e:
print_color(f"✗ Connection failed: {e}", "red")
print()
print("Troubleshooting:")
print(" 1. Verify Uptime Kuma is running: docker ps | grep uptime-kuma")
print(f" 2. Check URL is correct: {KUMA_URL}")
print(" 3. Verify credentials are correct")
sys.exit(1)
print()
# Get existing monitors
print_color("Fetching existing monitors...", "blue")
existing_monitors = api.get_monitors()
existing_names = {m["name"] for m in existing_monitors}
print(f"Found {len(existing_monitors)} existing monitor(s)")
print()
# Configure each monitor
print_color("Configuring monitors...", "blue")
print()
created = 0
skipped = 0
failed = 0
for monitor_def in MONITORS:
name = monitor_def["name"]
if name in existing_names:
print(f"⊙ {name} - Already exists (skipping)")
skipped += 1
continue
try:
# Create the monitor
api.add_monitor(
type=monitor_def["type"],
name=name,
url=monitor_def["url"],
interval=monitor_def["interval"],
description=monitor_def.get("description", ""),
retryInterval=60,
resendInterval=0,
maxretries=1,
upsideDown=False,
notificationIDList=[],
httpBodyEncoding="utf8",
method="GET",
maxredirects=10,
accepted_statuscodes=["200-299"]
)
print_color(f"✓ {name} - Created", "green")
print(f" URL: {monitor_def['url']}")
print(f" Interval: {monitor_def['interval']}s")
created += 1
except Exception as e:
print_color(f"✗ {name} - Failed: {e}", "red")
failed += 1
print()
# Disconnect
api.disconnect()
# Summary
print_color("═══════════════════════════════════════════", "blue")
print_color("Summary:", "green")
print_color("═══════════════════════════════════════════", "blue")
print(f"Created: {created}")
print(f"Skipped (already exist): {skipped}")
print(f"Failed: {failed}")
print()
if created > 0:
print_color("✓ Setup complete! Monitors are now active.", "green")
print()
print("View monitors at:", KUMA_URL)
print("Refresh Organizr to see status widgets update")
elif skipped == len(MONITORS):
print_color("✓ All monitors already configured", "green")
else:
print_color("⚠ Some monitors could not be created", "yellow")
sys.exit(1)
if __name__ == "__main__":
try:
setup_monitors()
except KeyboardInterrupt:
print()
print_color("Setup cancelled by user", "yellow")
sys.exit(130)
except Exception as e:
print()
print_color(f"Unexpected error: {e}", "red")
import traceback
traceback.print_exc()
sys.exit(1)