ngrok ile Yerel Webhook Geliştirme Ortamı Kurulumu

Webhook geliştirirken en can sıkıcı problem şu: yazdığın kodu test etmek için her seferinde bir sunucuya deploy etmek zorunda kalıyorsun. GitHub’dan push event’i gelecek, Stripe’tan ödeme bildirimi gelecek, Slack’ten bir mesaj tetiklenecek ama senin localhost:3000’in dış dünyaya kapalı. İşte tam bu noktada ngrok devreye giriyor ve hayatını kurtarıyor.

ngrok Nedir ve Nasıl Çalışır?

ngrok, lokal makinendeki bir portu güvenli bir tünel aracılığıyla internete açan bir araç. Teknik olarak konuşursak: ngrok sunucuları üzerinden encrypted bir tünel kuruyor ve sana https://abc123.ngrok.io gibi geçici bir public URL veriyor. Bu URL’e gelen tüm istekler lokal makinendeki uygulamana iletiliyor.

Webhook geliştirme senaryosunda şöyle çalışıyor:

  • Stripe bir ödeme işlemi tamamlandığında https://abc123.ngrok.io/webhook/stripe adresine POST isteği gönderiyor
  • ngrok bu isteği alıyor ve lokal localhost:3000/webhook/stripe adresine iletiiyor
  • Uygulamandan dönen yanıt da aynı şekilde geri gönderiliyor

Araya production deploy atmadan, gerçek webhook verisiyle lokal ortamda debug yapabiliyorsun. Bu iş akışını bir kez tattıktan sonra eskiye dönmek istemiyorsun.

Kurulum

Linux Kurulumu

# Snap ile kurulum (Ubuntu/Debian)
sudo snap install ngrok

# Ya da doğrudan binary indirme
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok

# Arch Linux
yay -S ngrok

macOS Kurulumu

# Homebrew ile
brew install ngrok/ngrok/ngrok

Windows Kurulumu

# Chocolatey ile
choco install ngrok

# Ya da Scoop ile
scoop install ngrok

