n8n Docker ile Kurulum ve İlk Yapılandırma

Otomasyon dünyasına adım atmak isteyen sistem yöneticilerinin önünde onlarca araç var. Zapier var, Make var, custom script’ler var. Ama hepsinin ortak bir sorunu var: ya pahalı, ya veriyi dışarı sızdırıyor, ya da bakımı cehennem. n8n bu denklemin dışında duruyor. Self-hosted, açık kaynak, görsel arayüzü var ve Docker ile birkaç dakikada ayağa kalkıyor. Geçen ay bir müşterimizin ortamında Jira-Slack-GitLab üçgenini n8n ile otomatize ettik, hiç script yazmadan. Bu yazıda o deneyimden yola çıkarak n8n’i Docker üzerine nasıl doğru kurduğumuzu ve ilk yapılandırmada nelere dikkat etmemiz gerektiğini aktaracağım.

Neden Docker ile Kuruyoruz?

n8n’i doğrudan Node.js üzerine kurmak mümkün ama pratikte bu yöntemi önermiyorum. Bağımlılık çakışmaları, Node sürüm uyumsuzlukları, sistem güncellemelerinde kırılan kurulumlar… Bunlarla uğraşmak yerine Docker’ın izolasyonundan faydalanmak çok daha temiz bir yaklaşım.

Ayrıca Docker Compose kullanarak tüm ortamı bir dosyada tanımlayabiliyorsunuz. Yarın başka bir sunucuya taşımanız gerektiğinde ya da disaster recovery senaryosunda bu dosyayı alıp gidiyorsunuz.

Ön Gereksinimler

Başlamadan önce sunucunuzda şunların kurulu olması gerekiyor:

  • Docker Engine (20.10+)
  • Docker Compose v2
  • En az 2GB RAM (production için 4GB öneriyorum)
  • 10GB boş disk alanı

Docker ve Compose kurulu değilse hızlıca kuralım:

# Ubuntu/Debian için
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Docker Compose v2 kontrolü
docker compose version

# Kullanıcıyı docker grubuna ekle (sudo olmadan çalıştırmak için)
sudo usermod -aG docker $USER
newgrp docker

Dizin Yapısını Oluşturalım

Production ortamında her şeyi düzenli tutmak sonradan başınızı kurtarır. n8n için şöyle bir dizin yapısı oluşturuyorum:

mkdir -p /opt/n8n/{data,files,backups}
chown -R 1000:1000 /opt/n8n/data

Burada chown 1000:1000 önemli. n8n Docker image’ı içinde node kullanıcısı UID 1000 ile çalışıyor. Bunu yapmazsanız volume bağladığınızda write permission hatalarıyla karşılaşırsınız. Bunu ilk kurulumda atlayanların yarısı “n8n başlamıyor, log’da bir şey yok” diye saatlerce uğraşır.

Docker Compose Dosyasını Hazırlayalım

Basit bir tek-container kurulumla başlayıp sonra production-ready hale getireceğiz.

Temel Kurulum (SQLite ile)

# /opt/n8n/docker-compose.yml
version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=n8n.sirketiniz.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.sirketiniz.com/
      - GENERIC_TIMEZONE=Europe/Istanbul
      - TZ=Europe/Istanbul
    volumes:
      - /opt/n8n/data:/home/node/.n8n
    networks:
      - n8n-network

networks:
  n8n-network:
    driver: bridge

Bu yapılandırma SQLite kullanıyor ve küçük ekipler için yeterli. Ama eğer birden fazla kişi aynı anda çalışacaksa ya da yüksek iş akışı hacmi bekliyorsanız PostgreSQL’e geçmenizi öneririm.

Production Kurulum (PostgreSQL ile)

Gerçek dünyada çoğu zaman bu yapıyı kullanıyoruz:

# /opt/n8n/docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: n8n-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n_user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - /opt/n8n/postgres:/var/lib/postgresql/data
    networks:
      - n8n-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n_user -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${N8N_HOST}/
      - 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_user
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
    volumes:
      - /opt/n8n/data:/home/node/.n8n
      - /opt/n8n/files:/files
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - n8n-network

networks:
  n8n-network:
    driver: bridge

Dikkat ettiyseniz n8n portunu 127.0.0.1:5678:5678 olarak bind ettim. Bu önemli: n8n’i doğrudan internete açmıyoruz, önüne bir reverse proxy koyacağız. Bağlantı noktasını 0.0.0.0 ile açarsanız firewall’ı unuttuğunuzda n8n dünyaya açık kalır.

