kertenkerem_
· DevOps · 5 dk okuma

SaaS Maliyetlerinden Kurtulun: Uptime Kuma ve n8n ile Ücretsiz Monitoring Stack Kurulumu

Datadog, New Relic ya da BetterStack faturalarının her ay sonunda FinOps ekiplerinin masasında yarattığı kalp çarpıntısını hepimiz biliyoruz. Özellikle yüzlerce microservice ya da edge endpoint barındıran altyapılarda, basit bir synthetic check ve alerting mekanizması için ödenen lisans bedelleri katlanılmaz seviyelere çıkabiliyor. Bu noktada self-hosted bir monitoring altyapısı kurmak doğrudan bir maliyet kararına dönüşüyor. Bu yazıda Uptime Kuma ve n8n ikilisini bir araya getirerek kurumsal ölçekte esnek ve tamamen ücretsiz bir observability & auto-remediation stack’ini nasıl ayağa kaldıracağımızı anlatıyorum.

Neden bu stack? Mimari kararlar

Piyasada Prometheus + Alertmanager ya da Zabbix gibi büyük çözümler varken neden Uptime Kuma ve n8n? Cevap bakım maliyeti (operational overhead) ve olay müdahale hızı (MTTR).

Prometheus Blackbox Exporter güçlüdür ama konfigürasyonu hantaldır; dashboard ve status page için de Grafana şarttır. Uptime Kuma ise tek bir container içinde HTTP(s), gRPC, TCP, DNS, Ping ve Docker container healthcheck özelliklerini native bir Status Page ile sunar. n8n, Alertmanager’ın kısıtlı webhook yapısının ötesine geçip alert deduplication, payload zenginleştirme (enrichment) ve hatta SSH/Kubernetes API üzerinden otomatik iyileştirme (self-healing) workflow’ları çalıştırmamıza izin verir.

Adım 1: production-ready Docker Compose mimarisi

Stack’imizi tek bir node üzerinde, izole bir Docker network’ü, persistent storage ve resource limitleriyle ayağa kaldıralım. SSL’i Traefik veya Nginx gibi bir reverse proxy’nin arkasında sonlandırdığınızı varsayıyoruz, bu yüzden internal network üzerinden güvenli bağlantı kuracağız.

version: '3.8'

networks:
  monitoring-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

volumes:
  uptime-kuma-data:
    driver: local
  n8n-data:
    driver: local

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1.23.13-debian
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - uptime-kuma-data:/app/data
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - monitoring-net
    ports:
      - "127.0.0.1:3001:3001"
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1024M
        reservations:
          cpus: '0.2'
          memory: 256M
    healthcheck:
      test: ["CMD-SHELL", "node extra/healthcheck.js"]
      interval: 30s
      timeout: 10s
      retries: 3

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    container_name: n8n-automation
    restart: unless-stopped
    environment:
      - N8N_HOST=n8n.internal.local
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - GENERIC_TIMEZONE=Europe/Istanbul
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
    volumes:
      - n8n-data:/home/node/.n8n
    networks:
      - monitoring-net
    ports:
      - "127.0.0.1:5678:5678"
    deploy:
      resources:
        limits:
          cpus: '1.5'
          memory: 2048M
        reservations:
          cpus: '0.2'
          memory: 512M

Burada kritik iki parametre var. Uptime Kuma’ya Docker socket’i ro (read-only) bağlayarak yerel container state’lerini doğrudan izleyebiliyoruz. n8n tarafında ise EXECUTIONS_DATA_PRUNE=true ile SQLite veritabanının kontrolsüz büyümesini engelliyor, disk I/O darboğazlarının önüne geçiyoruz.

Servisleri ayağa kaldıralım:

docker compose up -d
docker compose ps

Adım 2: Uptime Kuma konfigürasyonu ve probing stratejisi

