n8n Nedir: Açık Kaynak İş Akışı Otomasyonuna Giriş

Bir noktada her sistem yöneticisi şu soruyla yüzleşiyor: “Bu tekrar eden işleri neden hala elle yapıyorum?” Sunucu metrikleri topla, Slack’e bildir, ticket aç, rapor gönder… Her gün aynı döngü. Zapier’e bakıyorsun, fiyatı görünce geri çekiliyorsun. Make (eski adıyla Integromat) deniyorsun, yine ücretli duvar. Sonra n8n ile tanışıyorsun ve “nerede idim bu zamana kadar?” diyorsun.

n8n, açık kaynaklı, self-hosted olarak çalışabilen bir iş akışı otomasyon platformu. Görsel bir arayüzle node’ları birbirine bağlayarak karmaşık otomasyon senaryoları kurabiliyorsun. Ve en önemlisi: kendi sunucunda çalıştırıyorsun, verilerini kimseye vermiyor, lisans için kredi kartı numarası girmiyorsun.

n8n Neden Öne Çıkıyor

Piyasada onlarca otomasyon aracı var. Ama sysadmin perspektifinden bakınca n8n’i ayırt eden birkaç kritik özellik var.

Self-hosted olması belki de en büyük avantaj. Şirket verilerinin üçüncü parti SaaS platformlarından geçmemesi, özellikle bankacılık, sağlık veya kamu sektöründe çalışıyorsan hayati önem taşıyor. Kendi altyapında çalıştırıyorsun, kendi kurallarına göre yönetiyorsun.

Fair-code lisansı ilginç bir yerde duruyor. Kaynak kodu açık, değiştirebiliyorsun, kendi ihtiyaçlarına göre fork edebiliyorsun. Ancak n8n’i başkalarına SaaS olarak satmak istiyorsan lisans gerekiyor. Kendi iç kullanımın için tamamen ücretsiz.

JavaScript/Node.js tabanlı olması sysadmin’ler için büyük kolaylık. Her node içinde doğrudan JavaScript yazabiliyorsun. API’dan gelen veriyi manipüle etmek, koşullu mantık kurmak, custom fonksiyonlar yazmak için ayrı bir script dosyası açmana gerek yok.

400’den fazla entegrasyon mevcut. Slack, PagerDuty, Jira, GitHub, GitLab, AWS, GCP, Azure, Grafana, Prometheus… Aklına gelen hemen hemen her servis için hazır node var. Olmayan şeyler için HTTP Request node’u ile kendin yapabiliyorsun.

Kurulum: Docker ile 10 Dakikada Hazır

Teoriden pratiğe geçelim. En temiz kurulum yöntemi Docker Compose ile.

mkdir n8n-setup && cd n8n-setup

Aşağıdaki docker-compose.yml dosyasını oluştur:

cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=guclu_sifre_buraya
      - N8N_HOST=n8n.sirketim.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.sirketim.com/
      - GENERIC_TIMEZONE=Europe/Istanbul
      - TZ=Europe/Istanbul
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=postgres_sifre
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

  postgres:
    image: postgres:15-alpine
    container_name: n8n_postgres
    restart: unless-stopped
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=postgres_sifre
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  n8n_data:
  postgres_data:
EOF

Varsayılan SQLite yerine PostgreSQL kullanmak önemli. Production ortamda SQLite file corruption sorunları yaşayabiliyorsun, özellikle yoğun workflow’larda. PostgreSQL ile bu riski ortadan kaldırıyorsun.

docker-compose up -d
docker-compose logs -f n8n

Birkaç dakika sonra http://sunucu-ip:5678 adresinden arayüze erişebilirsin. Nginx reverse proxy ile HTTPS eklemek istersen:

cat > /etc/nginx/sites-available/n8n << 'EOF'
server {
    listen 443 ssl http2;
    server_name n8n.sirketim.com;

    ssl_certificate /etc/letsencrypt/live/n8n.sirketim.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.sirketim.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 86400;
    }
}
EOF

ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

proxy_read_timeout 86400 satırı önemli. Uzun süren workflow’larda bağlantının kesilmemesi için timeout’u yüksek tutuyorsun.

Temel Kavramlar: Workflow, Node, Credential