Environment Dosyası

Hassas bilgileri compose dosyasına gömmemek için .env kullanıyoruz:

# /opt/n8n/.env
POSTGRES_PASSWORD=guclu-bir-sifre-buraya
N8N_HOST=n8n.sirketiniz.com
N8N_ENCRYPTION_KEY=32-karakter-rastgele-string-buraya
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=baska-bir-guclu-sifre

N8N_ENCRYPTION_KEY için rastgele bir string üretelim:

openssl rand -hex 16

Bu key çok kritik. n8n tüm credential’larınızı (API key’ler, şifreler) bu key ile şifreleyerek veritabanında saklıyor. Key’i kaybederseniz tüm credential’larınız erişilemez hale gelir. Mutlaka yedekleyin.

Nginx Reverse Proxy Yapılandırması

n8n’i production’da kullanmak için önüne Nginx koyuyoruz. Hem SSL termination hem de ek güvenlik katmanı sağlıyor.

# /etc/nginx/sites-available/n8n
server {
    listen 80;
    server_name n8n.sirketiniz.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name n8n.sirketiniz.com;

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

    # Webhook'lar için önemli
    client_max_body_size 16m;

    location / {
        proxy_pass http://127.0.0.1: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 300s;
        proxy_connect_timeout 300s;
    }
}

proxy_read_timeout 300s değerini özellikle koydum. n8n workflow’ları bazen uzun sürebilir, özellikle AI node’ları veya büyük veri işleme adımları içeriyorsa. Varsayılan 60 saniyeyle bu işlemler timeout alır.

SSL sertifikası için Certbot:

certbot --nginx -d n8n.sirketiniz.com

Servisi Ayağa Kaldıralım

Artık her şey hazır:

cd /opt/n8n
docker compose up -d

# Logları izle
docker compose logs -f n8n

# Servis durumu
docker compose ps

Logları izlerken şunu görüyorsanız n8n başarıyla ayağa kalkmış demektir:

n8n  | Editor is now accessible via:
n8n  | https://n8n.sirketiniz.com/

İlk Giriş ve Temel Ayarlar

Tarayıcıdan https://n8n.sirketiniz.com adresine gidin. İlk girişte bir owner hesabı oluşturmanızı isteyecek. Bu hesap basic auth’tan bağımsız, n8n’in kendi kullanıcı yönetim sistemi.

İlk yapılandırmada birkaç kritik ayar var:

Settings > Personal > MFA: Eğer n8n internet üzerinden erişilebiliyorsa mutlaka aktif edin.

Settings > Community Nodes: Ekip olarak hangi community node’larının kurulabileceğini buradan yönetiyorsunuz. Her şeye izin vermek yerine ihtiyaç duyulanlara kısıtlı erişim daha güvenli.

Settings > Users: n8n 1.0 sonrasında multi-user desteği geldi. Ekip üyelerini buradan davet edebilirsiniz.

Gerçek Dünya Senaryosu: Sunucu Alert Otomasyonu

Kurulumu anlatmak bir şey, gerçekte ne işe yaradığını göstermek daha önemli. Şu senaryoyu ele alalım: Prometheus Alert Manager’dan gelen alertleri alıp Slack’e iletmek ve aynı zamanda bir Google Sheets’e loglamak istiyoruz.

n8n’de bu workflow şu node’lardan oluşur:

  • Webhook Node: Alert Manager’dan POST isteği alır
  • IF Node: Severity’e göre dallandırır (critical/warning)
  • Slack Node: İlgili kanala mesaj gönderir
  • Google Sheets Node: Alert’i log satırı olarak ekler

Bu işi bash script ile yapmaya çalışsaydınız: webhook server için ayrı bir süreç, Slack API auth, Google Sheets OAuth, error handling… Kolayca 300-400 satır kod. n8n’de bunu 20 dakikada görsel olarak çiziyorsunuz.

Webhook URL’iniz şu formatta olacak: https://n8n.sirketiniz.com/webhook/prometheus-alerts

Alert Manager yapılandırmasına eklemek için:

# alertmanager.yml içine
receivers:
  - name: 'n8n-webhook'
    webhook_configs:
      - url: 'https://n8n.sirketiniz.com/webhook/prometheus-alerts'
        send_resolved: true

Backup Stratejisi

n8n’de iki şeyi yedeklemeniz gerekiyor: veritabanı ve data dizini.

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

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