Uptime Kuma arayüzüne (http://localhost:3001) eriştikten sonra ilk işimiz probe stratejisini kurgulamak. Yalnızca HTTP 200 OK kontrolü production seviyesinde yetersizdir.

1. HTTP Keyword Check & payload validasyonu

Endpoint 200 dönüyor olabilir, ama arka planda database connection pool tükenmiş ve boş bir JSON array render ediyor olabilir. Monitor tipini HTTP(s) - Keyword seçerek response body içinde beklenen bir string (örneğin "status":"healthy") aratmalısınız.

2. Dynamic certificate monitoring

TLS sertifikalarının bitişine 14 gün kala alert tetiklemek için TLS/SSL probe ayarlarını etkinleştirin. Let’s Encrypt botlarının cert-manager veya ACME renewal hatalarında bu ayar işinizi görür.

3. Webhook entegrasyonu (n8n köprüsü)

Settings > Notifications > Setup Notification adımlarını izleyin:

  • Notification Type: Webhook
  • Post URL: https://n8n.yourdomain.com/webhook/uptime-kuma-alerts
  • Request Method: POST
  • Content-Type: application/json

Uptime Kuma olay anında n8n’e şuna benzer, ayrıntılı bir payload gönderir:

{
  "heartbeat": {
    "monitorID": 4,
    "status": 0,
    "time": "2024-03-24 14:32:10.123",
    "msg": "HTTP 502 Bad Gateway",
    "ping": 142
  },
  "monitor": {
    "name": "Auth-Service-Prod",
    "url": "https://auth.internal.domain/healthz",
    "type": "http",
    "tags": [{"name": "tier-1"}, {"name": "team-core"}]
  },
  "msg": "[Auth-Service-Prod] is Down: HTTP 502 Bad Gateway"
}

Adım 3: n8n ile event-driven remediation ve alert routing

Basit bir bildirim göndermek yerine n8n üzerinde bir incident management iş akışı kuralım. Senaryomuz şu: Servis düştüğünde alert’i Slack/Telegram kanalına at, ardından servisi kurtarmak için SSH üzerinden staging/prod ortamına safe-restart komutu gönder.

1. Webhook trigger ve status filtreleme

n8n üzerinde bir Webhook Node oluşturup path’i uptime-kuma-alerts yapın. Ardından gelen veriyi kontrol eden bir Switch Node ekleyin:

  • {{ $json.heartbeat.status }} === 0 -> Incident (DOWN)
  • {{ $json.heartbeat.status }} === 1 -> Recovery (UP)

2. Payload enrichment (Code Node)

Alert metnini güzelleştirmek ve etiketlere göre on-call mühendisi etiketlemek için araya bir Code (JavaScript) node koyuyoruz:

const monitor = $input.first().json.monitor;
const heartbeat = $input.first().json.heartbeat;

const isTier1 = monitor.tags && monitor.tags.some(t => t.name === 'tier-1');
const severity = heartbeat.status === 0 ? (isTier1 ? 'CRITICAL' : 'WARNING') : 'INFO';
const mention = isTier1 ? '@oncall-dev' : '';

return {
  json: {
    serviceName: monitor.name,
    targetUrl: monitor.url,
    errorMessage: heartbeat.msg,
    timestamp: heartbeat.time,
    severity: severity,
    mentionTarget: mention,
    rawPayload: $input.first().json
  }
};

3. Auto-remediation: safe container restart

Düşen servis stateless bir worker ya da memory leak yaşayan bir microservice ise, gece 03:00’te nöbetçiyi uyandırmadan önce kontrollü bir restart denemek mantıklıdır.

n8n’deki SSH Node’u kullanarak ilgili host üzerinde minimum yetkili bir service user ile remote command çalıştırıyoruz:

# n8n SSH Execution Node Komutu
docker restart {{ $json.serviceName.toLowerCase() }} || systemctl restart {{ $json.serviceName.toLowerCase() }}

Bu adımdan sonra n8n’e bir Wait Node (60 saniye) koyup Uptime Kuma API’sine ya da doğrudan servise probe atarak sorunun çözülüp çözülmediğini teyit edebilirsiniz. Düzelmediyse escalasyon yaparak PagerDuty/Opsgenie veya Telegram sesli arama botunu tetikleyebilirsiniz.

Production hardening: monitoring altyapısını kim izleyecek?

Monitoring sisteminin kendisi çökerse ne olur? Single point of failure (SPOF) riskini ortadan kaldırmak için iki kritik adımı atlamayın.

1. Dead Man’s Snitch (heartbeat monitoring)

Uptime Kuma içinde Push tipi bir monitor oluşturun. n8n üzerinden her 5 dakikada bir bu endpoint’e curl atan bir Cron Workflow tanımlayın. n8n ya da network giderse Uptime Kuma alarm üretir. Aynı şekilde harici, tamamen ücretsiz bir dış servise (örn. Cronitor veya Healthchecks.io) Uptime Kuma’nın kendisinden periyodik ping atın.

# n8n cron node içinden dış heartbeat servisine ping
curl -m 10 --retry 3 https://hc-ping.com/your-uuid-token

2. SQLite WAL modu ve otomatik backup

Uptime Kuma varsayılan olarak SQLite kullanır. Yoğun monitor sayısında (500+) database lock yaşamamak için SQLite WAL (Write-Ahead Logging) modunun etkin olduğundan emin olun:

# Uptime Kuma data dizininde
sqlite3 kuma.db "PRAGMA journal_mode=WAL;"

Veritabanı yedeğini her gece S3 uyumlu bir object storage’a rclone ya da restic ile şifreli olarak senkronize edin:

docker exec uptime-kuma sqlite3 /app/data/kuma.db ".backup '/app/data/kuma-backup.db'"
rclone copy /var/lib/docker/volumes/uptime-kuma-data/_data/kuma-backup.db remote-s3:monitoring-backups/

Özet ve maliyet karşılaştırması

Bu mimariyi Hetzner veya DigitalOcean üzerindeki 4-5 USD’lik bir VPS’te rahatlıkla çalıştırabilirsiniz. Ticari bir SaaS çözümünde 200 endpoint, multi-step healthcheck’ler ve custom webhook otomasyonları için ayda 150-400 USD arasında fatura ödemeniz gerekirken, bu stack ile tüm verinizi kendi altyapınızda tutuyor, n8n’in geniş ekosistemi sayesinde sınırsız auto-remediation senaryosu üretebiliyorsunuz.