Arayüzü ilk açtığında biraz overwhelmed hissedebilirsin. Birkaç temel kavramı oturtunca her şey yerine oturuyor.

Workflow en üst seviye yapı. Bir otomasyon senaryosu = bir workflow. “Sunucu alarmı gelince Slack’e yaz” ayrı bir workflow, “Her gece DB backup al” ayrı bir workflow.

Node workflow içindeki her bir adım. Bir HTTP isteği yapan node, bir veriyi dönüştüren node, bir email gönderen node… Node’lar birbirine bağlanıyor ve veri soldan sağa akıyor.

Trigger Node workflow’u başlatan özel node. Zamanlama (Cron), webhook, email gelince, dosya değişince gibi tetikleyiciler var.

Credential API key, şifre, token gibi hassas bilgiler için güvenli depolama. Node’lara doğrudan credential ID referansı veriyorsun, plain text şifre yazmıyorsun.

Expression node konfigürasyonlarında dinamik değer kullanmak için. {{ $json.hostname }} gibi syntax ile önceki node’dan gelen veriyi mevcut node’a taşıyabiliyorsun.

İlk Gerçek Dünya Senaryosu: Disk Dolunca Slack Bildirimi

Klasik sysadmin problemi. Bir sunucuda disk yüzde doksanı geçince Slack’e mesaj gönderelim.

Bu senaryoda üç node kullanıyoruz:

  • Schedule Trigger: Her 5 dakikada bir çalış
  • HTTP Request: Prometheus’tan disk metriklerini çek
  • IF: Eşik değeri aş mı?
  • Slack: Bildirim gönder

Prometheus sorgusu için HTTP Request node’unda URL şöyle olacak:

# Prometheus API endpoint - bu URL'yi n8n HTTP Request node'una giriyorsun
http://prometheus:9090/api/v1/query?query=100-(node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"}/node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"}*100)

IF node’unda koşul: {{ $json.data.result[0].value[1] }} değeri 90‘dan büyükse Slack node’u tetikle.

Slack mesaj template’i:

# Slack node mesaj içeriği (n8n expression syntax)
:warning: *Disk Uyarısı*
Sunucu: {{ $json.data.result[0].metric.instance }}
Kullanım: %{{ Math.round($json.data.result[0].value[1]) }}
Zaman: {{ new Date().toLocaleString('tr-TR', {timeZone: 'Europe/Istanbul'}) }}

Bu kadar. Kodlamadan, cronjob’dan, bash script’ten bağımsız bir alarm sistemi. Üstelik Slack credential’ı merkezi olarak yönetiyorsun, script’lerin içine gömmüyorsun.

Function Node ile Veri Manipülasyonu

n8n’in en güçlü özelliklerinden biri Function node’u. Doğrudan JavaScript yazabiliyorsun ve önceki node’dan gelen veriyi istediğin gibi şekillendirebiliyorsun.

Örnek senaryo: Bir API’dan sunucu listesi geliyor, her sunucu için ayrı item oluşturmak istiyorsun (split/flatten işlemi).

# Function node içine bu JavaScript kodunu yazıyorsun
const items = [];

for (const server of $input.first().json.servers) {
  items.push({
    json: {
      hostname: server.hostname,
      ip: server.ip_address,
      environment: server.tags.env || 'unknown',
      os: server.os_version,
      lastSeen: new Date(server.last_check * 1000).toISOString(),
      isStale: (Date.now() / 1000 - server.last_check) > 3600
    }
  });
}

return items;

Bu kod çalıştıktan sonra her sunucu için ayrı bir item oluşuyor ve downstream node’lar her item için ayrı ayrı çalışıyor. Split/iterate mantığını anlamak başlangıçta biraz zaman alıyor ama kavrayınca çok güçlü bir yapı.

Webhook ile Gerçek Zamanlı Entegrasyon

Zamanlama bazlı workflow’ların yanı sıra webhook ile event-driven otomasyon kurabiliyorsun. Bir örnek: GitLab’dan gelen pipeline failure event’ını işleyip Jira’da otomatik ticket açalım.

GitLab’da webhook URL’si olarak n8n’deki Webhook node URL’sini giriyorsun:

# n8n otomatik bu formatta URL üretiyor
https://n8n.sirketim.com/webhook/gitlab-pipeline-failure

Webhook node’una gelen payload’ı Function node’da işliyorsun:

# Function node - GitLab webhook payload'ından Jira ticket verisi hazırla
const payload = $input.first().json;

// Sadece failed pipeline'ları işle
if (payload.object_attributes?.status !== 'failed') {
  return [];  // Boş return = downstream node'lar çalışmaz
}

return [{
  json: {
    summary: `Pipeline Failure: ${payload.project.name} - ${payload.object_attributes.ref}`,
    description: `**Pipeline:** ${payload.object_attributes.id}n**Branch:** ${payload.object_attributes.ref}n**Commit:** ${payload.commit?.title}n**Yazar:** ${payload.user?.name}n**URL:** ${payload.object_attributes.url}`,
    project: 'OPS',
    issueType: 'Bug',
    priority: payload.object_attributes.ref === 'main' ? 'High' : 'Medium',
    labels: ['pipeline-failure', 'automated']
  }
}];

Sonrasında Jira node’unu bağlıyorsun, credential’ı seçiyorsun ve alan eşleştirmelerini {{ $json.summary }} gibi expression’larla yapıyorsun. Jira ticket’ı otomatik açılıyor.

Hata Yönetimi ve Retry Mekanizması

Production’da workflow çalıştırıyorsan hata yönetimi şart. n8n’de birkaç farklı yaklaşım var.

Her workflow için “Error Workflow” tanımlayabiliyorsun. Herhangi bir node hata verdiğinde bu ayrı workflow tetikleniyor ve hata detaylarını sana iletebiliyor.

# Error Workflow'daki Function node - hata bilgisini formatla
const error = $input.first().json;

return [{
  json: {
    workflow: error.workflow.name,
    node: error.node.name,
    errorMessage: error.execution.error.message,
    errorStack: error.execution.error.stack?.split('n').slice(0, 5).join('n'),
    executionId: error.execution.id,
    timestamp: new Date().toISOString(),
    url: `https://n8n.sirketim.com/execution/${error.execution.id}`
  }
}];

Bu output’u Slack’e veya PagerDuty’e gönderiyorsun. Workflow hata verdiğinde anında haberdar oluyorsun.

Node seviyesinde retry ayarı da var. HTTP Request gibi network işlemleri için node’un settings’inde “Retry On Fail” aktif edip kaç kez ve ne kadar aralıkla denensin diyebiliyorsun. Geçici network hatalarında workflow’un tamamen çökmesini önlüyor.

n8n CLI ile Workflow Yönetimi

Büyük bir ortamda onlarca workflow olduğunda arayüz üzerinden yönetmek zahmetleşiyor. n8n CLI burada devreye giriyor.

# Container içinde n8n CLI kullanımı
docker exec -it n8n n8n --help

# Tüm workflow'ları listele
docker exec -it n8n n8n list:workflow

# Belirli bir workflow'u dışa aktar (backup amaçlı)
docker exec -it n8n n8n export:workflow --id=5 --output=/home/node/.n8n/exports/

# Tüm workflow'ları export et (JSON formatında)
docker exec -it n8n n8n export:workflow --all --output=/home/node/.n8n/exports/

# Workflow'u import et
docker exec -it n8n n8n import:workflow --input=/home/node/.n8n/exports/workflow-5.json

Workflow’ları Git’te versiyonlamak için basit bir cron scripti:

#!/bin/bash
# /opt/scripts/n8n-backup.sh

BACKUP_DIR="/opt/n8n-backups"
GIT_REPO="/opt/n8n-workflows-git"
DATE=$(date +%Y%m%d_%H%M%S)

# Workflow'ları export et
docker exec n8n n8n export:workflow --all --output=/home/node/.n8n/exports/

# Container'dan host'a kopyala
docker cp n8n:/home/node/.n8n/exports/ $BACKUP_DIR/

