Merhaba arkadaşlar, bugün sizlere Nginx konfigürasyonlarında sıkça karşılaştığımız, özellikle modern PHP uygulamaları (Laravel, Symfony, WordPress vb.) çalıştırırken hayati öneme sahip olan `try_files` direktifini ve onunla birlikte "Front Controller Pattern"i nasıl kullanarak temiz, anlaşılır URL'ler oluşturacağımızı anlatacağım. Bu yöntem, sunucunuzdaki tüm istekleri tek bir giriş noktasına (genellikle index.php) yönlendirerek, uygulamanızın routing (yönlendirme) mantığını daha güvenli ve kontrollü hale getirir.
Neden try_files ve Front Controller Kullanmalıyız?
Öncelikle sorunu tanıyalım. Statik bir `about.html` dosyanız varsa, Nginx doğrudan onu sunar. Ancak dinamik bir PHP uygulamanızda `/iletisim` gibi bir URL'niz varsa, Nginx sunucusunda böyle bir dosya yoktur. İşte bu noktada `try_files` devreye girer. Bu direktif, Nginx'e "Şu dosyaları sırayla dene, eğer hiçbiri yoksa son olarak şu işlemi yap" talimatını verir. Front Controller Pattern ise, tüm HTTP isteklerinin önce tek bir kontrolcü dosyaya (front controller) gelmesi ve routing işleminin bu dosya içinden uygulama seviyesinde yapılmasıdır. Bu sayede:
Temiz URL'ler (SEO-Friendly): `site.com/index.php?sayfa=urunler` yerine `site.com/urunler` kullanabilirsiniz.
Merkezi Kontrol: Tüm istekler tek noktadan geçtiği için güvenlik ve loglama daha kolaydır.
Dosya Erişim Güvenliği: Gerçek dosya yolları gizlenir, uygulama mantığı dışındaki dosyalara doğrudan erişim engellenebilir.
Temel try_files Kullanımı ve Syntax'ı
`try_files` direktifinin genel yapısı şöyledir. Sunucu, listedeki dosyaları soldan sağa doğru kontrol eder. İlk bulduğunu sunar. Hiçbirini bulamazsa, son parametrede belirtilen işlemi (fallback) yapar.
`$uri`: İstenen dosya yolunu (ör: /css/style.css) arar.
`$uri/`: Eğer istenen bir dizinse, o dizini arar (ör: index.html veya index.php dosyası için).
`/index.php?$query_string`: Yukarıdakilerin hiçbiri bulunamazsa, isteği `index.php` dosyasına, orijinal sorgu parametreleriyle birlikte yönlendirir.
Front Controller Pattern için Örnek Nginx Konfigürasyonu
Şimdi gelelim pratik uygulamaya. Diyelim ki bir Laravel veya benzeri bir uygulamanız var ve tüm isteklerin `public/index.php` dosyasına gitmesini istiyorsunuz. Aşağıdaki gibi bir `server` bloğu oluşturabilirsiniz. Bu, benim de sıkça kullandığım standart bir yapıdır.
Bu konfigürasyonda dikkat etmeniz gereken en önemli nokta root direktifinin, uygulamanızın "public" dizinine işaret etmesi. Ayrıca `fastcgi_param SCRIPT_FILENAME` değişkeninde `$realpath_root` kullanmak, sembolik link kullandığınız durumlarda bile doğru dosya yolunun iletilmesini sağlar.
Dikkat Edilmesi Gerekenler ve Sık Yapılan Hatalar
Root Dizin Hatası: En sık karşılaştığım hata, `root` yolunun yanlış verilmesi. Emin değilseniz, `root` dizininizde `index.html` gibi bir test dosyası oluşturup tarayıcıdan erişmeyi deneyin.
PHP-FPM Socket/Port: `fastcgi_pass` değeri sisteminizdeki PHP-FPM yapılandırmasına uygun olmalı. Socket yolu farklı olabilir veya `127.0.0.1:9000` gibi bir port kullanıyor olabilirsiniz. Kontrol etmek için `ls -la /var/run/php/` komutunu kullanabilirsiniz.
try_files Döngüsü: `try_files` içinde son fallback olarak yine aynı `location`'ı işaret ederseniz sonsuz döngüye girip 500 hatası alırsınız. Fallback her zaman net bir dosya veya named location olmalıdır.
Statik Dosya Performansı: CSS, JS, resim gibi statik dosyalar için ayrı bir `location` bloğu eklemek performansı artırır. Örneğin:
Sonuç ve Öneriler
`try_files` direktifi, Nginx'in en güçlü ve esnek özelliklerinden biridir. Front Controller Pattern ile birlikte kullanıldığında, hem geliştirici deneyimini iyileştirir hem de son kullanıcıya daha temiz bir URL yapısı sunar. Bu konfigürasyon, Laravel, Symfony, CodeIgniter gibi çoğu modern framework için hazır halde çalışacaktır.
Ben genellikle yeni bir sunucu hazırlarken bu template'i kullanıyorum ve ihtiyaca göre `location` bloklarını genişletiyorum. Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı bir yaklaşımınız veya eklemek istediğiniz püf noktalar var mı? Aşağıya yorumlarınızı bekliyorum. Takıldığınız bir nokta olursa, yardımcı olmaya çalışırım.
Öncelikle sorunu tanıyalım. Statik bir `about.html` dosyanız varsa, Nginx doğrudan onu sunar. Ancak dinamik bir PHP uygulamanızda `/iletisim` gibi bir URL'niz varsa, Nginx sunucusunda böyle bir dosya yoktur. İşte bu noktada `try_files` devreye girer. Bu direktif, Nginx'e "Şu dosyaları sırayla dene, eğer hiçbiri yoksa son olarak şu işlemi yap" talimatını verir. Front Controller Pattern ise, tüm HTTP isteklerinin önce tek bir kontrolcü dosyaya (front controller) gelmesi ve routing işleminin bu dosya içinden uygulama seviyesinde yapılmasıdır. Bu sayede:
Temiz URL'ler (SEO-Friendly): `site.com/index.php?sayfa=urunler` yerine `site.com/urunler` kullanabilirsiniz.
Merkezi Kontrol: Tüm istekler tek noktadan geçtiği için güvenlik ve loglama daha kolaydır.
Dosya Erişim Güvenliği: Gerçek dosya yolları gizlenir, uygulama mantığı dışındaki dosyalara doğrudan erişim engellenebilir.
`try_files` direktifinin genel yapısı şöyledir. Sunucu, listedeki dosyaları soldan sağa doğru kontrol eder. İlk bulduğunu sunar. Hiçbirini bulamazsa, son parametrede belirtilen işlemi (fallback) yapar.
NGINX:
try_files $uri $uri/ /index.php?$query_string;
`$uri`: İstenen dosya yolunu (ör: /css/style.css) arar.
`$uri/`: Eğer istenen bir dizinse, o dizini arar (ör: index.html veya index.php dosyası için).
`/index.php?$query_string`: Yukarıdakilerin hiçbiri bulunamazsa, isteği `index.php` dosyasına, orijinal sorgu parametreleriyle birlikte yönlendirir.
Şimdi gelelim pratik uygulamaya. Diyelim ki bir Laravel veya benzeri bir uygulamanız var ve tüm isteklerin `public/index.php` dosyasına gitmesini istiyorsunuz. Aşağıdaki gibi bir `server` bloğu oluşturabilirsiniz. Bu, benim de sıkça kullandığım standart bir yapıdır.
NGINX:
server {
listen 80;
server_name sitem.com www.sitem.com;
root /var/www/projem/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
}
location ~ /\.(?!well-known). {
deny all;
}
}
Bu konfigürasyonda dikkat etmeniz gereken en önemli nokta root direktifinin, uygulamanızın "public" dizinine işaret etmesi. Ayrıca `fastcgi_param SCRIPT_FILENAME` değişkeninde `$realpath_root` kullanmak, sembolik link kullandığınız durumlarda bile doğru dosya yolunun iletilmesini sağlar.
Root Dizin Hatası: En sık karşılaştığım hata, `root` yolunun yanlış verilmesi. Emin değilseniz, `root` dizininizde `index.html` gibi bir test dosyası oluşturup tarayıcıdan erişmeyi deneyin.
PHP-FPM Socket/Port: `fastcgi_pass` değeri sisteminizdeki PHP-FPM yapılandırmasına uygun olmalı. Socket yolu farklı olabilir veya `127.0.0.1:9000` gibi bir port kullanıyor olabilirsiniz. Kontrol etmek için `ls -la /var/run/php/` komutunu kullanabilirsiniz.
try_files Döngüsü: `try_files` içinde son fallback olarak yine aynı `location`'ı işaret ederseniz sonsuz döngüye girip 500 hatası alırsınız. Fallback her zaman net bir dosya veya named location olmalıdır.
Statik Dosya Performansı: CSS, JS, resim gibi statik dosyalar için ayrı bir `location` bloğu eklemek performansı artırır. Örneğin:
NGINX:
location ~ \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
`try_files` direktifi, Nginx'in en güçlü ve esnek özelliklerinden biridir. Front Controller Pattern ile birlikte kullanıldığında, hem geliştirici deneyimini iyileştirir hem de son kullanıcıya daha temiz bir URL yapısı sunar. Bu konfigürasyon, Laravel, Symfony, CodeIgniter gibi çoğu modern framework için hazır halde çalışacaktır.
Ben genellikle yeni bir sunucu hazırlarken bu template'i kullanıyorum ve ihtiyaca göre `location` bloklarını genişletiyorum. Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı bir yaklaşımınız veya eklemek istediğiniz püf noktalar var mı? Aşağıya yorumlarınızı bekliyorum. Takıldığınız bir nokta olursa, yardımcı olmaya çalışırım.