Nginx mi Apache mi: Web Sunucusu Seçiminde Doğru Karar
Yıllar önce bir müşterimin sunucusuna baktığımda karşıma çıkan tablo hâlâ aklımda: Apache ile çalışan bir web sunucusu, günde 50.000 istek alan bir e-ticaret sitesi için neredeyse çökmek üzereydi. RAM dolmuş, process’ler birbirini bekliyor, kullanıcılar “sayfa açılmıyor” diye şikayet ediyordu. Nginx’e geçtikten sonra aynı donanımda sorunsuz çalıştı. Ama şunu da söyleyeyim: başka bir projede tam tersini yaşadım. Nginx’te halledemediğim bir .htaccess karmaşasını Apache ile dakikalar içinde çözdüm. Yani bu yazı “Nginx her zaman kazanır” türünden bir yazı değil. Gerçek dünyada doğru aracı seçmekten bahsedeceğiz.
Temel Mimari Fark: Neden Önemli?
Apache ve Nginx arasındaki en kritik fark, istek işleme modellerinde yatıyor. Bu farkı anlamadan hangisini seçeceğinize karar veremezsiniz.
Apache, her gelen bağlantı için yeni bir thread veya process oluşturur (MPM modülüne bağlı olarak). prefork MPM’de her istek için ayrı bir process açılır. worker MPM’de thread’ler kullanılır. Bu model basit ve sağlam, ancak yüksek eş zamanlı bağlantı sayısında bellek tüketimi hızla artar. 10.000 eş zamanlı bağlantı demek, 10.000 thread veya process demek olabilir.
Nginx ise event-driven, non-blocking bir mimariyle çalışır. Az sayıda worker process, binlerce bağlantıyı aynı anda yönetir. Bir bağlantı I/O beklerken worker bloklanmaz, diğer bağlantılara geçer. Bu yüzden yüksek eş zamanlılık senaryolarında Nginx belirgin şekilde öne çıkar.
Ama bu mimarinin bir bedeli var: Nginx, dinamik içerik üretemez. PHP, Python veya Ruby kodunu doğrudan çalıştıramaz; bunları bir upstream servise (PHP-FPM, uWSGI, Puma gibi) yönlendirmesi gerekir. Apache ise mod_php sayesinde PHP’yi kendi içinde çalıştırabilir. Bu durum bazı eski sistemlerde Apache’yi daha pratik kılıyor.
Kurulum ve İlk Yapılandırma
Her ikisini de Ubuntu 22.04 üzerinde kuralım ve temel yapılandırmalarına bakalım.
# Nginx kurulumu
sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
# Apache kurulumu
sudo apt install apache2 -y
sudo systemctl enable apache2
sudo systemctl start apache2
# Her ikisinin çalışıp çalışmadığını kontrol et
curl -I http://localhost
Nginx’in yapılandırma dosyası /etc/nginx/nginx.conf ana dosyasıdır. Ancak pratikte her site için ayrı bir dosya oluşturup /etc/nginx/sites-available/ altına koyarsınız:
# /etc/nginx/sites-available/orneksite.conf
server {
listen 80;
server_name orneksite.com www.orneksite.com;
root /var/www/orneksite;
index index.html index.php;
# Gzip sıkıştırma
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_name;
}
# Statik dosyalar için cache header
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
Apache tarafında ise Virtual Host yapısı kullanılır:
# /etc/apache2/sites-available/orneksite.conf
<VirtualHost *:80>
ServerName orneksite.com
ServerAlias www.orneksite.com
DocumentRoot /var/www/orneksite
<Directory /var/www/orneksite>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Mod_rewrite aktif olmalı
# sudo a2enmod rewrite
ErrorLog ${APACHE_LOG_DIR}/orneksite_error.log
CustomLog ${APACHE_LOG_DIR}/orneksite_access.log combined
</VirtualHost>
# Apache'de siteyi aktifleştirmek
sudo a2ensite orneksite.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
# Nginx'de siteyi aktifleştirmek
sudo ln -s /etc/nginx/sites-available/orneksite.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Performans Senaryoları: Kim Nerede Öne Çıkıyor?
Statik Dosya Servisi
Nginx bu alanda tartışmasız daha iyi. Statik dosyaları doğrudan kernel’ın sendfile() sistemi üzerinden sunar. Bir CDN veya dosya sunucusu kuruyorsanız Nginx’e doğrudan gidin.
# Nginx'de statik dosya sunucusu
# /etc/nginx/sites-available/static-server.conf örneği
server {
listen 80;
server_name static.orneksite.com;
root /var/www/static;
# Sendfile aktif (genellikle nginx.conf'ta global açık gelir)
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Büyük dosyalar için
location /downloads/ {
limit_rate 1m; # Kullanıcı başına 1MB/s
add_header Content-Disposition "attachment";
}
}
Yüksek Eş Zamanlı Bağlantı
Şöyle bir senaryo düşünün: canlı yayın platformu, gerçek zamanlı bildirim sistemi ya da çok kullanıcılı bir uygulama. Nginx’in worker yapısını optimize etmek için:
# /etc/nginx/nginx.conf içindeki kritik parametreler
worker_processes auto; # CPU çekirdeği sayısına göre otomatik
events {
worker_connections 4096; # Her worker için max bağlantı
use epoll; # Linux'ta en verimli I/O modeli
multi_accept on; # Aynı anda birden fazla bağlantı kabul et
}
# Sistemde de dosya limiti ayarlanmalı
# /etc/security/limits.conf'a ekleyin:
# www-data soft nofile 65535
# www-data hard nofile 65535
# Sistem limitlerini kontrol et
ulimit -n
cat /proc/sys/fs/file-max
# Gerekirse artır
echo "fs.file-max = 100000" >> /etc/sysctl.conf
sysctl -p
.htaccess Kullanımı: Apache’nin Avantajı
Birden fazla ekibin veya müşterinin aynı sunucuyu kullandığı shared hosting senaryolarında Apache’nin .htaccess desteği hayat kurtarıcı. Sistem yöneticisine gerek kalmadan uygulama düzeyinde konfigürasyon yapılabilir.
# .htaccess örneği - WordPress için tipik kullanım
Options -Indexes
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# www'suz URL'ye yönlendirme
RewriteCond %{HTTP_HOST} ^www.orneksite.com [NC]
RewriteRule ^(.*)$ https://orneksite.com/$1 [R=301,L]
# HTTPS yönlendirme
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# WordPress pretty URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Nginx’te aynı işlem için sunucu konfigürasyonunu değiştirmeniz gerekir ve her değişiklikten sonra nginx -t && systemctl reload nginx çalıştırmanız şart. Bu shared hosting için kötü bir deneyim, ancak dedicated/VPS ortamları için sorun değil. Hatta Nginx’in .htaccess okumaması bir avantaja dönüşüyor: her istek için dosya sistemi taraması yapmak zorunda kalmıyor.
Reverse Proxy: Nginx’in Parlayan Noktası
Modern uygulama mimarilerinde web sunucusu çoğunlukla bir reverse proxy olarak kullanılır. Node.js, Django, Flask, Spring Boot ne olursa olsun, arkadaki uygulamayı dışarıya Nginx üzerinden açarsınız. Bu senaryoda Nginx gerçekten mükemmel çalışıyor:
# Node.js uygulaması için reverse proxy
upstream nodejs_app {
server 127.0.0.1:3000;
server 127.0.0.1:3001; # Load balancing için ikinci instance
keepalive 32;
}
server {
listen 80;
server_name api.orneksite.com;
location / {
proxy_pass http://nodejs_app;
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_cache_bypass $http_upgrade;
# Timeout değerleri
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Apache da reverse proxy yapabilir ama konfigürasyonu daha uzun ve genellikle daha az performanslı olur. mod_proxy ve mod_proxy_http modülleri aktif edilmeli, sonra benzer bir konfigürasyon yazılmalıdır.
Güvenlik Yapılandırması
İkisinde de güvenlik önemli ama yaklaşım biraz farklı.
# Nginx için temel güvenlik başlıkları
server {
# Nginx sürüm bilgisini gizle
server_tokens off;
# Güvenlik başlıkları
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https:" always;
# Request boyutu limiti (upload koruması)
client_max_body_size 10m;
# Yavaş istek saldırılarına karşı
client_body_timeout 10;
client_header_timeout 10;
# Belirli user-agent'ları engelle
if ($http_user_agent ~* (wget|curl|libwww-perl|python)) {
return 403;
}
}
# Apache için güvenlik yapılandırması
# /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
TraceEnable Off
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Belirli dosyaları gizle
<FilesMatch "(.htaccess|.htpasswd|.git|composer.json)">
Require all denied
</FilesMatch>
SSL/TLS Yapılandırması: Certbot ile Pratik Çözüm
Her iki sunucu için de Certbot kullanımı neredeyse standart hale geldi:
# Certbot kurulumu
sudo apt install certbot python3-certbot-nginx python3-certbot-apache -y
# Nginx için SSL sertifikası al
sudo certbot --nginx -d orneksite.com -d www.orneksite.com
# Apache için SSL sertifikası al
sudo certbot --apache -d orneksite.com -d www.orneksite.com
# Otomatik yenilemeyi test et
sudo certbot renew --dry-run
# Crontab veya systemd timer ile otomatik yenileme
# Certbot genellikle bu timer'ı otomatik oluşturur
systemctl status certbot.timer
Certbot, Nginx konfigürasyonunuzu otomatik düzenler. Bu kulağa iyi gelse de bazen konfigürasyon dosyanızı beklenmedik biçimde değiştirebilir. Ben genellikle sertifikayı Certbot ile alıp SSL yapılandırmasını kendim yazıyorum:
# Manuel SSL yapılandırması - Nginx
server {
listen 443 ssl http2;
server_name orneksite.com;
ssl_certificate /etc/letsencrypt/live/orneksite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/orneksite.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/orneksite.com/chain.pem;
# Modern SSL protokolleri
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
}
Gerçek Dünya Senaryoları: Hangisini Seçmeli?
Teoriden çıkıp pratiğe geçelim. Birkaç tipik senaryo üzerinden konuşalım.
WordPress veya klasik PHP uygulaması, küçük/orta ölçek: Apache burada hâlâ çok mantıklı bir seçim. .htaccess sayesinde WordPress, Drupal, Joomla gibi sistemler kutudan çıkar çıkmaz çalışır. Geliştiriciler sunucuya SSH açmadan permalink ayarlarını değiştirebilir. Ancak sunucu özellikle sınırlıysa (1-2GB RAM, paylaşımlı ortam değil) Nginx + PHP-FPM kombinasyonu belirgin şekilde daha az kaynak tüketir.
Mikroservis mimarisi, API gateway: Nginx tartışmasız kazanır. Upstream tanımlamaları, load balancing, health check, rate limiting özellikleri ile tam bir API gateway işlevi görebilir. Nginx Plus kullanmak zorunda değilsiniz, açık kaynak sürümü bile çoğu senaryo için yeterli.
Shared hosting sağlayıcısıysanız: Apache. Müşterileriniz .htaccess bekler, panel yazılımları (cPanel, Plesk) Apache merkezli çalışır. Nginx kullanan bazı paneller var ama ekosistem hâlâ Apache ağırlıklı.
Yoğun statik içerik, medya sitesi, CDN edge: Nginx. Nokta.
Kurumsal ortam, eski uygulama entegrasyonu: Apache’nin modül ekosistemi daha zengin. mod_auth_kerb, mod_ldap, mod_security gibi modüller kurumsal ihtiyaçlar için Apache’yi cazip kılıyor. Nginx’te bunların alternatifleri var ama olgunluk seviyesi değişiyor.
Yüksek trafikli uygulama, eş zamanlılık kritik: Nginx. Ama burada şunu da hatırlatayım: eğer uygulamanızın kendisi yavaşsa, önünde hangi web sunucusu olduğu fazla fark yaratmaz. Darboğaz genellikle veritabanı veya uygulama katmanındadır.
Nginx ve Apache’yi Birlikte Kullanmak
Bazı ortamlarda ikisini birden kullanmak mantıklı. Nginx önde reverse proxy olarak oturur, arkada Apache uygulamaları yönetir. Bu sayede Nginx’in performansını ve Apache’nin .htaccess esnekliğini birlikte kullanırsınız:
# Nginx önde, Apache arkada
upstream apache_backend {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name orneksite.com;
# Statik dosyaları Nginx doğrudan sunar
location ~* .(jpg|jpeg|png|gif|css|js|ico)$ {
root /var/www/orneksite;
expires 30d;
}
# Dinamik istekleri Apache'ye yönlendir
location / {
proxy_pass http://apache_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Bu hibrit yaklaşım özellikle shared hosting sağlayıcılarında yaygın. cPanel’li sunucularda Apache 8080’de çalışırken önüne Nginx koyulmasi yaygın bir praktiğe dönüştü.
Loglama ve Sorun Giderme
Her iki sunucuda da log analizi hayati önemde.
# Nginx log formatı özelleştirme
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log detailed;
# Gerçek zamanlı log takibi
tail -f /var/log/nginx/error.log | grep -i "error|crit|alert"
# En çok istek alan URL'leri bul
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head 20
# 5xx hataları filtrele
awk '$9 >= 500' /var/log/nginx/access.log | tail -50
# Apache için benzer analiz
grep "error" /var/log/apache2/error.log | tail -50
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head 20
Nginx konfigürasyon testini asla atlamayın:
# Konfigürasyon test ve reload döngüsü
sudo nginx -t && sudo systemctl reload nginx
# Apache için
sudo apache2ctl configtest && sudo systemctl reload apache2
# Hangi portu dinlediklerini kontrol et
ss -tlnp | grep -E "nginx|apache|httpd"
Sonuç
“Nginx mi Apache mi?” sorusunun evrensel bir cevabı yok. Ama şu çerçeveyi kullanabilirsiniz:
- Yeni proje, modern stack, yüksek trafik beklentisi: Nginx ile başlayın. PHP-FPM ile birlikte çalışması mükemmel, reverse proxy yetenekleri güçlü, kaynak tüketimi düşük.
- WordPress ekosistemi, paylaşımlı ortam, geliştirici özerkliği önemli: Apache’nin
.htaccessavantajından yararlanın.
- Kurumsal, eski sistem entegrasyonu: Apache’nin modül ekosistemini araştırın.
- Statik içerik, API gateway, mikroservis önü: Nginx.
- Kararsız kaldınız ve çok trafik var: Nginx önde, Apache arkada hibrit mimariye bakın.
Son olarak şunu söyleyeyim: her iki sunucu da on yıllardır production ortamlarında güvenilir biçimde çalışıyor. Yanlış seçim yapmaktan çok kötü yapılandırma yapmak daha tehlikeli. Hangisini seçerseniz seçin, güvenlik başlıklarını ekleyin, log rotasyonunu ayarlayın, SSL konfigürasyonunuzu test edin ve düzenli güncelleme yapın. Geri kalanı optimize edilebilir.
