|
|
@@ -5,6 +5,7 @@ import sys
|
|
|
import logging
|
|
|
import time
|
|
|
import tempfile
|
|
|
+import threading
|
|
|
from flask import Flask, jsonify, request
|
|
|
from werkzeug.security import check_password_hash
|
|
|
from werkzeug.serving import WSGIRequestHandler
|
|
|
@@ -61,6 +62,36 @@ app = Flask(__name__)
|
|
|
# Global config instance - initialized during main execution
|
|
|
config = None
|
|
|
|
|
|
+# Systemd watchdog support
|
|
|
+def setup_systemd_watchdog():
|
|
|
+ """Setup systemd watchdog notifications"""
|
|
|
+ try:
|
|
|
+ import systemd.daemon
|
|
|
+ watchdog_usec = systemd.daemon.watchdog_enabled()
|
|
|
+ if watchdog_usec:
|
|
|
+ # Convert microseconds to seconds and send notifications at half the interval
|
|
|
+ interval = (watchdog_usec / 1000000) / 2
|
|
|
+ logger.info(f"Systemd watchdog enabled, sending notifications every {interval:.1f}s")
|
|
|
+
|
|
|
+ def watchdog_ping():
|
|
|
+ while True:
|
|
|
+ try:
|
|
|
+ systemd.daemon.notify("WATCHDOG=1")
|
|
|
+ time.sleep(interval)
|
|
|
+ except Exception as e:
|
|
|
+ logger.warning(f"Failed to send watchdog notification: {e}")
|
|
|
+ time.sleep(interval)
|
|
|
+
|
|
|
+ # Start watchdog thread
|
|
|
+ watchdog_thread = threading.Thread(target=watchdog_ping, daemon=True)
|
|
|
+ watchdog_thread.start()
|
|
|
+ return True
|
|
|
+ except ImportError:
|
|
|
+ logger.warning("systemd python package not available, watchdog disabled")
|
|
|
+ except Exception as e:
|
|
|
+ logger.warning(f"Failed to setup systemd watchdog: {e}")
|
|
|
+ return False
|
|
|
+
|
|
|
def require_auth(key_config=None, is_health=False):
|
|
|
"""Decorator for HTTP Basic Authentication"""
|
|
|
def decorator(f):
|
|
|
@@ -133,7 +164,6 @@ def send_ntfy_notification(backends: List[str], message: str, title: str = None)
|
|
|
ntfy_config["backends"] = [backend]
|
|
|
|
|
|
# Add timeout to prevent hanging using threading
|
|
|
- import threading
|
|
|
|
|
|
result = [None]
|
|
|
exception = [None]
|
|
|
@@ -508,9 +538,23 @@ def main():
|
|
|
# Add health check route
|
|
|
app.add_url_rule(config.health_route, 'health_check', health_check, methods=['GET'])
|
|
|
|
|
|
+ # Setup systemd watchdog
|
|
|
+ watchdog_enabled = setup_systemd_watchdog()
|
|
|
+
|
|
|
logger.info(f"Starting emergency access server on {config.server_host}:{config.server_port}")
|
|
|
logger.info(f"Health route: {config.health_route}")
|
|
|
logger.info(f"Configured {len(config.keys)} key(s)")
|
|
|
+ logger.info(f"Systemd watchdog: {'enabled' if watchdog_enabled else 'disabled'}")
|
|
|
+
|
|
|
+ # Notify systemd that we're ready
|
|
|
+ try:
|
|
|
+ import systemd.daemon
|
|
|
+ systemd.daemon.notify("READY=1")
|
|
|
+ logger.info("Sent READY=1 to systemd")
|
|
|
+ except ImportError:
|
|
|
+ pass
|
|
|
+ except Exception as e:
|
|
|
+ logger.warning(f"Failed to notify systemd ready: {e}")
|
|
|
|
|
|
# Use production-ready server with better error handling
|
|
|
try:
|