İş akışlarını otomatikleştirmek, özellikle tekrarlayan ve manuel hatalara açık süreçlerde, her zaman önceliğim olmuştur. Son zamanlarda AI (yapay zeka) yeteneklerinin bu otomasyonlara entegrasyonu, benim gibi pratik çözümler arayanlar için büyük bir fırsat sunuyor. Ancak bu entegrasyon genellikle kod yazmayı veya karmaşık API entegrasyonlarını gerektiriyor. İşte bu noktada n8n gibi “low-code/no-code” araçlar devreye giriyor. Ben de kendi sunucularımda, veri gizliliğini ve kontrolü elden bırakmadan, AI destekli agent akışları kurmak için n8n’i kullandım. Bu yazıda, bu deneyimimi ve nasıl yapıldığını adım adım anlatacağım.
Neden n8n ve Self-Hosted AI Otomasyonu?
Birkaç yıl önce, özellikle basit veri transferleri ve bildirim akışları için farklı otomasyon araçlarını denedim. Ancak AI yetenekleri işin içine girdiğinde, ya çok pahalı buldum ya da veri güvenliği endişeleri nedeniyle bulut tabanlı çözümlerden uzak durdum. Özellikle bir müşteri projesinde, hassas finansal verilerin işlendiği bir otomasyon kurmamız gerektiğinde, self-hosted bir çözüm kaçınılmaz oldu. n8n, hem geniş entegrasyon yelpazesi sunuyor hem de Docker desteği sayesinde kendi sunucumda rahatça barındırabiliyorum.
Self-hosting, benim için sadece maliyet avantajı değil, aynı zamanda verinin kontrolünü tamamen bende tutmak anlamına geliyor. Özellikle AI agent’lar kullanıldığında, LLM’lere gönderdiğiniz verilerin ne kadarının loglandığı veya eğitim için kullanıldığı konusu her zaman bir soru işareti. Kendi kontrolümdeki bir n8n kurulumu ile bu endişeleri minimuma indirdim. Ayrıca, n8n’in esnek yapısı sayesinde, istediğim kadar özel entegrasyon veya LLM sağlayıcıyı ekleyebilme özgürlüğüne sahibim. Bu, benim gibi farklı LLM’leri test etmeyi seven biri için önemli bir avantaj.
Kurulum Adımları: Docker Compose ile Hızlı Başlangıç
n8n’i kendi sunucunuzda çalıştırmanın en kolay yolu Docker Compose kullanmaktır. Ben genellikle basit kurulumlar için docker-compose.yml dosyasını kendim yazarım. Bu, bana hem esneklik sağlıyor hem de olası sorunlarda debug etmeyi kolaylaştırıyor. Aşağıdaki örnek, temel bir n8n kurulumu için yeterli olacaktır. Burada PostgreSQL’i veritabanı olarak kullanıyorum, çünkü n8n’in SQLite ile çalışması, özellikle yüksek yük altında veya beklenmedik kapanışlarda WAL bloat gibi sorunlara yol açabiliyor. Bir de Redis’i cache ve kuyruk mekanizması için ekledim, bu da performansı artırıyor.
İlk olarak, sunucunuzda bir dizin oluşturun ve içine docker-compose.yml dosyasını yerleştirin:
mkdir n8n-ai-automation
cd n8n-ai-automation
nano docker-compose.yml
docker-compose.yml içeriği şöyle olabilir:
version: '3.8'
services:
n8n:
image: n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_HOST=${N8N_HOST:-localhost}
- N8N_PORT=5678
- N8N_PROTOCOL=${N8N_PROTOCOL:-http}
- WEBHOOK_URL=${WEBHOOK_URL:-http://localhost:5678/}
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB:-n8n}
- DB_POSTGRESDB_USER=${POSTGRES_USER:-n8n}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD:-n8n}
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=${N8N_USER:-admin}
- N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD:-admin_password_change_me}
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- N8N_METRICS_ENABLED=true # Metrikleri Prometheus gibi araclarla izlemek icin
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
- redis
# Kaynak limitleri, OOM killer'dan korunmak icin onemli
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
postgres:
image: postgres:15
restart: always
environment:
- POSTGRES_DB=${POSTGRES_DB:-n8n}
- POSTGRES_USER=${POSTGRES_USER:-n8n}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-n8n}
volumes:
- postgres_data:/var/lib/postgresql/data
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
redis:
image: redis:7
restart: always
volumes:
- redis_data:/data
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 128M
volumes:
n8n_data:
postgres_data:
redis_data:
Bu dosya, n8n, PostgreSQL ve Redis servislerini tanımlar. environment değişkenleri ile n8n’in veritabanı bağlantı bilgilerini ve temel kimlik doğrulama ayarlarını yapıyorum. Güvenlik için N8N_BASIC_AUTH_ACTIVE ve kullanıcı/şifre değişkenlerini kullanmayı unutmayın. Ayrıca, deploy.resources altındaki limits ve reservations ile her servise ayrılacak bellek miktarını belirledim. Bu, özellikle VPS ortamlarında kaynakların aşırı tüketilmesini ve OOM-killed hatalarını önlemek için kritik. Geçen ay bir yan ürünümün CI/CD pipeline’ında bir sleep 360 komutu yüzünden build container’ının OOM-killed olduğunu görmüştüm, bu yüzden kaynak limitlerini baştan tanımlamak alışkanlık haline geldi.
Dosyayı kaydettikten sonra, docker compose up -d komutu ile servisleri başlatabilirsiniz:
docker compose up -d
Birkaç dakika içinde n8n arayüzüne http://localhost:5678 adresinden erişebilirsiniz. Eğer bir reverse proxy (Nginx gibi) kullanıyorsanız, N8N_HOST ve N8N_PROTOCOL değişkenlerini buna göre ayarlamanız gerekecek. Ben genellikle Nginx ile SSL sonlandırması yapıp n8n’i https://automations.benimsitem.com gibi bir adres altında yayınlarım.
İlk AI Agent Akışını Oluşturma
n8n’in gücü, kod yazmadan görsel bir arayüz üzerinden karmaşık iş akışları oluşturabilmesinden geliyor. İlk AI agent akışımızı, gelen bir e-postayı özetleyip Slack’e bildirim gönderme senaryosu üzerinden kurabiliriz. Bu, bir müşteri projesinde destek e-postalarını hızlıca triage etmek için kullandığım basit ama etkili bir yöntemdi.
-
Trigger (Tetikleyici): Workflow’u başlatmak için bir “Email” trigger’ı kullanabiliriz. Ben genellikle bir “Webhook” trigger’ı kurup, e-postaları başka bir servis (örneğin Mailgun veya kendi yazdığım basit bir email parser) üzerinden bu webhook’a yönlendiririm. Ancak n8n’in kendi “IMAP Email” veya “Gmail” node’ları da mevcut. Basitlik adına, bir “Manual Trigger” ile başlayıp, daha sonra gerçek bir tetikleyiciye bağlayabiliriz.
-
LLM Node: “AI” kategorisi altında birçok LLM (Large Language Model) node’u bulacaksınız. Ben genellikle “OpenAI” veya “Generic LLM” node’larını kullanırım. “Generic LLM” node’u, OpenRouter veya kendi özel API’leriniz üzerinden farklı LLM’lere erişim sağlar. Bu node’u tuvale sürükleyip bırakın.
-
Prompt Engineering: LLM node’unun içine, e-postayı özetlemesi için bir
System PromptveUser Promptgireceğiz. Prompt engineering burada kritik. Bir üretim firmasının ERP’sinde, üretim planlama için AI kullanırken, prompt’ların ne kadar detaylı ve yönlendirici olması gerektiğini defalarca test etmiştim.System Promptörneği:You are an AI assistant that summarizes incoming customer support emails. Focus on the main issue, the customer's name (if available), and any urgent requests. Keep the summary concise, maximum 3 sentences.User Promptörneği:Summarize the following email: --- Subject: Arızalı Ürün Hakkında From: Ayşe Yılmaz <[email protected]> Date: 2026-06-15 Body: Merhaba, 12345 sipariş numarası ile aldığım X marka ürününüz arızalı çıktı. Bir haftadır kullanıyorum ve dün aniden çalışmayı durdurdu. Acil değişim talep ediyorum. Lütfen en kısa sürede benimle iletişime geçin. Teşekkürler, Ayşe Yılmaz. ---Bu örneği, gelen e-postanın içeriğini dinamik olarak
{{ $json.body.text }}gibi ifadelerle bağlayabilirsiniz. -
Slack Node: LLM’den gelen özeti Slack kanalına göndermek için bir “Slack” node’u ekleyin. Slack node’unu yapılandırırken, bir Webhook URL veya Bot Token sağlamanız gerekecek. Mesaj kısmına LLM node’undan gelen çıktıyı
{{ $node["LLM Node"].json["text"] }}şeklinde bağlayabilirsiniz.
Bu akışı oluşturduktan sonra, “Test Workflow” düğmesine basarak veya bir test e-postası tetikleyerek çalışıp çalışmadığını kontrol edebilirsiniz. Gördüğünüz gibi, hiçbir kod yazmadan, birkaç sürükle-bırak işlemiyle AI destekli bir otomasyon kurmuş olduk.
Gerçek Dünya Agent Akışları: RAG ve Çoklu LLM Entegrasyonu
Daha karmaşık senaryolarda, AI agent’larımızın sadece genel bilgiye değil, aynı zamanda kendi özel veri setlerimize de erişmesi gerekir. İşte burada RAG (Retrieval-Augmented Generation) devreye giriyor. Bir müşteri projesinde, bankanın iç platformu için bir bilgi tabanı oluştururken, LLM’lerin doğru ve güncel bilgiye erişimi için RAG mimarisini kullanmıştım. n8n ile bunu da kod yazmadan yapabiliriz.
RAG Entegrasyonu
RAG için temel fikir, LLM’e bir soru sormadan önce, soruyla ilgili en alakalı bilgileri kendi veri kaynaklarımızdan çekmek ve bu bilgileri prompt’a eklemektir.
-
Veri Kaynağı: Kendi iç dokümanlarınız (PDF’ler, metin dosyaları, veritabanı kayıtları) bir vektör veritabanına (örneğin Pinecone, Weaviate, Qdrant veya hatta PostgreSQL’in
pg_vectoruzantısı) gömülü olmalıdır. n8n’in bu vektör veritabanlarına doğrudan entegrasyon node’ları vardır. Ben kendi tarafımda genelliklepg_vectorile PostgreSQL’i tercih ediyorum, çünkü zaten elimde olan bir teknolojiyi kullanmak ek maliyeti sıfırlıyor. -
Embeddings Oluşturma: Dokümanlarınızı vektör veritabanına yüklemeden önce, onların “embedding”lerini (sayısal vektör temsillerini) oluşturmanız gerekir. Bunun için “OpenAI Embeddings” veya “Cohere Embeddings” gibi node’ları kullanabilirsiniz.
-
Vektör Arama: Bir soru geldiğinde (örneğin bir Webhook trigger’ından), “Vector Store” kategorisinden ilgili vektör veritabanı node’unu kullanarak soruyla ilgili en alakalı doküman parçalarını ararsınız.
-
Prompt’ı Zenginleştirme: Arama sonuçlarından gelen bilgileri (genellikle metin parçaları), LLM node’unun
User Prompt’una ekleyerek prompt’ı zenginleştirirsiniz. Örneğin:Here is some relevant information from our internal knowledge base: --- {{ $node["Vector Search"].json["results"] }} --- Based on the information above, answer the following question: {{ $json.query }}
Bu sayede LLM, sadece genel bilgilerle değil, sizin kurumsal bilginizle de beslenerek daha doğru ve bağlamsal cevaplar üretebilir.
Çoklu LLM Sağlayıcı Entegrasyonu ve Fallback
Tek bir LLM sağlayıcısına bağımlı kalmak, hem maliyet hem de performans açısından riskli olabilir. Farklı sağlayıcılar farklı modeller sunar ve bu modellerin maliyetleri, hızları ve performansları değişir. n8n ile birden fazla LLM sağlayıcısını entegre edip, duruma göre veya bir sağlayıcı başarısız olduğunda diğerine geçiş yapacak fallback mekanizmaları kurabilirim. Ben genellikle Groq, Gemini Flash ve OpenRouter gibi sağlayıcıları bir arada kullanırım. Groq, hızıyla öne çıkarken, Gemini Flash daha uygun fiyatlı olabilir, OpenRouter ise farklı modelleri tek bir API üzerinden sunar.
Örnek bir çoklu LLM akışı:
- Ana LLM Denemesi: İlk olarak, ana tercih ettiğim LLM sağlayıcısını (örneğin Groq) kullanırım.
- Hata Kontrolü: Eğer Groq node’undan bir hata gelirse (örneğin API zaman aşımı veya rate limit), bir “IF” node’u ile bu durumu kontrol ederim.
- Fallback LLM: Hata durumunda, “IF” node’unun “true” dalından başka bir LLM node’una (örneğin OpenRouter üzerinden Gemini Flash) geçiş yaparım.
- Sonuç Birleştirme: Her iki LLM’den gelen sonuçları daha sonra bir “Merge” node’u ile birleştirip, akışın kalanına tek bir çıktı olarak sunabilirim.
Bu mimari, özellikle kritik iş akışlarında kesintisizliği sağlamak için hayati önem taşır. Bir yan ürünümün finansal hesaplayıcılarında, AI tabanlı tahminler yaparken bu fallback mekanizmasını kullanıyorum. Böylece bir sağlayıcıda sorun olduğunda kullanıcı deneyimi kesintiye uğramıyor.
Operasyonel Detaylar: Güvenlik, İzleme ve Bakım
Self-hosted bir sistem kurmak, beraberinde operasyonel sorumlulukları da getirir. n8n’in sorunsuz ve güvenli çalışması için bazı temel önlemleri alıyorum.
Güvenlik Önlemleri
-
Nginx Reverse Proxy ve SSL: n8n’i doğrudan internete açmak yerine, önüne bir Nginx reverse proxy koyarım. Nginx ile hem SSL sonlandırması (Let’s Encrypt ile ücretsiz) yaparım hem de temel güvenlik katmanları eklerim. Örneğin,
rate limitingile DDoS saldırılarına karşı ilk savunmayı oluştururum. Ayrıca,X-Content-Type-Options,X-Frame-Optionsgibi HTTP security header’larını ayarlarım.Örnek Nginx yapılandırması:
server { listen 80; server_name automations.benimsitem.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name automations.benimsitem.com; ssl_certificate /etc/letsencrypt/live/automations.benimsitem.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/automations.benimsitem.com/privkey.pem; # Güvenlik header'lari add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; add_header X-XSS-Protection "1; mode=block"; location / { proxy_pass http://localhost:5678; 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; # Rate limiting ornegi # limit_req zone=one burst=5 nodelay; } } -
Fail2ban: Sunucuma SSH üzerinden yapılan brute-force saldırılarını engellemek için
fail2bankullanırım. Ayrıca, n8n’in web arayüzüne yapılan başarısız giriş denemelerini de loglardan takip edipfail2banile engelleyebilirim. Bunun için n8n loglarınıjournaldile merkezi olarak toplar vefail2baniçin özel bir jail kuralı yazarım.Örnek
fail2banjail kuralı (n8n için):[n8n-auth] enabled = true port = http,https filter = n8n-auth logpath = /var/log/syslog # Veya journald'dan gelen loglarin saklandigi yer maxretry = 5 bantime = 3600Ve
filter.d/n8n-auth.confdosyası:[Definition] failregex = .*n8n.*authentication failed for user.*<HOST>.* ignoreregex =Bu kural, n8n loglarında “authentication failed for user” desenini arayarak başarısız giriş denemelerini tespit eder ve IP adresini bir saatliğine engeller.
-
Kernel Module Blacklist: Güvenlik açıklarına karşı, kullanmadığım kernel modüllerini blacklist’e alırım. Özellikle
algif_aeadgibi modüllerin eski CVE’leri (CVE-2026-31431 gibi) olduğunda bu tür önlemler almak önemlidir. Bu, genel sistem güvenliğini artırır.
İzleme ve Bakım
- Log Yönetimi:
journaldile tüm Docker container’larının loglarını merkezi olarak toplarım. Bu, sorun giderme ve güvenlik denetimi için çok önemlidir. Bir hata durumunda,journalctl -u docker.service -fkomutu ile canlı logları izlerim veyajournalctl -u docker.service --since "1 hour ago"ile geçmiş logları kontrol ederim. - Kaynak İzleme:
cgrouplimitlerini Docker Compose dosyasında belirterek bellek ve CPU kullanımını kontrol altında tutarım. Bunun yanı sıra, Prometheus ve Grafana gibi araçlarla n8n’in kendi metriklerini (N8N_METRICS_ENABLED=trueile açılan) ve sunucunun genel kaynak kullanımını izlerim. ÖzelliklePostgreSQL WAL bloatveyaRedis OOM eviction policygibi durumları önceden tespit etmek için veritabanı ve cache sunucularının metriklerini yakından takip ederim. - Yedekleme: PostgreSQL veritabanı için düzenli yedeklemeler alırım.
pg_dumpkomutu veya bir yedekleme aracı ile bu işlemi otomatize ederim. n8n workflow’ları da bir JSON dosyası olarak dışa aktarılabilir, bu da kurtarma senaryolarında işime yarar.
Sonuç ve Gelecek Adımlar
n8n ile kendi AI otomasyonlarımı self-hosted olarak kurmak, bana hem esneklik hem de maliyet avantajı sağladı. Özellikle kod yazmadan karmaşık agent akışları oluşturabilmek, RAG ile kendi verimi kullanabilmek ve farklı LLM sağlayıcılarını entegre edebilmek büyük bir artı. Bir üretim ERP’sinde üretim planlama, bir e-ticaret sitesinde müşteri destek e-postalarını önceliklendirme veya kendi yan ürünümde finansal tahminler yapma gibi birçok farklı senaryoda bu tür AI otomasyonlarını kullanıyorum.
Bu kurulum, sadece AI entegrasyonu değil, aynı zamanda sistem yönetimi, ağ güvenliği (Nginx, fail2ban) ve veritabanı optimizasyonu (PostgreSQL) gibi birçok alandaki deneyimimi bir araya getirdiğim bir proje oldu. Başlangıçta bazı MTU/MSS mismatches veya DNS negative caching gibi sinsi sorunlarla karşılaşsam da, adım adım debug ederek çözdüm.
Eğer siz de kendi AI otomasyonlarınızı kurmak istiyor ancak kod yazmak istemiyorsanız ve veri kontrolü sizin için öncelikliyse, n8n’in self-hosted kurulumu kesinlikle denemeye değer. Bir sonraki adım olarak, bu AI agent’ları daha da akıllı hale getirmek için “agent pattern”lerini (planlama, araç kullanımı, hafıza) n8n içinde nasıl daha etkili kullanabileceğimi araştırıyorum. Belki de bir sonraki yazımda bu konuyu ele alırım.