nginx nedir ve üstlendiği beş iş
nginx ("engine-x" diye okunur) açık kaynaklı bir HTTP sunucusu ve proxy'dir. Igor Sysoev onu, çoğu sunucunun bu yük altında çöktüğü bir dönemde tek makinede on bin eşzamanlı bağlantıyı açık tutabilmek için yazdı ve 2004'te yayımladı. Bugün Apache ile birlikte en yaygın kullanılan iki web sunucusundan biridir; pek çok load balancer'ın, Kubernetes ingress controller'ın ve CDN'in içindeki motor da odur. Açık kaynak sürümü nginx.org'dadır; arkasındaki şirketi 2019'da satın alan F5, NGINX Plus adlı ticari bir sürüm satar.
Ad beş rolü kapsar ve tek bir yapılandırma hepsini birleştirebilir:
Web sunucusu. Diskteki dosyaları okuyup gönderir: HTML, CSS, JavaScript, görseller, indirmeler. En hızlı yaptığı iş budur; kopyalamayı sendfile ile çekirdeğe bırakır.
Reverse proxy. İsteği kabul eder ve internete doğrudan açılmaması gereken bir uygulamaya iletir: PHP-FPM, Node.js, Python, Go, Java, bir container. İletilmesi gereken başlıklar dahil konunun tamamı reverse proxy rehberimizde.
Load balancer. İstekleri o uygulamanın birkaç kopyasına dağıtır ve arızalanan kopyaya trafik göndermeyi bırakır.
Önbellek. Upstream yanıtlarını diskte saklar ve tekrarlanan isteklere uygulamaya yeniden sormadan cevap verir.
TLS sonlandırıcı. Sertifikaları tutar, tarayıcıyla HTTPS, HTTP/2 ve HTTP/3 konuşur, özel bir adresteki uygulamayla düz HTTP konuşur.
Ne olmadığı: bir uygulama sunucusu. nginx PHP, Python ya da Ruby kodunuzu çalıştırmaz. Bu istekleri onları çalıştıran bir sürece verir ve cevabı geri gönderir.
Olay güdümlü mimari: nginx neden bu kadar çok bağlantı tutar
nginx başladığında bir master süreci yapılandırmayı okur, dinlenecek portları açar ve genellikle CPU çekirdeği başına bir tane olmak üzere birkaç worker süreci başlatır (worker_processes auto). Master hiçbir zaman trafik sunmaz. Worker'ları yönetir ve reload'u kesintisiz yapan odur.
Her worker tek thread'lidir ve bir olay döngüsü çalıştırır. Linux'ta epoll, BSD ve macOS'ta kqueue üzerinden çekirdeğe, bağlantılarından hangisinde hazır bir şey olduğunu sorar: yeni bir istek, daha fazla bayt alabilecek bir istemci, cevap vermiş bir upstream. Hazır olan her bağlantıda kısa bir iş yapar ve geçer; hiçbir şey beklemede oturmaz. İstekler arasında boşta duran bir keep-alive bağlantı ya da isteğini damla damla gönderen yavaş bir mobil istemci, worker'a birkaç kilobayt belleğe mal olur, CPU'ya değil.
Apache'nin klasik modeli bunun tersidir. prefork MPM her bağlantıya kendi sürecini, worker MPM kendi thread'ini verir; o süreç ya da thread, meşgul de olsa boşta da olsa bağlantı sürdükçe bağlı kalır. On bin açık keep-alive bağlantı, getirdiği bellek ve context switch yüküyle on bin süreç ya da thread demektir. Apache'nin daha yeni event MPM'i boşta bekleyen keep-alive bağlantıları bir listener thread'e bırakır ve aradaki farkı daraltır, ama her aktif istek yine bir thread tutar.
Buradan çıkan kural: bir worker asla bloklanmamalıdır. Gerçekten zaman alan işler, PHP çalıştırmak ya da veritabanı sorgulamak gibi, başka bir süreçte yapılır ve nginx cevabı bir olay daha olarak ele alır. Kapasite hesabı worker_processes × worker_connections'tır; nginx proxy yaparken her istemci bu yuvalardan ikisini kullanır: biri tarayıcıya, biri upstream'e.
nginx.conf'un başı: bir master, çekirdek başına bir worker, her birinde bir olay döngüsü
user www-data;
worker_processes auto; # one worker per CPU core
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024; # per worker: clients + upstream connections
}
http {
include mime.types;
sendfile on;
keepalive_timeout 65s;
include /etc/nginx/conf.d/*.conf; # one file per site
}
nginx ne işe yarar
Pratikte nginx şu konumlardan birinde, çoğu zaman aynı anda birkaçında durur.
Statik bir siteyi ya da front-end build'ini sunmak. Bir React, Vue ya da Astro build'i, dokümantasyon, bir açılış sayfası: diskte dosyalar ve önünde nginx, başka bir şey yok.
PHP'nin önünde. WordPress, Laravel ve çoğu PHP uygulaması nginx ile PHP-FPM ikilisiyle çalışır. nginx görselleri, CSS'i ve JavaScript'i kendisi sunar, .php isteklerini ise fastcgi_pass ile bir Unix soketi üzerinden FPM'e iletir.
Bir uygulama sunucusunun önünde. Node.js, Python (Gunicorn, Uvicorn), Ruby (Puma) ve Go servisleri yerel bir portu dinler. nginx HTTPS'i sonlandırır, isteği tamponlayarak yavaş istemcileri karşılar, sonra proxy_pass ile iletir; böylece uygulama yalnızca hızlı ve tamamlanmış istekler görür.
Load balancing: birkaç uygulama kopyası arasında dağıtım; aşağıda kısaca anlatılıyor.
Hiçbiri olmayan bir uygulama için TLS ve modern protokoller: sertifikalar (çoğu kişi bunları certbot ve Let's Encrypt ile alır), nginx 1.25 ve sonrasında http2 on; ile HTTP/2 ve listen 443 quic; ile HTTP/3. Protokollerin neyi değiştirdiği HTTP/2 ve HTTP/3 rehberinde.
Kapıdaki kurallar: yönlendirmeler, limit_req ile rate limiting, IP izin ve engel listeleri, gzip sıkıştırma ve yanıt başlıkları. Hangi başlıkların neden gönderileceği HTTP güvenlik başlıkları rehberinde.
Satır satır en küçük server bloğu
Bir server bloğu bir sitedir. nginx onu isteğin geldiği porta ve server_name ile karşılaştırdığı Host başlığına göre seçer. İçindeki location blokları URL yollarıyla eşleşir. Aşağıdaki blok statik bir site sunar ve /api/'yi 3000 portundaki bir uygulamaya iletir.
listen porttur; bir kez IPv4, bir kez IPv6 için.
server_name bu bloğun cevap verdiği host adlarını listeler. Host'u hiçbir blokla eşleşmeyen bir istek, o portun default server'ına gider: default_server ile işaretlenmiş blok, yoksa nginx'in okuduğu ilk blok. IP'nize yönlendirilmiş bilinmeyen bir host adının başka bir siteyi göstermesinin nedeni budur. return 444; (bağlantıyı kapat) diyen bir catch-all blok bunu durdurur.
root dosyaların arandığı yerdir: /about.html, /var/www/example/about.html olur.
try_files önce dosyayı, sonra dizini, sonra son çareyi dener. Tek sayfalık bir uygulamada (SPA), istemci tarafı rotalar uygulamayı yüklesin diye =404 yerine /index.html yazın.
location eşleşmesinin insanları şaşırtan bir sırası vardır. Tam eşleşme (=) doğrudan kazanır. Aksi halde nginx en uzun eşleşen öneki aklında tutar, sonra düzenli ifadeleri (~, ~*) dosyadaki sırayla dener ve eşleşen ilkini alır; hiçbiri eşleşmezse aklında tuttuğu öneki kullanır. ^~ öneki regex adımını atlar. Bu örnekte /api/logo.png, /api/ tarafından değil görsel regex'i tarafından sunulur; "location'ım neden yok sayılıyor" sorusunun olağan cevabı budur.
expires, parmak izli (fingerprinted) dosyalara Cache-Control: max-age ve Expires ekler. Değerleri Cache-Control rehberiyle seçin.
Bu blok düz HTTP'dir. Sertifikayı bloğu sizin için düzenleyen certbot ile ekleyin ve 80 portunu 443'e yönlendirin.
/etc/nginx/conf.d/example.conf: arkasında API olan statik bir site
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(?:css|js|woff2|png|jpg|webp|avif|svg)$ {
expires 30d;
access_log off;
}
location /api/ {
proxy_pass http://127.0.0.1:3000;
# plus the forwarded headers from the reverse proxy guide
}
}
Kurulum, test, reload: her gün kullanılan komutlar
Dağıtım paketleri ana dosyayı /etc/nginx/nginx.conf'a koyar. Debian ve Ubuntu siteleri /etc/nginx/sites-available/ içinde tutar ve sites-enabled/ içine bir symlink ile etkinleştirir; RHEL, Rocky, Alpine ve nginx.org paketleri /etc/nginx/conf.d/*.conf'u okur. Loglar /var/log/nginx/'e gider.
İki alışkanlık, kendi elinizle yarattığınız kesintilerin çoğunu önler. Her reload'dan önce nginx -t çalıştırın: tüm yapılandırmayı ayrıştırır ve her hatanın dosyasını ve satırını söyler. Ve restart yerine reload yapın. Reload'da master yeni yapılandırmayla yeni worker'lar başlatır ve eskilerin açık isteklerini bitirmesine izin verir; hiçbir bağlantı kopmaz. Yeni yapılandırma yüklenmezse master eski worker'ları çalışır halde tutar ve nedenini loglar.
nginx -T, nginx'in gördüğü haliyle, her include açılmış olarak yapılandırmanın tamamını yazdırır. Bir ayar etkisiz görünüyorsa genellikle unuttuğunuz bir dosyada ezilmiştir; -T hangisi olduğunu gösterir.
# Debian / Ubuntu
sudo apt install nginx
nginx -v # version; -V adds build options and modules
# check the syntax, then apply without dropping connections
sudo nginx -t && sudo systemctl reload nginx
# the whole effective configuration, includes expanded
sudo nginx -T | less
# which names and ports are configured
sudo nginx -T | grep -E '^\s*(server_name|listen)'
# watch errors while you test
sudo tail -f /var/log/nginx/error.log
nginx ve Apache karşılaştırması
İkisi de olgun, ücretsiz ve neredeyse her site için yeterince hızlı. Aralarında gerçekten karar verdiren farklar:
Bağlantı modeli. nginx'in olay döngüsü boşta ve yavaş bağlantıları neredeyse bedavaya tutar; Apache her aktif isteğe, event MPM dışında her boşta bağlantıya da bir süreç ya da thread bağlar. Çok sayıda eşzamanlı keep-alive bağlantıda nginx çok daha az bellek kullanır.
Yapılandırma. AllowOverride açıkken Apache her istekte yol üzerindeki her dizinden .htaccess dosyalarını okur; böylece bir kullanıcı sunucu yapılandırmasına dokunmadan kuralları değiştirebilir. nginx'te bunun karşılığı yoktur: her kural merkezi yapılandırmada durur ve yüklenirken bir kez ayrıştırılır. Bu daha hızlı ve denetlemesi daha kolaydır, ama taşınırken bir WordPress ya da Laravel .htaccess'inin location ve try_files kuralları olarak yeniden yazılması gerekir.
PHP. Apache PHP'yi mod_php ile kendi süreçleri içinde çalıştırabilir; nginx her zaman ayrı bir PHP-FPM havuzuyla konuşur. Güncel Apache kurulumları da çoğu zaman PHP-FPM kullanır, yani bu artık çoğunlukla varsayılanlardaki bir farktır.
Modüller. Apache modülleri çalışma anında çok geniş bir katalogdan yükler. nginx dinamik modülleri destekler, ama her biri çalıştırdığınız nginx sürümüne karşı derlenmek zorundadır; çok sayıda ek, derleme demektir.
Statik dosyalar ve proxy, nginx'in en güçlü olduğu alandır. Bu yüzden yaygın bir hibrit kurulum, dosyaları sunan ve TLS'i sonlandıran nginx'i öne, .htaccess'e bağımlı bir uygulamayı çalıştıran Apache'yi arkaya koyar.
Dürüst özet: sıfırdan başlıyorsanız çoğu ekip için varsayılan tercih nginx'tir. Ama çalışan bir Apache'yi değiştirmek yavaş bir siteyi hızlandırmaz. Yavaş olan kısım neredeyse her zaman uygulama ya da ziyaretçiye olan mesafedir, web sunucusu değil.
Reverse proxy, load balancer ve önbellek: kısa hali
Proxy tek bir direktiftir, proxy_pass; artı uygulamaya istemcinin gerçekte kim olduğunu söyleyen başlıklar. Bu başlıklar, WebSocket desteği ve proxy_cache reverse proxy rehberinde anlatılıyor; bu sayfa onları tekrarlamıyor.
Load balancing, sunucuları adlandıran bir upstream bloğu ekler. Varsayılan round robin'dir. least_conn her isteği en az aktif bağlantısı olan sunucuya gönderir, bu da süreleri farklı istekler için uygundur; ip_hash ya da hash bir istemciyi aynı sunucuda tutar. Açık kaynak nginx'te sağlık kontrolü pasiftir: fail_timeout içinde max_fails kadar hatadan sonra bir sunucu o süre boyunca atlanır ve proxy_next_upstream isteği bir başkasında yeniden dener. Bir URL'i düzenli aralıklarla yoklayan aktif kontroller NGINX Plus özelliğidir. Daha geniş resim için load balancer'ın ne yaptığına bakın.
Önbellekleme iyi çalışır, baştan bilinmesi gereken tek bir eksikle: açık kaynak nginx'te önbellekteki bir URL'i purge edecek bir komut yoktur. Kaydın süresinin dolmasını beklersiniz ya da her sunucuda önbellek dizininden dosyaları silersiniz. Bu eksik, ekiplerin herkese açık önbelleği bir CDN'e taşımasının en yaygın nedenlerinden biridir.
Tek bir nginx arkasında üç uygulama sunucusu
upstream app {
least_conn;
server 10.0.0.11:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.12:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.13:3000 backup; # used only when the others are down
keepalive 32; # reuse connections to the app
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Connection ""; # required for upstream keepalive
proxy_next_upstream error timeout http_502;
# plus the forwarded headers from the reverse proxy guide
}
}
502, 504 ve 413: nginx size ne söylüyor
Ziyaretçinin gördüğü durum kodu özettir; açıklama error log'dadır. Bu hataların her biri orada kendine özgü bir satır bırakır.
502 Bad Gateway, nginx'in upstream'den kullanılabilir bir cevap alamadığı anlamına gelir. connect() failed (111: Connection refused), proxy_pass'taki adreste hiçbir şeyin dinlemediğini söyler: uygulama kapalıdır ya da başka bir porttadır. connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory), kurulu PHP sürümüyle eşleşmeyen bir PHP-FPM soket yoludur; aynı satırdaki (13: Permission denied) ise nginx kullanıcısının açamadığı bir sokettir. upstream prematurely closed connection, uygulamanın istek ortasında çöktüğü ya da öldürüldüğü anlamına gelir; uygulamanın kendi logunu ve çekirdeğin out-of-memory mesajlarını okuyun. upstream sent too big header, yanıt başlıklarının, çoğu zaman bir yığın çerezin, tampona sığmadığı anlamına gelir: proxy_buffer_size'ı, PHP için fastcgi_buffer_size'ı büyütün. Önde bir CDN olduğu durum dahil tam teşhis 502 Bad Gateway rehberinde.
504 Gateway Timeout, upstream'in isteği kabul ettiği ama varsayılanı 60 saniye olan proxy_read_timeout (ya da fastcgi_read_timeout) içinde cevap vermediği anlamına gelir. Log upstream timed out (110: Connection timed out) while reading response header from upstream der. Yavaş olduğu bilinen bir dışa aktarma ya da rapor için daha uzun bir timeout doğrudur; sıradan sayfalarda yalnızca yavaş bir sorguyu ya da dolmuş bir worker havuzunu gizler. Zincirdeki her proxy'nin kendi sınırı vardır; öndeki bir load balancer ya da CDN, nginx'ten önce vazgeçebilir.
413 Request Entity Too Large, istek gövdesinin varsayılanı 1 MB olan client_max_body_size'tan büyük olduğu anlamına gelir: klasik başarısız görsel ya da yedek yüklemesi. Log client intended to send too large body der. Sınırı global olarak değil, yüklemeleri alan server ya da location içinde büyütün; PHP için upload_max_filesize ve post_max_size'ı da buna göre artırın, yoksa nginx'in geçirdiğini PHP reddeder.
nginx'ten gelen bir 503 genellikle kendi limit_req ya da limit_conn kuralının bir isteği geri çevirmesidir; bu ve diğer nedenler 503 Service Unavailable rehberinde. directory index of "/var/www/..." is forbidden ise index dosyası olmayan bir dizin için verilen 403'tür; 403 Forbidden rehberinde anlatılıyor.
Error log satırları ve her birinin işaret ettiği direktif
# /var/log/nginx/error.log (abridged)
connect() failed (111: Connection refused) while connecting to upstream -> 502
upstream prematurely closed connection while reading response header -> 502
upstream sent too big header while reading response header from upstream -> 502
upstream timed out (110: Connection timed out) while reading response header -> 504
client intended to send too large body: 52428800 bytes -> 413
# the matching fixes, in the server or location that needs them
client_max_body_size 64m; # PHP: raise upload_max_filesize and post_max_size too
proxy_read_timeout 300s; # only for a known slow endpoint
proxy_buffer_size 16k; # large response headers and cookies
proxy_buffers 8 16k;
nginx'in önüne ne zaman CDN konmalı
Tek bir nginx çok trafik sunar. Değiştiremediği şey bulunduğu yerdir. Başka bir ülkedeki ziyaretçi, tek veri merkezinize yapılan her gidiş-dönüşü bekler; çoğu tekrarlanan isteklerden oluşan bir trafik sıçraması yine tek makinenize iner; IP'nizi hedef alan bir saldırı sitenizi çalıştıran sunucuya ulaşır. CDN eklemenin zamanı bu anlardır: kitleniz sunucudan uzaktadır, önbelleğe alınabilir trafik yükün büyük bir kısmıdır, birden fazla makinede önbellek purge'üne ihtiyacınız vardır ya da origin'e artık doğrudan erişilememesi gerekir.
nginx'i tutarsınız; işi değişir. CDN herkese açık ön kapı olur, nginx de origin olur: edge mesafeyi, önbelleği ve filtrelemeyi üstlenirken nginx dosyaları sunar ve istekleri uygulamaya yönlendirir. nginx tarafında ayarlanacak üç şey var. Doğru Cache-Control başlıkları gönderin, çünkü edge onlara uyar. Ziyaretçinin IP'sini realip modülüyle geri kazanın (CDN'in adresleri için set_real_ip_from, gönderdiği başlık için real_ip_header); yoksa her log satırı ve her limit_req bölgesi ziyaretçi yerine edge'i görür. Ve origin'e yalnızca CDN'in erişmesine izin verin ki saldırılar onun etrafından dolaşamasın.
CDN.com.tr edge'i de nginx üzerinde çalışır: yapılandırması paketinizdeki dosya boyutunu client_max_body_size olarak uygular; bu yüzden CDN'den geçen bir yüklemede hem bu sınırın hem de kendi sınırınızın yeterince büyük olması gerekir. Origin'inizin önünde, Türkiye'de ve yurt dışında sunucuları olan edge ağı, yol bazındaki dağıtım kurallarına göre önbelleğe alır ve panelden, cdnctl komut satırından ya da REST API'den tam yol ya da klasör bazında anında purge eder. WAF, DDoS koruması, JavaScript challenge'lı bot koruması, ülke ve IP kuralları ve rate limiting, istek sunucunuza ulaşmadan önce çalışır; bağlı her alan adı için Let's Encrypt sertifikaları çıkarılır ve yenilenir.
İki ayrıntı geçişi doğrulamayı kolaylaştırır. Edge önbelleğinde olan sayfalar origin'iniz kapalıyken de sunulmaya devam eder ve X-Proxy-Cache-MT yanıt başlığı HIT ya da MISS gösterir; böylece bir isteğin nginx'inize hiç ulaşıp ulaşmadığını anlayabilirsiniz. Edge origin'e SNI da gönderir; birden fazla HTTPS server bloğu olan bir nginx doğru sertifikayı sunar.
nginx hakkında sık sorulanlar
nginx nasıl okunur?
"Engine-x" diye. Hem nginx hem NGINX kullanılır; küçük harfli yazım açık kaynak projenin ve binary'sinin adıdır.
nginx ücretsiz mi?
nginx.org'daki açık kaynak nginx, iki maddeli BSD lisansıyla ticari kullanım dahil ücretsizdir. NGINX Plus, F5'in ücretli aboneliğidir; aktif sağlık kontrolleri, önbelleği purge etmek ve upstream'leri çalışma anında değiştirmek için bir API, canlı durum paneli ve destek ekler.
nginx web sunucusu mu, reverse proxy mi?
İkisi de, çoğu zaman aynı yapılandırmada. root içeren bir location diskten dosya sunar, proxy_pass ya da fastcgi_pass içeren bir diğeri isteği bir uygulamaya verir. Çoğu site ikisini birden yapar: statik dosyalar doğrudan, dinamik her şey proxy üzerinden.
nginx Apache'den daha mı iyi?
Statik dosyalar, proxy ve çok sayıda eşzamanlı bağlantı için daha az bellek kullanır ve yeni kurulumlarda olağan tercihtir. .htaccess'e ya da yalnızca Apache'de olan bir modüle bağımlıysanız Apache daha uygundur. Tipik bir sitede darboğaz iki web sunucusu da değildir; uygulama ve ziyaretçilere olan mesafedir.
Alan adım nginx'te neden başka bir siteyi gösteriyor?
İsteğin Host başlığıyla hiçbir server_name eşleşmedi; nginx de o portun default server'ını kullandı: default_server ile işaretlenmiş blok ya da yüklediği ilk blok. Adları nginx -T | grep server_name ile kontrol edin ve bilinmeyen host adları hiçbir şey almasın diye 444 döndüren bir catch-all blok ekleyin.
CDN kullanıyorsam nginx'e hâlâ ihtiyacım var mı?
Genellikle evet, origin olarak: dosyaları sunacak ve istekleri uygulamanıza yönlendirecek bir şey yine gerekir ve CDN içeriği oradan çeker. CDN.com.tr container uygulamalarında yayın için onu atlayabilirsiniz, çünkü edge her uygulamaya arada reverse proxy container'ı olmadan platformun iç rotası üzerinden ulaşır.