Nginx ve PHP-FPM: PHP siteleri Nginx ile nasıl çalışır?
Apache ile çalışan bir sitede PHP çoğunlukla "kendiliğinden" çalışır; çünkü Apache PHP'yi bir modül olarak kendi içinde çalıştırabilir. Nginx'te durum farklıdır: Nginx PHP kodunu çalıştıramaz. Onun yerine isteği, PHP'yi çalıştırmak için ayrı bir servis olarak bekleyen PHP-FPM'e (FastCGI Process Manager) iletir, yanıtı alır ve ziyaretçiye gönderir.
İkisi arasındaki konuşma dili FastCGI adlı protokoldür. Yani ortada iki ayrı yazılım, iki ayrı yapılandırma ve aralarında bir bağlantı vardır. PHP sitelerinde Nginx ile yaşanan sorunların çoğu ("502 Bad Gateway", boş sayfa, PHP dosyasının indirilmesi) bu bağlantının bir ucundaki ayardan kaynaklanır. Bu rehber önce düzenin nasıl işlediğini, sonra adım adım doğru yapılandırmayı anlatır. Nginx'e yeniyseniz önce Nginx nedir rehberine göz atın.
Kısaca
- Nginx PHP çalıştırmaz; .php isteklerini FastCGI ile PHP-FPM'e iletir.
- fastcgi_pass adresi, PHP-FPM havuzundaki listen değeriyle aynı olmalıdır.
- try_files, var olmayan dosyaların PHP'ye gönderilmesini önler.
- Soket yoksa ya da izinleri yanlışsa ziyaretçi 502 görür.
Gerekenler
- Sunucuda yönetici (sudo) yetkisi
- Kurulu Nginx ve PHP-FPM paketi
- Sitenin Nginx yapılandırma dosyası ve yedeği
- Nginx ve PHP-FPM günlüklerine erişim
Not
Bu rehberdeki soket ve dosya yolları örnektir. PHP-FPM'in soket yolu, servis adı ve yapılandırma klasörü dağıtıma ve PHP sürümüne göre değişir; kendi sunucunuzdaki değerleri 2. adımdaki gibi doğrulayın.
Bu sayfada
Adım adım Nginx ve PHP-FPM yapılandırması
-
Akışı anlayın: kim ne yapıyor?
Bir istek geldiğinde iş bölümü şöyledir:
- Statik dosyalar (görsel, CSS, JavaScript): Nginx diskten okur ve doğrudan gönderir; PHP-FPM hiç devreye girmez.
- PHP istekleri: Nginx isteği, hangi dosyanın çalıştırılacağı bilgisiyle birlikte PHP-FPM'e iletir. PHP-FPM, bekleyen işçi süreçlerinden biriyle dosyayı çalıştırır ve çıktıyı Nginx'e geri verir.
Nginx ile PHP-FPM iki yoldan biriyle konuşur:
- Unix soketi: Disk üzerinde özel bir dosyadır (ör.
/run/php/php-fpm.sock). Yalnızca aynı makinedeki süreçler kullanabilir; erişim dosya izinleriyle denetlenir. - TCP adresi:
127.0.0.1:9000gibi bir adres ve bağlantı noktası. PHP-FPM başka bir makinede ya da kapsayıcıda (container) çalışıyorsa bu yol gerekir.
İkisi aynı makinedeyse Unix soketi yaygın tercihtir; hangisini seçerseniz seçin, iki tarafta aynı değer yazmalıdır.
: Büyüt -
PHP-FPM'in çalıştığını ve nerede dinlediğini bulun
Önce PHP-FPM servisinin çalıştığından emin olun, sonra havuz dosyasındaki
listensatırını bulun. Bu satır, Nginx'in bağlanacağı soketi ya da adresi gösterir.Bash# PHP-FPM çalışıyor mu? (servis adı dağıtıma göre değişir) systemctl status php-fpm # RHEL, AlmaLinux ve benzerleri systemctl status 'php*-fpm' # Debian, Ubuntu: adında sürüm bulunur # Havuz hangi soketi ya da adresi dinliyor? sudo grep -R "^listen" /etc/php-fpm.d/ /etc/php/ 2>/dev/null # Soket dosyası var mı, sahibi ve izinleri ne? ls -l /run/php/ /run/php-fpm/ 2>/dev/nullServis adı ve yollar dağıtıma göre değişir: Debian ve Ubuntu'da servis adında ve yollarda PHP sürümü bulunur (ör.
/run/php/altında sürüm numaralı bir soket,/etc/php/<sürüm>/fpm/pool.d/altında havuz dosyaları); RHEL, AlmaLinux ve benzerlerinde servis çoğunluklaphp-fpm, havuz klasörü/etc/php-fpm.d/, soket ise/run/php-fpm/altındadır. Barındırma panelleri kendi yollarını kullanabilir. Tahmin etmeyin;listensatırında ne yazıyorsa onu kullanın. -
server bloğunda PHP isteklerini PHP-FPM'e yönlendirin
Aşağıdaki
serverbloğu PHP ile çalışan bir site için temel düzeni gösterir.Nginxserver { listen 80; server_name ornek.com www.ornek.com; root /var/www/ornek.com/public; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { # Dosya diskte yoksa PHP'ye gönderme try_files $uri =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # Soket yolu dağıtıma göre değişir; havuzdaki "listen" değeriyle aynı olmalı fastcgi_pass unix:/run/php/php-fpm.sock; # TCP ile dinleyen havuz için: fastcgi_pass 127.0.0.1:9000; } }Satır satır anlamı:
index index.php index.html;Bir klasör istendiğinde (ör./) hangi dosyanın aranacağını söyler.index.phplistede yoksa ana sayfa açılmaz ya da 403 döner.location /içindekitry_files: İstenen adres gerçek bir dosya ya da klasörse onu sunar; değilse 404 döndürür.location ~ \.php$: Adresi.phpile biten istekleri yakalar.fastcgi_pass: İsteğin iletileceği PHP-FPM adresi. Unix soketi içinunix:önekiyle yol, TCP için127.0.0.1:9000biçiminde yazılır.
Tüm istekleri tek bir
index.phpdosyasında karşılayan uygulamalarda (çoğu çatı ve hazır içerik yönetim sistemi)location /bloğu biraz farklıdır: dosya bulunamazsa istek 404 yerineindex.php'ye yönlendirilir.Nginx# "location /" bloğunun içi: dosya ya da klasör yoksa isteği index.php'ye ver try_files $uri $uri/ /index.php?$query_string;Bu blok yoksa ana sayfa açılır ama alt sayfalar 404 verir. Apache'de aynı işi
.htaccessiçindeki yeniden yazma kuralları yapar; taşıma için Apache'den Nginx'e geçiş rehberine bakın.
: Büyüt -
fastcgi_params ve SCRIPT_FILENAME'i doğru verin
Nginx, PHP-FPM'e yalnızca "bir istek var" demez; isteğin ayrıntılarını FastCGI parametreleri olarak gönderir: istek yöntemi, sorgu dizgisi, ziyaretçinin IP adresi, sunucu adı ve benzerleri. PHP tarafında bunlar
$_SERVERdizisinde görünür.include fastcgi_params;Nginx ile birlikte gelen ve bu standart parametreleri tanımlayan dosyayı içeri alır.SCRIPT_FILENAMEPHP-FPM'e hangi dosyanın çalıştırılacağını tam yoluyla söyleyen parametredir.$document_root$fastcgi_script_namedeğeri,rootile verdiğiniz klasörü ve istenen dosya adını birleştirir.
fastcgi_paramsdosyası genellikleSCRIPT_FILENAMEsatırını içermez; bu yüzden örnekte ayrıca yazılmıştır. Nginx ile gelenfastcgi.confadlı dosya ise bu satırı da içerir; onu kullanıyorsanız satırı ikinci kez yazmanız gerekmez. Debian ve Ubuntu paketlerinde bu ayarları toplayan hazır bir parça dosya da bulunur. Hangisini kullanırsanız kullanın, parametrenin bir kez ve doğru tanımlandığını denetleyin.SCRIPT_FILENAMEeksik ya da yanlışsa PHP-FPM dosyayı bulamaz: ziyaretçi boş bir sayfa ya da "File not found." yanıtı görür. En sık nedenirootyönergesinin yanlış klasörü göstermesi ya dalocationiçinde farklı birroottanımlanmasıdır. -
Var olmayan dosyaları PHP'ye göndermeyin
Örnekteki PHP bloğunun ilk satırı
try_files $uri =404;bir savunma önlemidir. İstenen.phpdosyası diskte yoksa Nginx isteği PHP-FPM'e hiç iletmez, doğrudan 404 döndürür.Bu neden önemli? Denetim olmadığında, gerçekte var olmayan bir
.phpadresi PHP'ye ulaşır ve PHP'nin yol çözümleme ayarına bağlı olarak başka bir dosya PHP olarak çalıştırılabilir. Sitenizde kullanıcıların dosya yükleyebildiği bir alan varsa bu, yüklenmiş bir dosyanın kod gibi çalıştırılmasına kadar gidebilir. Tek satırlık denetim bu kapıyı kapatır.- Bu denetim, Nginx ile PHP-FPM aynı dosya sistemini gördüğünde çalışır. PHP-FPM ayrı bir makinede ya da kapsayıcıdaysa Nginx dosyayı göremez ve her istek 404 olur; o düzende denetim PHP tarafında yapılmalıdır.
- Ek katman olarak PHP-FPM havuzundaki
security.limit_extensionsayarı, hangi uzantıların PHP olarak çalıştırılabileceğini sınırlar; bu sınırı gevşetmeyin.
-
Havuz (pool) ayarlarını tanıyın
PHP-FPM, işçi süreçlerini havuz (pool) adı verilen gruplar hâlinde yönetir. Her havuzun kendi dinleme adresi, kendi kullanıcısı ve kendi süreç sınırları vardır. Aynı sunucuda birden fazla site varsa her birine ayrı havuz ve ayrı kullanıcı tanımlamak, bir sitedeki sorunun diğerinin dosyalarına ulaşmasını zorlaştırır.
PHP-FPM; Havuz dosyası (ör. www.conf); yolu dağıtıma göre değişir [ornek] user = ornek group = ornek ; Nginx'teki fastcgi_pass ile aynı olmalı listen = /run/php/php-fpm.sock ; Soketin sahibi ve izinleri: Nginx'in kullanıcısı erişebilmeli ; (Debian, Ubuntu: www-data; RHEL, AlmaLinux: nginx) listen.owner = www-data listen.group = www-data listen.mode = 0660 ; Süreç yönetimi (sayılar öneri değil, sözdizimi örneğidir) pm = dynamic pm.max_children = 10 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3Ayar Ne belirler? listenPHP-FPM'in dinlediği soket ya da adres. Nginx'teki fastcgi_passile aynı olmalıdır.user,groupPHP kodunun hangi kullanıcıyla çalışacağı. Dosya okuma ve yazma izinleri bu kullanıcıya göre işler. pmSüreç yönetim kipi: static(sabit sayıda süreç),dynamic(yüke göre alt ve üst sınır arasında) ya daondemand(istek geldikçe başlatılır, boşta kalınca kapatılır).pm.max_childrenAynı anda çalışabilecek işçi süreç sayısının üst sınırı; yani aynı anda işlenebilecek PHP isteği sayısı. pm.max_childreniçin herkese uyan bir sayı yoktur. Her işçi süreç bellek kullanır; sınır çok yüksekse yoğun anda sunucunun belleği tükenir, çok düşükse istekler sırada bekler ve PHP-FPM günlüğünde sınıra ulaşıldığını bildiren bir uyarı görülür. Doğru değer, sunucunun boş belleğine ve uygulamanızın süreç başına kullandığı belleğe bakılarak, ölçülerek bulunur. Örnekteki sayıları öneri olarak değil, sözdizimi örneği olarak okuyun.
: Büyüt -
Soket izinlerini ve 502 hatasını denetleyin
"502 Bad Gateway", Nginx'in arkadaki servisten geçerli bir yanıt alamadığı anlamına gelir. PHP sitelerinde en sık nedeni, Nginx'in PHP-FPM'e bağlanamamasıdır. Nedenini tahmin etmeyin; Nginx hata günlüğü açıkça söyler.
Günlükteki ifade Olası neden Bakılacak yer No such file or directory Soket dosyası yok: PHP-FPM çalışmıyor ya da fastcgi_passyolu yanlış (ör. PHP sürümü yükseltildi, soket adı değişti)Servis durumu; listenilefastcgi_passaynı mı?Permission denied Soket var ama Nginx'in çalıştığı kullanıcının ona erişim izni yok listen.owner,listen.group,listen.modeConnection refused TCP adresinde dinleyen servis yok Servis durumu; adres ve bağlantı noktası Unix soketi bir dosya olduğu için izinleri vardır. Havuzdaki
listen.ownervelisten.groupsoketin sahibini,listen.modeise izinlerini belirler. Nginx işçi süreçlerinin çalıştığı kullanıcı (dağıtıma göre çoğunluklawww-dataya danginx) bu sokete okuma ve yazma izniyle erişebilmelidir. Soketi herkese açmak (0666) sorunu "çözer" ama sunucudaki her kullanıcının PHP-FPM'e istek göndermesine izin verir; bunun yerine sahibi ve grubu doğru ayarlayın.Sayfa bir süre bekledikten sonra hata veriyorsa (504) ya da 502 yalnızca yoğun anlarda görülüyorsa neden bağlantı değil, PHP tarafındaki yavaşlık ya da süreç sınırıdır. Ayrıntılı teşhis için 502 ve 504 hataları rehberine bakın.
: Büyüt -
Yükleme klasöründe PHP çalıştırmayı kapatın
Ziyaretçilerin ya da yöneticilerin dosya yüklediği klasörde (ör.
/upload/) PHP çalışması için hiçbir neden yoktur. Yükleme denetiminizde bir açık olsa bile, o klasördeki dosyalar PHP-FPM'e gönderilmiyorsa yüklenen zararlı bir dosya çalıştırılamaz. Bu, tek başına yeterli olmayan ama etkili bir ikinci savunma hattıdır.Nginx# Genel "location ~ \.php$" bloğundan ÖNCE yazılmalıdır location ~* ^/upload/.*\.(php|phtml|phar)$ { return 403; }İki noktaya dikkat edin: klasör adını kendi sitenize göre değiştirin ve bu bloğu genel
location ~ \.php$bloğundan önce yazın. Nginx, düzenli ifadelilocationbloklarını dosyadaki sırayla dener ve ilk eşleşeni kullanır; sıra tersse kural devreye girmez. Yükleme güvenliğinin bütünü için dosya yükleme güvenliği rehberine bakın.
: Büyüt -
Test edin, yeniden yükleyin, doğrulayın
Değişikliklerden sonra önce yapılandırmayı denetleyin, sonra ilgili servisi yeniden yükleyin. Nginx dosyasını değiştirdiyseniz Nginx'i, havuz dosyasını değiştirdiyseniz PHP-FPM'i yeniden yüklemeniz gerekir.
Bash# Nginx yapılandırmasını denetle ve yeniden yükle sudo nginx -t sudo systemctl reload nginx # Havuz dosyası değiştiyse PHP-FPM'i yeniden yükle (servis adı dağıtıma göre değişir) sudo systemctl reload php-fpm # Sorun varsa son hata kayıtlarına bak sudo tail -n 50 /var/log/nginx/error.logArdından tarayıcıdan sınayın: ana sayfa açılıyor mu, bir alt sayfa açılıyor mu, var olmayan bir
.phpadresi 404 veriyor mu, yükleme klasöründeki bir.phpadresi 403 veriyor mu? Bir PHP dosyası çalışmak yerine indiriliyorsa ya da kaynak kodu ekranda görünüyorsa, istek PHP bloğuna hiç ulaşmıyordur:location ~ \.php$bloğunun doğruserveriçinde olduğunu ve yeniden yükleme yapıldığını denetleyin.
Sık görülen belirtiler ve nedenleri
| Belirti | Olası neden |
|---|---|
| 502 Bad Gateway | PHP-FPM çalışmıyor, soket yolu yanlış ya da soket izinleri Nginx'e erişim vermiyor |
| Boş sayfa ya da "File not found." | SCRIPT_FILENAME eksik ya da yanlış; root yanlış klasörü gösteriyor |
| PHP dosyası indiriliyor | PHP için location bloğu yok ya da istek başka bir bloğa düşüyor |
| Ana sayfa açılıyor, alt sayfalar 404 | Ön denetleyici (index.php) için try_files yönlendirmesi eksik |
| Ana sayfada 403 | index yönergesinde index.php yok ya da klasör izinleri Nginx'in okumasına izin vermiyor |
| Dosya yüklerken 413 | Nginx'in istek gövdesi sınırı (client_max_body_size, varsayılanı 1m) aşılıyor; PHP'nin kendi yükleme sınırları da ayrıca geçerlidir |
Her durumda ilk bakılacak yer günlüklerdir: Nginx hata günlüğü (çoğunlukla /var/log/nginx/error.log) ve PHP-FPM günlüğü. Konumları yapılandırmaya göre değişebilir.
Güvenlik için kısa kontrol listesi
- PHP bloğunda
try_files $uri =404;var; var olmayan dosyalar PHP'ye gitmiyor. - Yükleme klasörlerinde PHP çalıştırma kapalı.
- Soket izinleri dar: yalnızca Nginx'in kullanıcısı ya da grubu erişebiliyor.
- PHP-FPM TCP ile dinliyorsa yalnızca
127.0.0.1ya da iç ağ adresinde dinliyor; internete açık değil. - Her site kendi havuzunda ve kendi kullanıcısıyla çalışıyor; PHP süreçleri yönetici (root) olarak çalışmıyor.
- PHP kullanıcısı yalnızca gereken klasörlere yazabiliyor.
- Hata ayrıntıları ziyaretçiye değil günlüğe yazılıyor.
Sunucunun geneli için Nginx güvenlik ayarları ve sunucu ve barındırma güvenliği rehberlerine bakın.
Sık sorulan sorular
Nginx'te PHP dosyası çalışmak yerine indiriliyor, neden?
İstek PHP-FPM'e iletilmiyor demektir. Sitenin server bloğunda .php uzantısını yakalayan bir location bloğu ve içinde fastcgi_pass bulunmalıdır. Blok varsa doğru server içinde olduğunu, yapılandırmanın test edilip yeniden yüklendiğini ve tarayıcının eski yanıtı önbellekten göstermediğini denetleyin.
Unix soketi mi, 127.0.0.1:9000 mi kullanmalıyım?
Nginx ve PHP-FPM aynı makinedeyse Unix soketi yaygın tercihtir; ağ bağlantı noktası açmaz ve erişim dosya izinleriyle denetlenir. PHP-FPM ayrı bir makinede ya da kapsayıcıda çalışıyorsa TCP gerekir. Hangisini seçerseniz seçin fastcgi_pass ile havuzdaki listen aynı olmalıdır.
PHP sürümünü yükselttim, site 502 vermeye başladı. Neden?
Bazı dağıtımlarda soket dosyasının ve servisin adında PHP sürümü bulunur. Sürüm değişince soket yolu da değişir, Nginx ise eski yola bağlanmaya çalışır. Yeni havuz dosyasındaki listen değerini bulun, fastcgi_pass satırını ona göre güncelleyin, test edip yeniden yükleyin.
pm.max_children kaç olmalı?
Herkese uyan bir değer yoktur. Sunucunun kullanılabilir belleğine ve uygulamanızın süreç başına kullandığı belleğe bağlıdır. Çok yüksek değer belleği tüketir, çok düşük değer istekleri bekletir. Kendi sunucunuzda ölçerek ve PHP-FPM günlüğündeki uyarılara bakarak ayarlayın.
Apache'deki .htaccess kurallarım PHP-FPM ile çalışır mı?
Hayır. .htaccess Apache'ye özgüdür; ne Nginx ne de PHP-FPM bu dosyayı okur. Yönlendirme, erişim kısıtı ve adres yeniden yazma kurallarının Nginx yapılandırmasına taşınması gerekir.
BYK Yazılım Destek Ekibi
Bu rehber BYK Yazılım destek ekibi tarafından hazırlanır ve düzenli olarak gözden geçirilir. Son güncelleme: 04.10.2026.
İlgili rehberler
- Nginx nedir, ne işe yarar?Nginx'in rolleri, olay tabanlı mimarisi, Apache ile farkı, yapılandırma blokları ve temel komutlar.
- 502, 504 ve diğer Nginx hataları: nedenleri ve çözümleri502, 504, 413, 499, 403 ve 404 hatalarının anlamı, olası nedenleri, günlüklerle teşhisi ve çözümü.
- Apache ve .htaccess'ten Nginx'e geçiş.htaccess kurallarını Nginx yapılandırmasına taşımak için yan yana örnekler, karşılık tablosu ve test listesi.
- Dosya yükleme güvenliği ve web shellGüvenli yükleme kuralları, yükleme klasöründe yürütmeyi kapatma, web shell belirtileri ve bulununca yapılacaklar.
Web sitenizin altyapısını birlikte konuşalım
BYK Yazılım kurumsal web siteleri geliştirir. Sitenizle ilgili sorularınız için bize yazabilirsiniz.
Bize ulaşın Kurumsal web sitesi hizmetimiz