PHP-FPM kurulumu#
Bu sayfa uzun yıllar "CentOS 7'de PHP 7 ve PHP-FPM kurulumu" başlığıyla yaşadı. CentOS 7'nin desteği Haziran 2024'te bitti, PHP 7'nin desteği ondan da önce, 2019'da bitmişti. Link hâlâ elimizde duruyor ama içeriği artık doğru olmayan bir şeyi öğretmemeli - o yüzden aynı soruyu güncel dağıtım ve sürümlerle yeniden yazdık. Mantık aynı, komutlar farklı.
PHP-FPM nedir, neden mod_php değil#
PHP-FPM (FastCGI Process Manager), PHP'yi web sunucusunun kendi sürecinden ayrı, bağımsız worker havuzları halinde çalıştırır. nginx zaten PHP çalıştıramaz - Apache'nin aksine bir PHP modülü yoktur - o yüzden nginx kullanan her kurulumda PHP-FPM zorunludur. Apache tarafında bile bugün mod_php yerine PHP-FPM tercih edilir: süreç izolasyonu, bağımsız yeniden başlatma ve daha öngörülebilir bellek kullanımı sağlar.
Hangi PHP sürümünü kurmalıyım#
PHP her Kasım'da yeni bir minör sürüm çıkarır; her sürüm ~2 yıl aktif, +1 yıl da yalnızca güvenlik yaması alır. "En güncel sürüm" bu sayfa yazıldıktan sonra da değişmeye devam edecek, o yüzden burada sabit bir numaraya değil php.net/supported-versions sayfasına bakın - o an aktif desteği olan sürümleri gerçek zamanlı gösterir.
Pratik kural
Yeni bir proje kuruyorsanız listedeki en güncel sürümü seçin. Var olan bir uygulamayı taşıyorsanız ve o uygulama eski bir sürüme kilitliyse, aşağıdaki "Birden fazla PHP sürümü aynı sunucuda" bölümüne bakın - illa en eskisini sistem geneline yaymanıza gerek yok.
Aşağıdaki örneklerde 8.4 kullanıyoruz; kendi tercih ettiğiniz sürüme göre değiştirin, adımların mantığı hepsinde aynı.
1. Paketleri kurun#
Dağıtımın kendi depoları genelde bir-iki sürüm geriden gelir. Güncel sürümlere erişmek için Ondřej Surý'nin PPA'sı - CentOS 7 döneminden beri PHP dünyasının fiili standardı - hâlâ referans kaynaktır:
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt update
sudo apt install -y nginx php8.4-fpm php8.4-cli php8.4-mysql \
php8.4-curl php8.4-gd php8.4-mbstring php8.4-xml php8.4-zip
Dağıtımın kendi deposuyla yetiniyorsanız paket adlarından sürüm numarasını çıkarın (php-fpm, php-cli, …) - o zaman Ubuntu/Debian sürümünün varsayılanını alırsınız.
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf module reset php
sudo dnf module enable -y php:remi-8.4
sudo dnf install -y nginx php-fpm php-cli php-mysqlnd php-curl php-gd php-mbstring php-xml php-zip
CentOS 7'nin doğrudan devamı olmasa da, Rocky/AlmaLinux bugün RHEL ailesinde aynı rolü oynuyor - Remi deposu da CentOS 7 döneminden beri aynı işi yapıyor. remi-8.4 yerine güncel sürüm ne ise onu yazın (dnf module list php mevcut seçenekleri gösterir).
Bu komutlar EL9 içindir
epel-release-latest-9 ve remi-release-9 paket adlarındaki 9, major EL sürümüne (Rocky/AlmaLinux 9) özeldir - EL8'de epel-release-latest-8 + remi-release-8, EL10'da epel-release-latest-10 + remi-release-10 gerekir. Yanlış sürüm numarasıyla kurulum bağımlılık çakışmasıyla başarısız olur. Kendi major sürümünüzü cat /etc/os-release ile doğrulayın.
Morpheus ile
"sunucuma en güncel php-fpm sürümünü kur, nginx zaten kurulu"
Morpheus dağıtımı tanır, hangi sürümlerin depoda mevcut olduğuna bakar ve doğru depo/paket adını seçer; RHEL ailesinde modül etkinleştirme adımını da o çalıştırır.
2. Havuzu (pool) yapılandırın#
PHP-FPM, her site/uygulama için ayrı bir "havuz" tanımlar. Havuz dosyasının konumu ve içindeki soket yolu dağıtıma göre değişir - ikisini karıştırırsanız 502 alırsınız, o yüzden ayrı ayrı veriyoruz.
[www]
user = www-data
group = www-data
listen = /run/php/php8.4-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
sudo systemctl restart php8.4-fpm
[www]
user = nginx
group = nginx
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
sudo systemctl restart php-fpm
user/group yerine yalnızca soket iznini paylaşmak isterseniz
Yukarıdaki user/group değerlerini nginx'inkiyle aynı yapmak en basit yol - tek siteli bir sunucuda pratikte sorun çıkarmaz. Ama FPM worker'larının kendi kimliğini korumasını (nginx'ten ayrı bir kullanıcı) istiyorsanız, user/group'u değiştirmek yerine yalnızca listen.owner/listen.group/listen.mode satırlarını nginx'in çalıştığı kullanıcıya göre ayarlamanız yeterli - soket izni ile worker kimliği ayrı şeylerdir, ikincisini değiştirmeden birincisini çözebilirsiniz.
3. nginx'e bağlayın#
server {
listen 80;
server_name example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
Debian/Ubuntu'nun nginx paketi yalnızca sites-enabled/ altındakini yükler - sites-available/'a yazmak tek başına yeterli değil, sembolik bağla etkinleştirmeniz gerekir:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t && sudo systemctl reload nginx
RHEL ailesinin nginx paketi sites-available/sites-enabled kullanmaz - her şey conf.d/ altına düz .conf dosyası olarak yazılır, ayrıca etkinleştirme adımı gerekmez. snippets/fastcgi-php.conf de Debian paketine özeldir; RHEL'de fastcgi parametrelerini elle eklersiniz:
server {
listen 80;
server_name example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php-fpm/www.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
sudo nginx -t && sudo systemctl reload nginx
fastcgi_pass yolu, 2. adımda listen için yazdığınız soketle birebir aynı olmalı. Bu ikisi arasındaki en ufak yazım farkı 502 Bad Gateway ile sonuçlanır - listedeki en sık PHP-FPM hatası budur.
4. Test edin (ve hemen silin)#
echo "<?php phpinfo();" | sudo tee /var/www/example.com/info.php
https://example.com/info.php sayfasını açın, PHP sürümünü ve yüklü modülleri görün.
info.php'yi kalıcı bırakmayın
phpinfo() sunucu yollarını, yüklü modülleri ve bazen ortam değişkenlerini dışarı sızdırır. Test biter bitmez silin:
sudo rm /var/www/example.com/info.php
Birden fazla PHP sürümü aynı sunucuda#
Eski bir uygulama daha eski bir sürüme kilitliyken yeni bir tanesi güncelini istiyorsa (mesela 8.1 ile 8.4 bir arada), ikisini yan yana kurabilirsiniz - her sürümün kendi FPM havuzu, kendi soketi olur (php8.1-fpm.sock, php8.4-fpm.sock), site bazında nginx fastcgi_pass ile hangisine gideceğini seçer. Sistem genelindeki php komutu tek sürüme bağlıdır; update-alternatives --config php (Debian) ile CLI tarafını değiştirebilirsiniz. Eski sürümü yalnızca o uygulama için tutun - güvenlik desteği bittiyse yeni site açarken bir daha seçmeyin.
Sorun giderme#
502 Bad Gateway - neredeyse her zaman soket/port uyuşmazlığı. nginx'teki fastcgi_pass ile FPM havuzundaki listen aynı değeri taşımıyor, ya da FPM servisi hiç ayakta değil (systemctl status php8.4-fpm Debian/Ubuntu'da, systemctl status php-fpm RHEL ailesinde).
"Permission denied" FPM loglarında - user/group sunucudaki gerçek kullanıcıyla uyuşmuyor, ya da dosya izinleri çok kısıtlayıcı. Önce hangi dosya/dizinde takıldığını log'dan görün, yalnızca o yolun sahipliğini düzeltin (chown www-data:www-data /var/www/example.com/o-dosya) - tüm site köküne kör kör chown -R uygulamak, uygulama koduyla yüklenen içeriği aynı sahiplikte bırakır ve web süreci ele geçirilirse kod dosyalarını da yazılabilir hale getirir.
Değişiklik etki etmiyor - FPM'i reload değil restart etmeniz gerekebilir; havuz dosyası değişiklikleri yalnızca yeniden başlatmada okunur.
Morpheus ile
"php-fpm neden 502 veriyor bak"
Morpheus nginx error log'unu, FPM servis durumunu ve soket dosyasının varlığını kontrol eder, hangisinin eksik olduğunu söyler.
Kontrol listesi#
- [ ]
systemctl status php8.4-fpm(Debian/Ubuntu) ya dasystemctl status php-fpm(RHEL ailesi)active (running) - [ ]
nginx -t→syntax is ok - [ ]
fastcgi_passve FPMlistenaynı soketi gösteriyor - [ ]
info.phptest edildi ve silindi - [ ]
user/groupdeğerleri nginx'in çalıştığı kullanıcıyla eşleşiyor