# PostgreSQL backup
docker exec n8n-postgres pg_dump -U n8n_user n8n | gzip > "${BACKUP_DIR}/n8n_db_${DATE}.sql.gz"

# Data dizini backup (workflow export'ları, credential dosyaları)
tar -czf "${BACKUP_DIR}/n8n_data_${DATE}.tar.gz" /opt/n8n/data

# 30 günden eski yedekleri sil
find "${BACKUP_DIR}" -name "*.gz" -mtime +30 -delete

echo "Backup tamamlandi: ${DATE}"

Bu script’i cron’a ekleyelim:

chmod +x /opt/n8n/backup.sh

# Her gün saat 02:00'de çalıştır
echo "0 2 * * * root /opt/n8n/backup.sh >> /var/log/n8n-backup.log 2>&1" | sudo tee /etc/cron.d/n8n-backup

Workflow’larınızı ayrıca n8n arayüzünden de export edebilirsiniz (Settings > Import/Export). JSON formatında dışa aktarılan workflow’ları git repo’suna koymayı alışkanlık haline getirin. Böylece workflow versiyonlama da olmuş olur.

Güncelleme Prosedürü

n8n hızlı gelişiyor, sürümler sık çıkıyor. Güncelleme yapmadan önce mutlaka backup alın:

cd /opt/n8n

# Backup al
./backup.sh

# Yeni image'ı çek
docker compose pull

# Servisi yeniden başlat
docker compose up -d

# Log'ları kontrol et
docker compose logs -f n8n --tail=50

Eğer büyük bir versiyon atladıysanız (örneğin 0.x’ten 1.x’e) release notes’u mutlaka okuyun. Breaking change’ler olabiliyor. Bir keresinde bir major update sonrasında bazı webhook URL’leri değişmişti, bunu fark etmeden production’a geçince birkaç integration’ı kırmıştık.

Kaynak Kullanımını İzleme

n8n zamanla büyüyebilir, özellikle çok sayıda workflow çalışıyorsa:

# Container kaynak kullanımı
docker stats n8n n8n-postgres

# n8n loglarında hata ara
docker logs n8n --since 24h 2>&1 | grep -i "error|warn" | tail -50

# Veritabanı boyutu
docker exec n8n-postgres psql -U n8n_user -d n8n -c "
SELECT
  schemaname,
  tablename,
  pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
"

Zamanla execution_entity tablosu büyür. n8n’in kendi arayüzünden Settings > Pruning bölümünde execution history tutma süresini ayarlayın. Ben genellikle başarılı execution’lar için 7 gün, başarısız olanlar için 30 gün tutuyorum.

Sık Karşılaşılan Sorunlar

Webhook’lar çalışmıyor: WEBHOOK_URL environment variable’ını yanlış set ettiyseniz webhook’lar oluşturulamıyor. Değerin trailing slash ile bitmesi önemli.

Container başlamıyor, log boş: Büyük ihtimalle volume permission sorunu. chown 1000:1000 /opt/n8n/data komutunu çalıştırın.

Credential’lar kaydedilmiyor: N8N_ENCRYPTION_KEY set edilmemişse veya sonradan değiştirildiyse bu sorunu yaşarsınız. Key’i baştan doğru set edin ve değiştirmeyin.

Memory kullanımı artıyor: Çok sayıda paralel execution veya büyük veri setleri işleyen workflow’lar buna yol açar. Compose dosyasına memory limit ekleyin:

services:
  n8n:
    # ...mevcut ayarlar...
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M

Sonuç

n8n’in Docker üzerine kurulumu teknik olarak karmaşık değil, ama production’da doğru yapmak önemli. PostgreSQL backend, düzgün volume yönetimi, reverse proxy ve backup stratejisi olmadan kurduğunuz şey bir oyuncak olarak kalır.

Burada anlattıklarımı birkaç kez farklı müşteri ortamlarında uyguladım. Doğru kurulduğunda n8n gerçekten bakımı düşük, güvenilir bir otomasyon katmanı oluşturuyor. Özellikle ops ekiplerinin “bunu scriptlemeye vaktimiz yok” dediği küçük ama hayat kurtaran otomasyonlar için ideal.

Bir sonraki yazıda n8n’de ilk gerçek workflow’ları nasıl oluşturduğumuzu, özellikle error handling ve retry mekanizmalarını ele alacağız. n8n öğrenmek görsel arayüzü sayesinde hızlı, ama production-grade workflow yazmak ayrı bir konu.

Bir yanıt yazın

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