Nginx Debug Modu: error_log Debug Seviyesi ile Hata Ayıklama

Nginx üzerinde garip bir şey oluyor, istekler düzgün gitmiyor, upstream bağlantıları kesiliyor ya da bir location bloğu beklendiği gibi çalışmıyor. Normal log seviyeleri sana yeterli bilgiyi vermiyor. İşte bu noktada error_log direktifinin debug seviyesi devreye giriyor. Bu yazıda Nginx’in debug log modunu en ince ayrıntısına kadar ele alacağız.

Nginx Log Seviyeleri Hiyerarşisi

Nginx’te error_log direktifi birden fazla log seviyesini destekler. Bu seviyeler aşağıdan yukarıya doğru giderek daha az ayrıntı içerir:

  • debug: Her şeyi loglar, en ayrıntılı seviye
  • info: Genel bilgi mesajları
  • notice: Önemli ama hata olmayan olaylar
  • warn: Uyarılar
  • error: Hatalar (varsayılan davranışa en yakın)
  • crit: Kritik hatalar
  • alert: Acil müdahale gerektiren durumlar
  • emerg: Sistem kullanılamaz hale geldi

Bir seviye seçtiğinde, o seviye ve üzeri tüm mesajlar loglanır. Yani warn seçersen warn, error, crit, alert ve emerg mesajlarını görürsün. debug seçersen gerçekten her şeyi görürsün.

Debug Modunu Aktif Etmek için Nginx Derleme Şartı

Burada kritik bir nokta var: Nginx’i debug moduyla kullanmak için binary’nin --with-debug flag’iyle derlenmiş olması gerekiyor. Bu flag olmadan error_log direktifine debug yazsanbile hiçbir şey olmaz.

Kurulu Nginx’in debug desteğiyle gelip gelmediğini kontrol etmek için:

nginx -V 2>&1 | grep -- '--with-debug'

Eğer çıktıda --with-debug görüyorsan hazırsın. Görmüyorsan birkaç seçeneğin var:

Ubuntu/Debian için:

apt-get install nginx-debug

Bu paket, /usr/sbin/nginx-debug binary’sini kurar. Aynı config dosyalarını kullanır, sadece binary farklıdır.

CentOS/RHEL için resmi Nginx repo’sundan:

yum install nginx-debug
# veya
dnf install nginx-debug

Manuel derleme tercih ediyorsan:

./configure --with-debug --with-http_ssl_module --with-http_v2_module 
  --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx 
  --modules-path=/usr/lib64/nginx/modules 
  --conf-path=/etc/nginx/nginx.conf 
  --error-log-path=/var/log/nginx/error.log 
  --http-log-path=/var/log/nginx/access.log 
  --pid-path=/var/run/nginx.pid
make && make install

Temel Konfigürasyon

Debug loglamayı açmanın en basit yolu nginx.conf dosyasındaki error_log direktifini güncellemek:

# /etc/nginx/nginx.conf

error_log /var/log/nginx/error.log debug;

events {
    worker_connections 1024;
}

http {
    # ...
}

Bu ayar global seviyede tüm trafiği debug modda loglar. Dikkat: Production’da bunu yapmak log dosyasını çok hızlı büyütür ve disk I/O’yu ciddi şekilde artırır. Yüksek trafikli bir sunucuda dakikalar içinde GB’larca log üretebilirsin.

nginx-debug binary kullanıyorsan servisi şöyle başlatabilirsin:

# Önce normal nginx'i durdur
systemctl stop nginx

# Debug binary'yi başlat
nginx-debug -c /etc/nginx/nginx.conf

# Veya systemd ile
service nginx-debug start

Logları gerçek zamanlı takip etmek için:

tail -f /var/log/nginx/error.log | grep -v "^$"

Belirli IP İçin Debug Loglama

Production ortamında en güvenli yöntem sadece belirli bir IP adresinden gelen istekler için debug loglamayı aktif etmektir. Bu sayede diğer kullanıcılar etkilenmez ve log dosyası kontrolsüz büyümez.

# /etc/nginx/nginx.conf

error_log /var/log/nginx/error.log;

events {
    worker_connections 1024;
    debug_connection 192.168.1.50;
    debug_connection 10.0.0.0/24;
}

debug_connection direktifi events bloğu içinde tanımlanır ve IP adresi veya CIDR notasyonu kabul eder. Bu yöntemi kullandığında global error_log seviyesi ne olursa olsun, belirtilen IP’lerden gelen bağlantılar için debug mesajları üretilir.

Birden fazla IP veya subnet tanımlayabilirsin:

events {
    worker_connections 1024;
    debug_connection 192.168.1.50;      # Geliştirici bilgisayarı
    debug_connection 10.10.0.0/16;      # İç ağ
    debug_connection 172.16.5.100;      # Test sunucusu
}

Virtual Host Bazlı Debug Loglama

Her server bloğu için ayrı debug log dosyası tanımlamak izolasyon açısından çok işe yarıyor:

http {
    # Genel log seviyesi normal kalsın
    error_log /var/log/nginx/error.log warn;

    server {
        listen 80;
        server_name app.example.com;

        # Sadece bu virtual host için debug
        error_log /var/log/nginx/app_debug.log debug;

        location / {
            proxy_pass http://backend;
        }
    }

    server {
        listen 80;
        server_name static.example.com;
        # Bu server normal log seviyesini kullanır
        root /var/www/static;
    }
}

Bu konfigürasyonla app.example.com‘a gelen tüm istekler /var/log/nginx/app_debug.log dosyasına debug seviyesinde loglanırken diğer server blokları etkilenmez.

Gerçek Dünya Senaryosu 1: Upstream Bağlantı Sorunları

Diyelim ki bir reverse proxy kurulumunda upstream sunucuya zaman zaman bağlanamıyorsun ama hata mesajı yeterince açıklayıcı değil. Debug logu bu durumda altın değerinde:

upstream backend_pool {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
    keepalive 32;
}

server {
    listen 80;
    server_name api.example.com;

    error_log /var/log/nginx/api_debug.log debug;

    location /api/ {
        proxy_pass http://backend_pool;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }
}

Debug logunda şunları arayabilirsin:

# Upstream seçim kararlarını gör
grep "upstream" /var/log/nginx/api_debug.log | grep -E "trying|next"

# Keepalive bağlantı durumunu kontrol et
grep "keepalive" /var/log/nginx/api_debug.log

# Bağlantı hatalarını filtrele
grep "connect() failed|upstream timed out" /var/log/nginx/api_debug.log

Debug logda tipik bir upstream seçim akışı şöyle görünür:

2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: found 0 live connections
2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: trying to reuse keepalive connection
2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: keepalive connection is reused

Bağlantı sorunu varsa şunu görürsün:

2024/01/15 14:23:42 [debug] 12345#0: *2 upstream: next upstream
2024/01/15 14:23:42 [error] 12345#0: *2 connect() failed (111: Connection refused)

Gerçek Dünya Senaryosu 2: Location Bloğu Eşleşme Sorunları

Bir müşterim location bloklarının beklenmedik şekilde çalıştığından şikayet etti. Regex location’ları ile prefix location’ları çakışıyordu. Debug log bu durumu çözmekte son derece etkili:

server {
    listen 80;
    server_name example.com;

    error_log /var/log/nginx/location_debug.log debug;

    location /api {
        proxy_pass http://api_backend;
    }

    location ~* ^/api/v2/(.*)$ {
        proxy_pass http://api_v2_backend/$1;
    }

    location /static {
        root /var/www;
        expires 30d;
    }

    location / {
        proxy_pass http://main_backend;
    }
}

Debug logda hangi location’ın seçildiğini görmek için:

grep "test location|using location|rewrite" /var/log/nginx/location_debug.log

Örnek debug çıktısı:

[debug] worker process: test location: "/api/v2/users"
[debug] worker process: test location: ~ "^/api/v2/(.*)$"
[debug] worker process: using configuration "^/api/v2/(.*)$"

Bu çıktı sana hangi location’ın kazandığını net olarak gösterir.

Gerçek Dünya Senaryosu 3: SSL/TLS Handshake Hataları

SSL sorunları debug modda inanılmaz derecede detaylı görünür. Özellikle client certificate doğrulama (mTLS) sorunlarında bu bilgiler hayat kurtarır:

server {
    listen 443 ssl;
    server_name secure.example.com;

    error_log /var/log/nginx/ssl_debug.log debug;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    ssl_client_certificate /etc/nginx/ssl/ca.pem;
    ssl_verify_client on;

    location / {
        proxy_pass http://backend;
    }
}

SSL debug mesajlarını filtrelemek için:

# SSL handshake adımlarını takip et
grep "ssl|SSL" /var/log/nginx/ssl_debug.log | head -50

# Sertifika doğrulama hatalarını bul
grep "verify|certificate" /var/log/nginx/ssl_debug.log

# Cipher suite müzakerelerini gör
grep "cipher|protocol" /var/log/nginx/ssl_debug.log

Debug Log Dosyasını Yönetmek

Debug modu açıkken log dosyası hızla büyür. Birkaç pratik önlem almanı öneririm:

Log rotation ayarı:

# /etc/logrotate.d/nginx-debug dosyası oluştur
cat > /etc/logrotate.d/nginx-debug << 'EOF'
/var/log/nginx/*_debug.log {
    daily
    missingok
    rotate 3
    compress
    delaycompress
    notifempty
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /var/run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}
EOF

Geçici debug için log boyutunu izle:

# Debug loglamayı açtıktan sonra boyutu izle
watch -n 5 'ls -lh /var/log/nginx/debug.log && tail -1 /var/log/nginx/debug.log'

Log dosyasını sıfırla ama silme (rotation olmadan):

# Dosyayı truncate et, nginx inode'u tuttuğu için sorunsuz çalışır
> /var/log/nginx/debug.log

# Sonra nginx'e log dosyasını yeniden açmasını söyle
nginx -s reopen

Debug Log Analiz Araçları

Ham debug logu çok gürültülü olabilir. Anlamlı bilgileri çıkarmak için bazı pratik grep komutları:

# Belirli bir istek ID'sini takip et (connection numarası ile)
CONNECTION_ID="12345"
grep "*${CONNECTION_ID}" /var/log/nginx/debug.log

# Tüm benzersiz hata mesajlarını listele
grep "[error]|[warn]" /var/log/nginx/debug.log | 
  sed 's/[0-9]{4}/[0-9]{2}/[0-9]{2}.*] //' | 
  sort | uniq -c | sort -rn | head -20

# Belirli bir URL path'i için debug akışını gör
grep "GET /api/users" /var/log/nginx/debug.log | 
  awk '{print $NF}' | sort | uniq

# Upstream response time dağılımı
grep "upstream response time" /var/log/nginx/access.log | 
  awk '{print $NF}' | sort -n | 
  awk 'BEGIN{c=0; s=0} {c++; s+=$1; a[c]=$1} END{
    print "Count:", c
    print "Avg:", s/c
    print "P95:", a[int(c*0.95)]
    print "Max:", a[c]
  }'

Nginx Debug Log ile İlgili Yaygın Yanılgılar

Yanılgı 1: “Debug log açtım ama hiçbir şey göremiyorum”

Bu genellikle iki sebepten olur. Birincisi, binary --with-debug olmadan derlenmiştir. İkincisi, error_log direktifini yanlış context’te tanımlamışsındır. debug_connection her zaman events bloğunda olmalı:

# YANLIŞ - events dışında
http {
    debug_connection 192.168.1.1;  # Bu çalışmaz!
}

# DOĞRU
events {
    debug_connection 192.168.1.1;
}

Yanılgı 2: “Server bloğundaki error_log global olanı override eder”

Bu kısmen doğru. Server bloğundaki error_log o server için ayrı bir log dosyası açar ama global log tamamen kapanmaz. Her iki dosyaya da yazılır.

Yanılgı 3: “Debug modu performance’ı biraz etkiler”

Hayır, “biraz” değil. Debug modu ciddi şekilde etkiler. Her bağlantı için onlarca, bazen yüzlerce satır log yazılır. Yüksek trafikli ortamda disk I/O bottleneck’i yaratabilir. Asla production’da genel debug loglamayı açık bırakma. debug_connection ile sadece test IP’ni hedefle.

Config Değişikliği Sonrası Reload

Config’i güncelledikten sonra Nginx’i reload et. Restart gerektirmez:

# Config syntax kontrolü
nginx -t

# Config doğruysa reload
nginx -s reload
# veya
systemctl reload nginx

# Debug loglanmaya başladı mı kontrol et
tail -f /var/log/nginx/error.log

Debug Modunu Programatik Olarak Aç/Kapat

Bazen anlık sorun yakalama için debug modunu dinamik olarak açıp kapatman gerekebilir. Bunun için basit bir script işe yarar:

#!/bin/bash
# /usr/local/bin/nginx-debug-toggle

NGINX_CONF="/etc/nginx/nginx.conf"
BACKUP_CONF="/etc/nginx/nginx.conf.backup"

toggle_debug() {
    local action=$1
    cp $NGINX_CONF $BACKUP_CONF

    if [ "$action" = "on" ]; then
        sed -i 's/error_log.*error;/error_log /var/log/nginx/error.log debug;/' $NGINX_CONF
        echo "Debug mode: ON"
    elif [ "$action" = "off" ]; then
        sed -i 's/error_log.*debug;/error_log /var/log/nginx/error.log warn;/' $NGINX_CONF
        echo "Debug mode: OFF"
    fi

    nginx -t && nginx -s reload || {
        echo "Config hatasi, geri yukleniyor..."
        cp $BACKUP_CONF $NGINX_CONF
        nginx -s reload
    }
}

case "$1" in
    on|off) toggle_debug $1 ;;
    *) echo "Kullanim: $0 [on|off]" ;;
esac
chmod +x /usr/local/bin/nginx-debug-toggle

# Debug'ı aç
nginx-debug-toggle on

# Sorunu repro et, logları incele
tail -f /var/log/nginx/error.log

# Debug'ı kapat
nginx-debug-toggle off

Sonuç

Nginx debug loglama, sysadmin hayatını kurtaran ama dikkatli kullanılması gereken güçlü bir araç. Özetlemek gerekirse:

  • --with-debug flag olmadan binary debug log üretmez, önce bunu kontrol et
  • Production’da global debug yerine mutlaka debug_connection ile spesifik IP hedefle
  • Virtual host bazlı debug logları izolasyon ve analiz kolaylığı sağlar
  • Log dosyası büyümesini izle, gerektiğinde truncate et veya rotation kur
  • Upstream sorunları, location eşleşme problemleri ve SSL handshake hataları için debug log birinci tercih olmalı
  • İşin bitince debug modunu kapat, reload etmeyi unutma

Debug log sana Nginx’in iç dünyasını adım adım gösterir. Saatlerce sürebilecek bir sorun tespiti, doğru filtreleme komutlarıyla birkaç dakikaya inebilir. Önemli olan log gürültüsüne boğulmamak ve neye baktığını bilmek.

Bir yanıt yazın

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