Post-Tyranny-Tech-Infrastru.../ansible/roles/kuma/templates/register_monitors.py.j2
Pieter 13685eb454 feat: Add infrastructure roles for multi-tenant architecture
Add new Ansible roles and configuration for the edge proxy and
private network architecture:

## New Roles:
- **edge-traefik**: Edge reverse proxy that routes to private clients
  - Dynamic routing configuration for multiple clients
  - SSL termination at the edge
  - Routes traffic to private IPs (10.0.0.x)

- **nat-gateway**: NAT/gateway configuration for edge server
  - IP forwarding and masquerading
  - Allows private network clients to access internet
  - iptables rules for Docker integration

- **diun**: Docker Image Update Notifier
  - Monitors containers for available updates
  - Email notifications via Mailgun
  - Per-client configuration

- **kuma**: Uptime monitoring integration
  - Registers HTTP monitors for client services
  - Automated monitor creation via API
  - Checks Authentik, Nextcloud, Collabora endpoints

## New Playbooks:
- **setup-edge.yml**: Configure edge server with proxy and NAT

## Configuration:
- **host_vars**: Per-client Ansible configuration (valk, white)
  - SSH bastion configuration for private IPs
  - Client-specific secrets file references

This enables the scalable multi-tenant architecture where:
- Edge server has public IP and routes traffic
- Client servers use private IPs only (cost savings)
- All traffic flows through edge proxy with SSL termination

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 19:05:51 +01:00

128 lines
4.6 KiB
Django/Jinja
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Uptime Kuma Monitor Registration Script
Auto-generated for client: {{ client_name }}
"""
import sys
from uptime_kuma_api import UptimeKumaApi, MonitorType
# Configuration
KUMA_URL = "{{ kuma_url }}"
KUMA_USERNAME = "{{ kuma_username | default('') }}"
KUMA_PASSWORD = "{{ kuma_password | default('') }}"
CLIENT_NAME = "{{ client_name }}"
CLIENT_DOMAIN = "{{ client_domain }}"
# Monitor definitions
MONITORS = {{ kuma_monitors | to_json }}
# Monitor type mapping
TYPE_MAP = {
"http": MonitorType.HTTP,
"https": MonitorType.HTTP,
"ping": MonitorType.PING,
"tcp": MonitorType.PORT,
"dns": MonitorType.DNS,
}
def main():
"""Register monitors with Uptime Kuma"""
# Check if credentials are provided
if not KUMA_USERNAME or not KUMA_PASSWORD:
print("⚠️ Kuma registration skipped: No credentials provided")
print("")
print("To enable automated monitor registration, add to your secrets:")
print(" kuma_username: your_username")
print(" kuma_password: your_password")
print("")
print("Note: API keys (uk1_*) are only for REST endpoints, not monitor management")
print("Manual registration required at: https://status.vrije.cloud")
sys.exit(0) # Exit with success (not a failure, just skipped)
try:
# Connect to Uptime Kuma (Socket.io connection)
print(f"🔌 Connecting to Uptime Kuma at {KUMA_URL}...")
api = UptimeKumaApi(KUMA_URL)
# Login with username/password
print(f"🔐 Authenticating as {KUMA_USERNAME}...")
api.login(KUMA_USERNAME, KUMA_PASSWORD)
# Get existing monitors
print("📋 Fetching existing monitors...")
existing_monitors = api.get_monitors()
existing_names = {m['name']: m['id'] for m in existing_monitors}
# Register each monitor
added_count = 0
updated_count = 0
skipped_count = 0
for monitor_config in MONITORS:
monitor_name = monitor_config['name']
monitor_type_str = monitor_config.get('type', 'http').lower()
monitor_type = TYPE_MAP.get(monitor_type_str, MonitorType.HTTP)
# Build monitor parameters
params = {
'type': monitor_type,
'name': monitor_name,
'interval': monitor_config.get('interval', 60),
'maxretries': monitor_config.get('maxretries', 3),
'retryInterval': monitor_config.get('retry_interval', 60),
}
# Add type-specific parameters
if monitor_type == MonitorType.HTTP:
params['url'] = monitor_config['url']
params['method'] = monitor_config.get('method', 'GET')
if 'expected_status' in monitor_config:
params['accepted_statuscodes'] = monitor_config['expected_status'].split(',')
elif monitor_type == MonitorType.PING:
params['hostname'] = monitor_config.get('hostname', monitor_config.get('url', ''))
# Check if monitor already exists
if monitor_name in existing_names:
print(f"⚠️ Monitor '{monitor_name}' already exists (ID: {existing_monitors[monitor_name]})")
print(f" Skipping (update not implemented)")
skipped_count += 1
else:
print(f" Adding monitor: {monitor_name}")
try:
result = api.add_monitor(**params)
print(f" ✓ Added (ID: {result.get('monitorID', 'unknown')})")
added_count += 1
except Exception as e:
print(f" ✗ Failed: {e}")
# Disconnect
api.disconnect()
# Summary
print("")
print("=" * 60)
print(f"📊 Registration Summary for {CLIENT_NAME}:")
print(f" Added: {added_count}")
print(f" Skipped (already exist): {skipped_count}")
print(f" Total monitors: {len(MONITORS)}")
print("=" * 60)
if added_count > 0:
print(f"✅ Successfully registered {added_count} new monitor(s)")
except Exception as e:
print(f"❌ ERROR: Failed to register monitors: {e}")
print("")
print("Troubleshooting:")
print(f" 1. Verify Kuma is accessible: {KUMA_URL}")
print(" 2. Check username/password are correct")
print(" 3. Ensure uptime-kuma-api Python package is installed")
print(" 4. Check network connectivity from deployment machine")
sys.exit(1)
if __name__ == "__main__":
main()