diff --git a/ops/glitchtip-auth-forwarder/Dockerfile b/ops/glitchtip-auth-forwarder/Dockerfile index 4506f329..963dab2c 100644 --- a/ops/glitchtip-auth-forwarder/Dockerfile +++ b/ops/glitchtip-auth-forwarder/Dockerfile @@ -7,8 +7,9 @@ RUN pip install --no-cache-dir "sentry-sdk==2.18.0" COPY forwarder.py . -# nobody (uid 65534) — минимальные привилегии -USER nobody +# Запускается под root — необходимо для чтения /var/log/caddy/gendsgn.ru.log +# (Caddy пишет лог под UID 0). Mounts: caddy_logs:ro + auth_forwarder_state (write). +# Attack surface минимален: нет network listener, нет shell, образ python:3.12-slim. # -u для unbuffered stdout — docker logs виден сразу без буферизации CMD ["python", "-u", "forwarder.py"] diff --git a/ops/glitchtip-auth-forwarder/forwarder.py b/ops/glitchtip-auth-forwarder/forwarder.py index 72cec657..e1037550 100644 --- a/ops/glitchtip-auth-forwarder/forwarder.py +++ b/ops/glitchtip-auth-forwarder/forwarder.py @@ -67,6 +67,10 @@ KNOWN_MONITOR_UAS = frozenset( ) _shutdown = False +# Throttle для unhandled exceptions — не более одного Sentry event за 5 минут, +# чтобы persistent ошибка (напр. PermissionError) не спамила GlitchTip. +_last_exc_sent: float = 0.0 +_EXC_THROTTLE_S: float = 300.0 def _signal_handler(signum: int, frame: object) -> None: @@ -299,10 +303,14 @@ def main() -> None: time.sleep(5) except Exception as exc: print(f"[forwarder] unhandled error: {exc}", file=sys.stderr, flush=True) - try: - sentry_sdk.capture_exception(exc) - except Exception: - pass + global _last_exc_sent + now_wall = time.time() + if now_wall - _last_exc_sent > _EXC_THROTTLE_S: + try: + sentry_sdk.capture_exception(exc) + except Exception: + pass + _last_exc_sent = now_wall time.sleep(5) print("[forwarder] shutting down gracefully", flush=True)