ansible/scripts/kuma-add-monitors.sh
ilia cb18204f3a
Some checks failed
CI / skip-ci-check (pull_request) Successful in 35s
CI / lint-and-test (pull_request) Failing after 31s
CI / secret-scanning (pull_request) Successful in 9s
CI / dependency-scan (pull_request) Successful in 17s
CI / sast-scan (pull_request) Successful in 30s
CI / ansible-validation (pull_request) Successful in 1m15s
CI / license-check (pull_request) Successful in 15s
CI / vault-check (pull_request) Successful in 13s
CI / container-scan (pull_request) Successful in 8s
CI / sonar-analysis (pull_request) Successful in 8s
CI / playbook-test (pull_request) Successful in 27s
CI / workflow-summary (pull_request) Successful in 5s
Homelab sprint: monitoring stack, Caddy public URLs, vault secrets.
Deploy Kuma/Beszel monitoring docs and scripts, UniFi API key in vault,
listmonk migration inventory, status.levkin.ca + stats on Caddy, and
handoff doc for next agent.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 08:08:39 -04:00

90 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Add or update Uptime Kuma HTTP monitors via API.
# Usage:
# export KUMA_PASSWORD='...' # not in vault yet — set manually once
# ./scripts/kuma-add-monitors.sh
#
# Monitors are idempotent: existing names are skipped.
# Links the default SMTP notification to any monitor that has none.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
KUMA_URL="${KUMA_URL:-http://10.0.10.22:3001}"
KUMA_USER="${KUMA_USER:-admin}"
KUMA_PASSWORD="${KUMA_PASSWORD:-}"
if [[ -z "${KUMA_PASSWORD}" ]] && [[ -f "${REPO_ROOT}/.env" ]]; then
# shellcheck disable=SC1091
set -a
source "${REPO_ROOT}/.env"
set +a
KUMA_PASSWORD="${KUMA_PASSWORD:-}"
fi
if [[ -z "${KUMA_PASSWORD}" ]]; then
echo "Set KUMA_PASSWORD (admin UI password; not stored in vault yet)" >&2
exit 1
fi
export KUMA_URL KUMA_USER KUMA_PASSWORD
"${REPO_ROOT}/.venv/bin/python3" <<'PY'
import os
import sys
try:
from uptime_kuma_api import UptimeKumaApi
except ImportError:
print("Run: .venv/bin/pip install uptime-kuma-api", file=sys.stderr)
sys.exit(1)
# Public HTTPS endpoints worth watching (Beszel covers host metrics separately).
MONITORS = [
{"type": "http", "name": "levkin.ca", "url": "https://levkin.ca", "interval": 60, "retryInterval": 60, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
{"type": "http", "name": "Portfolio", "url": "https://iliadobkin.com", "interval": 60, "retryInterval": 60, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
{"type": "http", "name": "Search", "url": "https://search.levkin.ca", "interval": 120, "retryInterval": 60, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
{"type": "http", "name": "PDF", "url": "https://pdf.levkin.ca", "interval": 120, "retryInterval": 60, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
{"type": "http", "name": "Umami script", "url": "https://stats.levkin.ca/script.js", "interval": 300, "retryInterval": 120, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
{"type": "http", "name": "Mattermost", "url": "https://slack.levkin.ca", "interval": 120, "retryInterval": 60, "maxretries": 3, "accepted_statuscodes": ["200-299"]},
]
url = os.environ["KUMA_URL"]
user = os.environ["KUMA_USER"]
password = os.environ["KUMA_PASSWORD"]
with UptimeKumaApi(url) as api:
api.login(user, password)
existing = {m.get("name"): m for m in api.get_monitors()}
notifs = [n for n in api.get_notifications() if n.get("isActive")]
smtp = next((n for n in notifs if n.get("isActive")), None)
if not smtp and notifs:
smtp = notifs[0]
if not smtp:
smtp = {"id": 1} # fallback: first notification in DB
for spec in MONITORS:
name = spec["name"]
if name in existing:
print(f"skip (exists): {name} id={existing[name].get('id')}")
continue
result = api.add_monitor(**spec)
print(f"added: {name} -> {result}")
existing[name] = result if isinstance(result, dict) else {"id": result}
if smtp:
nid = smtp["id"]
for m in api.get_monitors():
nlist = m.get("notificationIDList") or {}
if isinstance(nlist, dict) and nlist.get(str(nid)):
continue
if isinstance(nlist, dict):
nlist[str(nid)] = True
else:
nlist = {str(nid): True}
api.edit_monitor(m["id"], notificationIDList=nlist)
print(f"linked notification {nid} -> {m.get('name')}")
else:
print("warn: no SMTP notification found — create one in Kuma UI first", file=sys.stderr)
PY