# Git repo'ya kopyala ve commit et
cp $BACKUP_DIR/exports/*.json $GIT_REPO/workflows/
cd $GIT_REPO
git add .
git diff --staged --quiet || git commit -m "n8n workflow backup - $DATE"
git push origin main 2>/dev/null || true

echo "[$DATE] Backup tamamlandi"

Bu scripti crontab’a ekleyince workflow değişikliklerini Git history’de takip edebiliyorsun. Bir şeyleri bozarsan git diff ile neyin değiştiğini görüyorsun.

Performans ve Ölçekleme Notları

Başlangıç için tek node kurulum yeterli ama workflow sayısı ve karmaşıklığı arttıkça bazı şeylere dikkat etmek gerekiyor.

Execution history temizliği kritik. n8n her workflow çalışmasının kaydını tutuyor. Aylar sonra bu tablo devasa boyuta ulaşabiliyor. PostgreSQL’de şu sorguyu çalıştırarak kontrol edebilirsin:

# n8n PostgreSQL container'ında execution sayısını kontrol et
docker exec -it n8n_postgres psql -U n8n -d n8n -c 
  "SELECT COUNT(*) as toplam, 
          MIN(started_at) as en_eski, 
          MAX(started_at) as en_yeni 
   FROM execution_entity;"

n8n’in EXECUTIONS_DATA_MAX_AGE ve EXECUTIONS_DATA_PRUNE environment variable’larını set etmeyi unutma:

# docker-compose.yml environment kısmına ekle
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168   # saat cinsinden, bu 7 gun
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000

Queue mode çok yoğun ortamlar için. Redis ile birlikte worker’ları scale edebiliyorsun ama bu ayrı bir yazı konusu.

Memory ayarı da önemli. Node.js varsayılan olarak 512MB ile başlıyor, büyük veri işleyen workflow’larda bu yetersiz kalabiliyor:

# docker-compose.yml environment kısmına ekle
- NODE_OPTIONS=--max-old-space-size=2048

Güvenlik: Dikkat Edilmesi Gerekenler

n8n’i internet’e açıyorsan bazı temel önlemleri es geçme.

Basic auth yerine n8n’in kendi authentication sistemini kullan ve güçlü şifreler belirle. Eğer kurumsal ortamdaysan LDAP veya SAML entegrasyonuna bak (Enterprise özellik ama self-hosted için makul fiyatlı).

Webhook URL’leri herkese açık olabiliyor. Bu URL’lere authentication eklemek için Header Auth veya Query Param Auth kullanabiliyorsun. GitLab, GitHub gibi servislerin webhook imzası doğrulama özelliklerini de Function node içinde implemente etmeyi düşün.

# GitLab webhook imzası doğrulama - Function node
const crypto = require('crypto');

const payload = $input.first().json;
const signature = $input.first().headers['x-gitlab-token'];
const secret = 'senin-webhook-secret-key';

if (signature !== secret) {
  throw new Error('Gecersiz webhook imzasi - yetkisiz istek');
}

return $input.all();

n8n container’ının network erişimini de kısıtlamayı düşün. Internal servislere erişmesi gerekiyorsa internal network’e, dış internet’e çıkması gerekiyorsa outbound firewall kurallarını ihtiyaç bazlı ayarla.

Sonuç

n8n, sysadmin ve DevOps mühendisleri için ciddi bir zaman kazandırıcı. İlk kurulum birkaç saatini alabilir, ilk birkaç workflow’u yaparken öğrenme eğrisi var, ama bundan sonrası hızlanıyor.

Benim önerim: Küçük bir problemle başla. “Her sabah sunucu durumunu Slack’e yazan bir workflow” gibi. Bunu kurunca platform’u anlamaya başlıyorsun ve giderek daha karmaşık senaryolara geçebiliyorsun.

n8n’in en büyük katkısı teknik olmayan ekip arkadaşlarının da workflow oluşturabilmesi ya da en azından mevcut workflow’ları takip edebilmesi. “Bu alarm neden geldi?” sorusunu artık onlara n8n’de gösterebiliyorsun, bash script içindeki regex’i açıklamana gerek kalmıyor.

Self-hosted, açık kaynak, JavaScript tabanlı, 400+ entegrasyon. Production kullanım için PostgreSQL, Nginx ve düzgün bir backup stratejisi ile kurarsan, uzun vadede çok değerli bir araç olduğunu göreceksin.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir