Hastanenin acil servis triyaj ve hasta kayıt bankosunu düşünün. Gece yarısı acil servise nefes darlığı çeken bir hasta başvurur. Hasta kayıt memuruna T.C. kimlik kartını uzatır. Memur hastanın kimliğini bilgisayarda sorgular; T.C. numarası doğrudur, sigortası aktiftir, kimlikte hiçbir sorun yoktur. Memur "Tamam, kimliğiniz doğrulandı" der. Ancak hastanın giriş kaydını basacağı resmi protokol defterinin bulunduğu dolabın anahtarı kaybolmuştur ya da memurun elindeki tüm tükenmez kalemlerin mürekkebi bitmiştir! Memur fiziki olarak deftere tek bir harf bile yazamaz. Hastanın yüzüne bakar ve çaresizce şöyle der: "Kimliğiniz doğru ama sisteme dosya açamadım, lütfen kapıdan çıkıp tekrar sıraya girin ve kimliğinizi baştan verin." Hasta şaşkınlıkla sıradan çıkar, kapıya gider, tekrar bankoya gelir; kimliğini verir, memur yine onaylar ama yine yazamaz ve yine kapıya gönderir. Hasta sonsuz bir bürokratik döngünün içinde rehin kalmıştır.

PHP tabanlı web uygulamalarında (WordPress, Laravel, OpenCart veya özel e-ticaret sistemleri) session_save_path dizininin izinlerinin veya sahipliğinin bozulması, web dünyasında tam olarak bu hezeyanı üretir: Sonsuz Giriş Döngüsü (Session Login Loop).


PHP Oturumu (Session) Nasıl Yaşar?

HTTP protokolü durumsuz (stateless) bir protokoldür. Bir istek bittiğinde istemci ile sunucu arasındaki tüm hafıza silinir. Web sitelerinin bir kullanıcının kim olduğunu hatırlayabilmesi için oturum mekanizması icat edilmiştir.

Standart bir PHP kurulumunda bu mekanizma dosya sistemi üzerinden yürür:

[Kullanıcı Tarayıcısı]                      [Linux Sunucusu]
         │                                         │
         │ 1. POST /login.php                      │
         │    (Kullanıcı adı: admin, Parola: 123)   │
         ├────────────────────────────────────────►│
         │                                         │ 2. Parola hash'i doğrulandı!
         │                                         │ 3. session_start() çağrıldı.
         │                                         │ 4. Sunucu diskine dosya yazılacak:
         │                                         │    /var/lib/php/sessions/sess_91823...
         │                                         │    İçerik: user_id|i:1; logged_in|b:1;
         │                                         │
         │ 5. HTTP 200 OK                          │
         │    Set-Cookie: PHPSESSID=91823...       │
         │◄────────────────────────────────────────┤

Eğer sunucu 4. adımda o küçük oturum dosyasını diske yazamazsa ne olur?

  • Kullanıcının şifresi doğrudur.
  • Veritabanı sorgusu başarılıdır.
  • Ancak sunucu kullanıcının oturum açtığı bilgisini fiziksel belleğe kazıyamaz.
  • Kullanıcı bir sonraki sayfaya (/admin/dashboard.php) geçtiğinde, PHP oturum dosyasını diskte arar; dosya boştur veya hiç oluşmamıştır. PHP der ki: "Sen kimsin? Oturumun yok!" ve kullanıcıyı tekrar /login.php sayfasına fırlatır!

Patolojinin Anatomisi: Hata Yok, Giriş de Yok!

Bu arızayı sistem yöneticileri ve geliştiriciler için bir kabusa dönüştüren asıl faktör, ekranda hiçbir hata mesajının görünmemesidir.

Kullanıcı kullanıcı adını ve şifresini yazar, "Giriş Yap" butonuna basar:

  • Sayfa 1 saniye yenilenir.
  • Form kutucukları tekrar boşalır.
  • Ekranda "Hatalı şifre" yazmaz.
  • "Kullanıcı bulunamadı" yazmaz.
  • 500 Internal Server Error vermez.
  • Sadece giriş sayfası tekrar açılır.

Müşteri şifresini 10 kez sıfırlar, yeni şifre alır; yine giremez. Tarayıcı önbelleğini temizler, gizli sekmeden dener; yine giremez. Destek masasına "Siteniz bozuldu, şifremi kabul etmiyor!" diye biletler yağmaya başlar.


İzinler Nasıl Bozulur? Suçlular Kürsüsü

/var/lib/php/sessions (veya CentOS/cPanel'de /tmp ya da /var/cpanel/php/sessions) dizini durduk yere bozulmaz. Bu patolojiyi tetikleyen tipik insan ve otomasyon hataları şunlardır:

1. chmod -R 777 veya chown Çılgınlığı

Acemi bir geliştirici sitede bir resim yükleme hatası aldığında sunucuda geniş çaplı bir sahiplik değişikliği çalıştırır:

sudo chown -R www-data:www-data /var/lib/

Eğer sunucuda PHP-FPM farklı bir kullanıcı havuzuyla (örneğin nginx veya sanal hosting kullanıcısı ahmet) çalışıyorsa, o andan itibaren ahmet kullanıcısı oturum dizinine yazamaz hale gelir!

2. PHP Sürüm Güncellemesi (PHP 8.1 -> 8.2 Geçişi)

Ubuntu veya Debian üzerinde apt upgrade ile yeni PHP sürümleri kurulduğunda, paket yöneticisi bazen oturum dizininin izinlerini varsayılan paket ayarlarına (root:root veya 0733) çeker. PHP-FPM süreci bu dizine yazamaz.

3. Disk Doluluğu veya Inode Tükenmesi

Diskte gigabaytlarca boş yer olsa bile, sunucuda milyonlarca minik dosya varsa dosya sistemi Inode (İndeks Düğümü) sınırına dayanabilir (df -i). Inode tükendiğinde PHP yeni bir oturum dosyası açamaz; hata vermeden sessizce çöker.


Teşhis: Suç Aletini Yakalamak

Karanlıkta el yordamıyla aramak yerine Nginx/Apache ve PHP-FPM hata loglarını açtığınızda suçlu kendini hemen ele verir:

# PHP-FPM hata logunu izleyin:
tail -f /var/log/php8.2-fpm.log
# Veya Nginx error.log:
tail -f /var/log/nginx/error.log

Ekrana düşen o tanıdık log satırı:

FastCGI sent in stderr: "PHP message: PHP Warning: session_start(): 
open(/var/lib/php/sessions/sess_a9f1b..., O_RDWR) failed: 
Permission denied (13) in /var/www/site/login.php on line 4"

İşte oradadır: Permission denied (13). PHP feryat etmektedir: "Ben oturum dosyasını açmak istedim ama işletim sistemi kapıyı yüzüme çarptı!"


Cerrahi Operasyon: Dizini Onarmak

Bu patolojiyi düzeltmek 30 saniyelik bir terminal operasyonudur; ancak doğru kullanıcı ve izin kombinasyonunu bilmek şarttır.

1. PHP-FPM'in Hangi Kullanıcıyla Çalıştığını Tespit Edin:

ps aux | grep php-fpm
# Çıktıda worker süreçlerinin sahibi görünür: www-data, nginx veya cpanel kullanıcısı.

2. Oturum Dizinini ve İzinlerini Yeniden Yapılandırın:

Ubuntu / Debian ortamında standart yapı:

# Dizinin varlığını doğrulayın:
sudo mkdir -p /var/lib/php/sessions
 
# Sahipliği PHP-FPM kullanıcısına devredin:
sudo chown -R www-data:www-data /var/lib/php/sessions
 
# İzinleri 700 (veya grup erişimi gerekiyorsa 730 / 770) olarak ayarlayın:
sudo chmod 700 /var/lib/php/sessions

CentOS / RHEL / AlmaLinux ortamında:

sudo chown -R apache:apache /var/lib/php/session
# Veya Nginx kullanılıyorsa:
sudo chown -R nginx:nginx /var/lib/php/session
sudo chmod 770 /var/lib/php/session

Kalıcı Mimari Tedavi: Oturumları Diske Değil Redis'e Emanet Etmek

Modern ve ölçeklenebilir bir web mimarisinde kullanıcı oturumlarının yerel sunucu diskindeki minik dosyalarda (/var/lib/php/sessions) saklanması zaten mimari bir borçtur (technical debt).

Sunucunuz yatayda büyüdüğünde (Load Balancer arkasında 2 veya daha fazla sunucu olduğunda) yerel disk oturumları zaten çalışmaz; kullanıcının her isteği farklı sunucuya düştüğünde oturumu düşer.

En temiz, en hızlı ve izin sorunlarını kökten yok eden cerrahi çözüm, oturum yönetimini Redis bellek motoruna devretmektir:

; /etc/php/8.2/fpm/php.ini içine yazılacak modern reçete:
 
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?prefix=PHPREDIS_SESSION:&auth=GucluSifre123"

PHP-FPM servisini yeniden başlattığınız an (systemctl restart php8.2-fpm):

  • Oturumlar diske dosya yazmakla uğraşmaz; RAM hızında mikro saniyeler içinde Redis'e yazılır.
  • Disk doluluğu, dosya izinleri veya chmod faciaları oturumlarınızı etkileyemez.
  • Çoklu sunucu mimarisine geçtiğinizde tüm sunucular aynı Redis havuzundan oturumları ortaklaşa okur.

Sonuç

Doğrulanmış bir kimliği resmi deftere kaydedemeyen acil servis personeli hastayı içeri alamaz; oturum dosyasını diske yazamayan bir PHP motoru da şifresi doğru olan hiçbir kullanıcıyı içeri sokamaz.

Web mühendisliğinde kullanıcı deneyimi sadece ön yüz animasyonlarından ibaret değildir. /var/lib/php/sessions dizinindeki tek bir dosya izni, milyonluk bir portalın kapılarını dünyaya kilitleyebilir. Giriş panelleriniz sessiz döngülere girdiğinde suçu şifrelerde değil, işletim sisteminin yazma izinlerinde arayın.