Kurulum sonrası ngrok hesabı oluşturman gerekiyor. [ngrok.com](https://ngrok.com) adresinden ücretsiz hesap açabilirsin. Ücretsiz plan çoğu geliştirme senaryosu için yeterli ama bazı kısıtlamaları var (buna sonra değineceğiz).

Authentication Token’ı Yapılandırma

Hesap oluşturduktan sonra dashboard’dan authtoken’ını alıp ayarlaman gerekiyor:

ngrok config add-authtoken YOUR_AUTH_TOKEN_BURADA

# Config dosyasının nerede olduğunu görmek için
ngrok config check

Token ~/.config/ngrok/ngrok.yml dosyasına yazılıyor. Linux’ta bu dosyayı doğrudan da düzenleyebilirsin:

# ~/.config/ngrok/ngrok.yml
version: "2"
authtoken: YOUR_AUTH_TOKEN_BURADA

İlk Tüneli Başlatmak

En basit kullanım şekli şu:

# 3000 portunu internete aç
ngrok http 3000

# HTTPS tüneli (varsayılan olarak zaten HTTPS açıyor)
ngrok http --bind-tls=true 3000

Komutu çalıştırdığında terminalde şöyle bir çıktı göreceksin:

Session Status                online
Account                       [email protected] (Plan: Free)
Update                        update available
Version                       3.3.0
Region                        Europe (eu)
Latency                       23ms
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://abc123def456.ngrok-free.app -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

Burada kritik iki şey var:

  • Forwarding URL: Dış dünyaya verdiğin adres, bu adresi webhook servislerine tanımlayacaksın
  • Web Interface: http://127.0.0.1:4040 adresinde ngrok’un yerel dashboard’u açılıyor, tüm istekleri buradan izleyebilirsin

Web Interface ile Debug Yapmak

ngrok’un en güçlü özelliklerinden biri web arayüzü. Tarayıcıdan http://localhost:4040 adresini açtığında her gelen isteğin detayını görebiliyorsun:

  • HTTP method ve path
  • Request headers
  • Request body (JSON, form data, hepsi)
  • Response status kodu
  • Response body
  • Gecikme süresi

Özellikle Stripe veya GitHub webhook’larını test ederken bu arayüz inanılmaz işe yarıyor. Bir istek geldiğinde tam payload’u görüp kendi kodunda ne beklediğini anlıyorsun.

Daha da güzeli: Replay butonu var. Bir isteği tekrar tekrar gönderebiliyorsun. Webhook handler’ında bir bug buldun, düzelttdin, uygulamayı yeniden başlattın ve aynı isteği replay edebiliyorsun. Gerçek webhook servisini tekrar tetiklemene gerek kalmıyor.

Gerçek Dünya Senaryosu 1: Stripe Webhook Entegrasyonu

Stripe ile çalışıyorsun ve ödeme başarılı olduğunda kendi uygulamana bildirim gelsin istiyorsun. Normalde bunu test etmek için ya production ortamına deploy atmak ya da Stripe’ın test event’lerini kullanmak gerekiyor. ngrok ile çok daha kolay.

Önce basit bir webhook handler yazalım (Node.js/Express örneği):

// webhook-server.js
const express = require('express');
const app = express();

// Stripe webhook için raw body gerekli
app.use('/webhook/stripe', express.raw({ type: 'application/json' }));
app.use(express.json());

app.post('/webhook/stripe', (req, res) => {
    const event = JSON.parse(req.body);
    
    console.log(`Event type: ${event.type}`);
    console.log(`Event data:`, JSON.stringify(event.data, null, 2));
    
    switch (event.type) {
        case 'payment_intent.succeeded':
            const paymentIntent = event.data.object;
            console.log(`Ödeme başarılı! Amount: ${paymentIntent.amount}`);
            // Veritabanı güncellemesi, email gönderimi vs.
            break;
        case 'customer.subscription.deleted':
            console.log('Abonelik iptal edildi');
            break;
        default:
            console.log(`Bilinmeyen event: ${event.type}`);
    }
    
    res.json({ received: true });
});

app.listen(3000, () => {
    console.log('Webhook server 3000 portunda çalışıyor');
});

Sunucuyu başlat, ngrok’u aç:

node webhook-server.js &
ngrok http 3000

Aldığın URL’i (örneğin https://abc123.ngrok-free.app) Stripe Dashboard’da Developers > Webhooks bölümüne ekle. Endpoint URL olarak https://abc123.ngrok-free.app/webhook/stripe yaz.

Artık Stripe’ta test ödeme yapabilir ve lokal terminalde event’in geldiğini görebilirsin. Hem Stripe’ın arayüzünde hem de ngrok’un web arayüzünde her şeyi izleyebilirsin.

Gerçek Dünya Senaryosu 2: GitHub Webhook ile CI/CD Testi

GitHub repository’ne push atıldığında tetiklenmesini istediğin bir script var. Bunu production’da test etmeden önce lokal ortamda doğrulamak istiyorsun.

# github_webhook.py
from flask import Flask, request, jsonify
import hashlib
import hmac
import json
import os

app = Flask(__name__)

GITHUB_SECRET = os.environ.get('GITHUB_SECRET', 'mysecrettoken')

def verify_signature(payload, signature):
    """GitHub webhook imzasını doğrula"""
    mac = hmac.new(
        GITHUB_SECRET.encode('utf-8'),
        msg=payload,
        digestmod=hashlib.sha256
    )
    expected = f"sha256={mac.hexdigest()}"
    return hmac.compare_digest(expected, signature)

@app.route('/webhook/github', methods=['POST'])
def github_webhook():
    signature = request.headers.get('X-Hub-Signature-256', '')
    
    if not verify_signature(request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401
    
    event_type = request.headers.get('X-GitHub-Event')
    payload = request.json
    
    if event_type == 'push':
        branch = payload['ref'].split('/')[-1]
        commits = len(payload['commits'])
        pusher = payload['pusher']['name']
        
        print(f"Push event! Branch: {branch}, Commits: {commits}, By: {pusher}")
        
        if branch == 'main':
            print("Main branch'e push var, deployment tetikleniyor...")
            # os.system("./deploy.sh") gibi bir şey çalıştırabilirsin
    
    elif event_type == 'pull_request':
        action = payload['action']
        pr_title = payload['pull_request']['title']
        print(f"PR Event: {action} - {pr_title}")
    
    return jsonify({'status': 'ok'})

if __name__ == '__main__':
    app.run(port=3000, debug=True)
# Secret'ı ayarla ve sunucuyu başlat
export GITHUB_SECRET="mysecrettoken"
python github_webhook.py &

# Tüneli aç
ngrok http 3000

GitHub’da repository Settings > Webhooks > Add webhook kısmına gidip ngrok URL’ini ekle. Content type olarak application/json seç, secret’ı gir ve hangi event’leri almak istediğini seç.

ngrok Config Dosyası ile Çoklu Tünel

Birden fazla servisi aynı anda dışarıya açman gerekebilir. Örneğin backend 3000’de, webhook handler 4000’de çalışıyor. Her birini ayrı terminalde açmak yerine config dosyası kullanabilirsin:

# ~/.config/ngrok/ngrok.yml
version: "2"
authtoken: YOUR_AUTH_TOKEN

tunnels:
  backend:
    addr: 3000
    proto: http
    inspect: true
  
  webhook-handler:
    addr: 4000
    proto: http
    inspect: true
  
  grpc-service:
    addr: 5000
    proto: http
    inspect: true

Tüm tünelleri aynı anda başlatmak için:

# Tüm tünelleri başlat
ngrok start --all

# Sadece belirli tünelleri başlat
ngrok start backend webhook-handler

Custom Subdomain Kullanımı

Ücretsiz planda her ngrok başlatışında farklı bir URL alıyorsun. Bu durum şunu zorlaştırıyor: her seferinde webhook URL’ini ilgili servise tekrar girmek gerekiyor. Paid planlarda sabit subdomain tanımlayabiliyorsun:

# Paid plan ile sabit subdomain
ngrok http --subdomain=mywebhooks 3000

# Bu şekilde her zaman aynı URL alırsın
# https://mywebhooks.ngrok.io

Eğer free plan kullanıyorsan ve bu can sıkıcı geliyorsa, webhook URL’ini her değiştiğinde otomatik güncelleyen basit bir script yazabilirsin. Örneğin ngrok’un API’sini kullanarak:

#!/bin/bash
# get-ngrok-url.sh
# ngrok başladıktan sonra aktif tünel URL'ini getir

sleep 2  # ngrok'un başlaması için bekle

NGROK_URL=$(curl -s http://localhost:4040/api/tunnels | 
    python3 -c "import sys, json; tunnels = json.load(sys.stdin)['tunnels']; 
    print([t['public_url'] for t in tunnels if t['proto'] == 'https'][0])")

echo "Aktif ngrok URL: $NGROK_URL"
echo "Webhook endpoint: $NGROK_URL/webhook"

# Otomatik olarak clipboard'a kopyala (Linux)
echo "$NGROK_URL/webhook" | xclip -selection clipboard
echo "URL clipboard'a kopyalandı!"
chmod +x get-ngrok-url.sh
ngrok http 3000 &
./get-ngrok-url.sh

ngrok’u Systemd Service Olarak Çalıştırmak

Geliştirme ortamında ngrok’u her oturumda manuel başlatmak istemiyorsan systemd service tanımlayabilirsin:

# /etc/systemd/system/ngrok-webhook.service
sudo tee /etc/systemd/system/ngrok-webhook.service << 'EOF'
[Unit]
Description=ngrok Webhook Tunnel
After=network.target

[Service]
Type=simple
User=youruser
ExecStart=/usr/local/bin/ngrok http 3000 --log=stdout
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable ngrok-webhook
sudo systemctl start ngrok-webhook

# Durumu kontrol et
sudo systemctl status ngrok-webhook

# Logları takip et
sudo journalctl -u ngrok-webhook -f

Güvenlik Konuları

ngrok kullanırken aklında bulundurman gereken birkaç önemli nokta var.

Kimlik doğrulama ekle: Tüneli açık bırakırsın ve başkası keşfederse uygulamana istek gönderebilir. ngrok’un basic auth özelliğini kullan:

# Basic auth ile tünel aç
ngrok http 3000 --basic-auth="kullanici:sifre"

# Ya da config dosyasında
# tunnels:
#   myapp:
#     addr: 3000
#     proto: http
#     auth: "kullanici:sifre"

IP kısıtlaması: Belirli IP’lerden gelen isteklere izin ver. Örneğin sadece Stripe’ın IP aralıklarından istek bekliyorsun:

# Sadece belirli IP'ye izin ver
ngrok http 3000 --cidr-allow=140.238.1.0/24

Webhook secret doğrulaması: Yukarıdaki GitHub örneğinde gördüğün gibi, webhook imzasını her zaman doğrula. ngrok bir tünel açıyor ama bu gelecek isteklerin meşru olduğunu garanti etmiyor.

Inspection’ı kapat: Bazı durumlarda web arayüzünde görünen veriler hassas olabilir (API key, kullanıcı verisi vs.). Production benzeri verilerle çalışıyorsan inspection’ı kapatabilirsin:

ngrok http 3000 --inspect=false

Docker ile ngrok Kullanımı

Dockerize edilmiş bir uygulamayla çalışıyorsan ngrok’u da container olarak çalıştırabilirsin:

# docker-compose.yml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    networks:
      - app-network
  
  ngrok:
    image: ngrok/ngrok:latest
    command: http app:3000 --log=stdout
    ports:
      - "4040:4040"
    environment:
      - NGROK_AUTHTOKEN=${NGROK_AUTHTOKEN}
    depends_on:
      - app
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
# NGROK_AUTHTOKEN'ı ayarla
export NGROK_AUTHTOKEN=your_token_here

# Compose'u başlat
docker compose up -d

# ngrok URL'ini öğren
curl -s http://localhost:4040/api/tunnels | python3 -m json.tool

Ücretsiz Plan Kısıtlamaları

ngrok’un ücretsiz planını kullanıyorsan şunları bilmen gerekiyor:

  • Rastgele URL: Her başlatışta farklı bir URL alıyorsun
  • Aylık bant genişliği: 1 GB transfer limiti var
  • Eşzamanlı bağlantı: Aynı anda 1 tünel açabiliyorsun
  • Inspect süresi: İnceleme verisi 8 saatlik geçmişi saklıyor
  • Request rate: Dakikada 40 istek sınırı var

Geliştirme aşamasında bu limitler genellikle yeterli oluyor. Ama yoğun webhook testleri yapıyorsan ya da birden fazla tünel gerekiyorsa paid plana geçmeyi düşünebilirsin. Starter plan aylık 10 dolar civarı ve bu noktadaki en büyük avantaj sabit domain ve çoklu tünel.

Alternatifler

ngrok’u sevmiyorsan ya da daha fazla kontrol istiyorsan alternatiflere bakabilirsin:

  • localtunnel: Açık kaynak, ücretsiz ama bazen kararsız
  • Cloudflare Tunnel: Cloudflare hesabın varsa çok iyi bir seçenek, ücretsiz ve kalıcı URL veriyor
  • telebit: Self-hosted seçenek, kendi sunucunda kuruyorsun
  • frp: Çin kaynaklı açık kaynak, self-hosted, çok esnek

Özellikle Cloudflare Tunnel’ı öneriyorum. Eğer bir domainin varsa ve Cloudflare kullanıyorsan, cloudflared tunnel komutuyla çok benzer bir çözüm elde edebiliyorsun. Üstelik permanent URL verdiği için webhook URL’ini bir kez tanımlıyorsun ve bir daha değiştirmiyorsun.

Hata Ayıklama İpuçları

ngrok ile çalışırken karşılaşabileceğin yaygın sorunlar:

“ERR_NGROK_108” hatası: Genellikle authtoken problemi. ngrok config check ile token’ın doğru ayarlandığından emin ol.

Tünel aniden kapanıyor: Ücretsiz planda 8 saatlik oturum süresi var. Uzun geliştirme seansları için yeni tünel başlatman gerekiyor.

Webhook gelmiyor gibi görünüyor: Önce http://localhost:4040 arayüzünü kontrol et. İstek geliyor mu? Geliyorsa uygulamanın problemi. Gelmiyorsa webhook URL’ini tekrar kontrol et.

Local uygulama HTTPS bekliyor: ngrok HTTPS tüneli açıyor ama lokal uygulamana HTTP ile yönlendiriyor. Bu normalde sorun olmaz ama --host-header parametresini kullanman gerekebilir:

# Host header'ı yeniden yaz
ngrok http 3000 --host-header=rewrite

# Ya da özel host header belirt
ngrok http 3000 --host-header="localhost:3000"

Sonuç

ngrok, webhook geliştirme sürecindeki en büyük acıyı ortadan kaldırıyor. Her test için sunucuya deploy atmak zorunda kalmıyorsun, üretim ortamına benzer gerçek verilerle lokal ortamda çalışabiliyorsun ve ngrok’un web arayüzü sayesinde her isteğin detayını anında inceleyip replay edebiliyorsun.

Kurulum beş dakika sürüyor, temel kullanım tek bir komutla başlıyor. Stripe’tan ödeme event’i bekliyorsun, GitHub’dan push bildirimi gelecek ya da herhangi bir webhook entegrasyonu geliştiriyorsun; ngrok olmadan bu işleri yapmak gerçekten zahmetli. Bir kez alıştıktan sonra geliştirme iş akışının ayrılmaz bir parçası haline geliyor.

Eğer self-hosted çözüm arıyorsan Cloudflare Tunnel’a da göz at, özellikle kalıcı URL ihtiyacın varsa daha iyi bir seçenek olabilir. Ama hızlıca bir tünel açıp test yapmak istiyorsan ngrok hala en pratik seçenek.

Bir yanıt yazın

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