IIS’te PHP Kurulumu ve WordPress Çalıştırma

Windows ortamında PHP çalıştırmak, Linux’a alışkın sistem yöneticileri için hep biraz “neden bu kadar karmaşık?” hissi uyandırır. Ama şunu söyleyeyim: IIS üzerinde PHP ve WordPress kurulumu, doğru adımları takip ettiğinizde tahmin ettiğinizden çok daha temiz ve kararlı çalışıyor. Özellikle kurumsal Windows ortamlarında, Active Directory entegrasyonu ve Windows kimlik doğrulaması gerektiren projelerde IIS’i tercih etmek mantıklı bir karar. Bu yazıda sıfırdan başlayıp production-ready bir WordPress kurulumuna kadar gideceğiz.

Ön Hazırlık ve Gereksinimler

Başlamadan önce ortamımızı netleştirelim. Bu yazıdaki adımlar Windows Server 2019/2022 üzerinde test edildi, ama Windows Server 2016 için de büyük ölçüde geçerli. Elinizde şunlar olmalı:

  • Administrator yetkisine sahip bir hesap
  • İnternet erişimi (ya da gerekli kurulum paketleri)
  • SQL Server ya da MySQL/MariaDB (biz bu yazıda MySQL kullanacağız)
  • En az 2 GB RAM, 20 GB disk alanı

Bir de şunu baştan söyleyeyim: PHP’yi IIS’e entegre etmenin iki yolu var. Birincisi CGI, ikincisi FastCGI. CGI her istek için yeni bir PHP process açar, FastCGI ise process havuzu kullanır. Production ortamda FastCGI kullanmak şart, performans farkı ciddi. Biz direkt FastCGI yolunu izleyeceğiz.

IIS Kurulumu ve Gerekli Rollerin Eklenmesi

IIS büyük ihtimalle sunucunuzda henüz yüklü değil. PowerShell ile birkaç dakikada halledebiliriz:

# PowerShell'i Administrator olarak açın
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
Install-WindowsFeature -Name Web-CGI
Install-WindowsFeature -Name Web-Mgmt-Console
Install-WindowsFeature -Name Web-Default-Doc
Install-WindowsFeature -Name Web-Dir-Browsing
Install-WindowsFeature -Name Web-Http-Errors
Install-WindowsFeature -Name Web-Static-Content
Install-WindowsFeature -Name Web-Http-Redirect
Install-WindowsFeature -Name Web-Health
Install-WindowsFeature -Name Web-Performance

Ya da tek seferde daha kapsamlı bir kurulum için:

Install-WindowsFeature Web-Server, Web-CGI, Web-Mgmt-Console, Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-Static-Content, Web-Http-Redirect, Web-Health, Web-Performance -IncludeManagementTools

Kurulum bittikten sonra IIS’in ayağa kalktığını doğrulayalım:

Get-Service W3SVC
# Status: Running görmelisiniz

# Tarayıcıdan da kontrol edin
Start-Process "http://localhost"

CGI özelliğini neden ayrıca ekliyoruz? IIS’in varsayılan kurulumu CGI modülünü getirmiyor. FastCGI de bu modülün üzerine inşa edildiği için olmadan PHP çalışmıyor. Bunu atlayan sistem yöneticilerinin “PHP yüklü ama çalışmıyor” şikayetiyle zaman kaybettiğini defalarca gördüm.

PHP Kurulumu

PHP’yi Windows’a kurmanın birkaç yolu var: resmi PHP sitesinden zip indirmek, Web Platform Installer kullanmak ya da Chocolatey gibi paket yöneticileriyle kurmak. Ben üretim ortamlarında zip yöntemini tercih ediyorum çünkü tam kontrol sizde oluyor, hangi extension’ların yüklü olduğunu siz belirliyorsunuz.

Önce php.net’ten Windows için Thread Safe (TS) versiyonunu indirin. IIS + FastCGI kombinasyonu için Thread Safe versiyon gerekiyor. NTS (Non-Thread Safe) değil. Bu sık yapılan bir hata.

# İndirme dizini oluşturun
New-Item -Path "C:PHP" -ItemType Directory

# PHP'yi bu dizine çıkartın (7-Zip ya da Windows'un kendi aracıyla)
# php.net/downloads adresinden php-8.2.x-Win32-vs16-x64.zip indirin
# C:PHP altına açın

# php.ini dosyasını oluşturun
Copy-Item "C:PHPphp.ini-production" "C:PHPphp.ini"

Şimdi php.ini dosyasında bazı değişiklikler yapmamız gerekiyor. Notepad ya da VSCode ile açın:

# php.ini içinde şu satırları düzenleyin/uncomment edin:

# Extension dizinini belirtin
extension_dir = "C:PHPext"

# WordPress için gerekli extension'lar
extension=curl
extension=gd
extension=mbstring
extension=mysqli
extension=openssl
extension=pdo_mysql
extension=xml
extension=zip
extension=fileinfo
extension=intl

# Zaman dilimi - bunu ayarlamazsanız WordPress sürekli uyarı verir
date.timezone = Europe/Istanbul

# Upload limitleri
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
memory_limit = 256M

# Hata loglama - production'da display_errors kapalı olmalı
display_errors = Off
log_errors = On
error_log = "C:PHPlogsphp_errors.log"

Log dizinini oluşturun ve PHP’yi PATH’e ekleyin:

New-Item -Path "C:PHPlogs" -ItemType Directory

# PHP'yi sistem PATH'ine ekle
$env:Path += ";C:PHP"
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:PHP", [EnvironmentVariableTarget]::Machine)

# Çalışıp çalışmadığını test edin
php -v

IIS’te FastCGI Yapılandırması

PHP kuruldu, şimdi IIS’e PHP’yi FastCGI üzerinden nasıl çalıştıracağını öğreteceğiz. Bu adım kritik.

# IIS Manager'ı açın ya da appcmd ile yapılandırın
# FastCGI handler ekle

& "$env:SystemRootsystem32inetsrvappcmd.exe" set config -section:system.webServer/fastCgi /+"[fullPath='C:PHPphp-cgi.exe',maxInstances='4',idleTimeout='300',activityTimeout='30',requestTimeout='90',instanceMaxRequests='10000',protocol='NamedPipe',flushNamedPipe='False']"

# PHP handler mapping ekle
& "$env:SystemRootsystem32inetsrvappcmd.exe" set config /section:handlers /+"[name='PHP_via_FastCGI',path='*.php',verb='GET,HEAD,POST',modules='FastCgiModule',scriptProcessor='C:PHPphp-cgi.exe',resourceType='Either']"

Alternatif olarak IIS Manager GUI üzerinden de yapabilirsiniz:

  • IIS Manager
  • Sunucu düzeyinde FastCGI Settings tıkla
  • Add Application ile C:PHPphp-cgi.exe ekle
  • Handler Mappings bölümünden Add Module Mapping ile .php uzantısını FastCgiModule‘e yönlendir

PHP’nin çalıştığını test etmek için basit bir test dosyası oluşturun:

# Test dosyası oluştur
Set-Content -Path "C:inetpubwwwroottest.php" -Value "<?php phpinfo(); ?>"

# Tarayıcıda açın
Start-Process "http://localhost/test.php"

phpinfo() sayfasını görüyorsanız PHP IIS entegrasyonu tamamdır. Test bitti mi? O test.php dosyasını silin. Production’da phpinfo() sayfası açık kalan sunucular güvenlik açığı oluşturur.

Remove-Item "C:inetpubwwwroottest.php"

MySQL Kurulumu

WordPress için veritabanı gerekiyor. MySQL Community Edition’ı mysql.com/downloads adresinden indirip yükleyin. Kurulum sırasında Developer Default yerine Server Only seçin, ihtiyacımız olan bu kadar.

# MySQL kurulumu sonrası temel güvenlik ayarı
# MySQL Shell'i açın ve çalıştırın:
mysql -u root -p

# WordPress için veritabanı ve kullanıcı oluşturun
-- MySQL'de çalıştırın
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'GucluBirSifre123!';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

utf8mb4 kullanmak önemli. Eski utf8 MySQL’de gerçek 4-byte UTF-8 karakterleri (emoji gibi) desteklemiyor. WordPress türkçe içerikle kullanılacaksa özellikle dikkat edin.

WordPress Kurulumu

WordPress dosyalarını wordpress.org’dan indirip web dizinine çıkartın:

# WordPress indirme ve yerleştirme
$wpUrl = "https://wordpress.org/latest.zip"
$wpZip = "C:tempwordpress.zip"
$wpDest = "C:inetpubwwwrootwordpress"

New-Item -Path "C:temp" -ItemType Directory -Force
Invoke-WebRequest -Uri $wpUrl -OutFile $wpZip
Expand-Archive -Path $wpZip -DestinationPath "C:inetpubwwwroot" -Force

# wp-config.php oluştur
Copy-Item "$wpDestwp-config-sample.php" "$wpDestwp-config.php"

wp-config.php dosyasını düzenleyin:

# wp-config.php içindeki kritik satırlar
# Not: Bu değerleri kendi değerlerinizle değiştirin

define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'GucluBirSifre123!' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );

# Salt değerlerini https://api.wordpress.org/secret-key/1.1/salt/ adresinden alın
# Her kurulum için benzersiz olmalı

# WordPress tablo öneki - varsayılan wp_ yerine farklı bir şey kullanın
$table_prefix = 'wpr8x_';

IIS’te WordPress için Site Yapılandırması

Şimdi WordPress için özel bir IIS sitesi oluşturacağız. Varsayılan siteyi kullanmak yerine izole bir site oluşturmak yönetim açısından çok daha temiz.

# Yeni IIS sitesi oluştur
New-WebSite -Name "WordPress" -Port 80 -PhysicalPath "C:inetpubwwwrootwordpress" -Force

# Application pool oluştur ve yapılandır
New-WebAppPool -Name "WordPressPool"
Set-ItemProperty -Path "IIS:AppPoolsWordPressPool" -Name "managedRuntimeVersion" -Value ""
Set-ItemProperty -Path "IIS:AppPoolsWordPressPool" -Name "startMode" -Value "AlwaysRunning"

# Siteyi bu pool'a ata
Set-ItemProperty -Path "IIS:SitesWordPress" -Name "applicationPool" -Value "WordPressPool"

Managed Runtime Version’ı neden boş bırakıyoruz? IIS application pool varsayılan olarak .NET runtime kullanmaya çalışır. PHP uygulamaları için buna gerek yok ve bazen çakışma yaratıyor. No Managed Code seçeneği bu demek.

web.config ile URL Rewriting

WordPress’in kalıcı bağlantıları (pretty permalinks) çalışması için URL rewriting şart. IIS’te bunu web.config ile yapıyoruz. Ama önce URL Rewrite Module‘ü kurmanız gerekiyor. Bunu IIS Web Platform Installer’dan ya da doğrudan Microsoft’tan indirebilirsiniz.

# web.config dosyasını WordPress dizinine oluşturun
# C:inetpubwwwrootwordpressweb.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="WordPress" patternSyntax="Wildcard">
                    <match url="*" />
                    <conditions>
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php" />
                </rule>
            </rules>
        </rewrite>
        <staticContent>
            <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
            <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
        </staticContent>
    </system.webServer>
</configuration>

Dosya İzinleri

Windows’ta dosya izinleri biraz farklı çalışıyor. WordPress’in dosya yazabilmesi için doğru izinleri vermeliyiz:

# Application pool identity'sine yazma izni ver
# WordPressPool için IIS AppPoolWordPressPool hesabını kullanıyoruz

$wpPath = "C:inetpubwwwrootwordpress"
$acl = Get-Acl $wpPath

$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "IIS AppPoolWordPressPool",
    "Modify",
    "ContainerInherit,ObjectInherit",
    "None",
    "Allow"
)

$acl.SetAccessRule($accessRule)
Set-Acl -Path $wpPath -AclObject $acl

Write-Host "İzinler başarıyla ayarlandı."

Bu izin olmadan WordPress tema güncelleyemiyor, plugin yükleyemiyor, cache dosyası oluşturamıyor. Kurulum sonrası “izin hatası” şikayetlerinin neredeyse tamamı bu adımın atlanmasından kaynaklanıyor.

SSL Sertifikası Ekleme

Production ortamında HTTP’de kalmak artık bir seçenek değil. Let’s Encrypt Windows’ta win-acme aracıyla kolayca kullanılabiliyor:

# win-acme'yi indirin (github.com/win-acme/win-acme)
# Çalıştırın ve domain için sertifika oluşturun

.wacs.exe --target iis --siteid 2 --installation iis

# Sertifika otomatik yenilenecek şekilde Windows Task Scheduler'a ekleniyor

Eğer kurumsal bir ortamdaysanız ve kendi CA’nız varsa, sertifikayı IIS Manager üzerinden Server Certificates bölümünden import edebilirsiniz.

Performans ve Güvenlik Ayarları

Kurulum çalışıyor artık, ama birkaç ek ayar yapmazsak production için hazır sayılmaz.

OPcache Aktifleştirme:

# php.ini'ye ekleyin
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

OPcache PHP script’leri derlenmiş halde bellekte tutuyor. WordPress gibi dosya yoğun uygulamalarda fark çok belirgin, disk I/O ciddi ölçüde azalıyor.

IIS Request Filtering:

# Hassas dosyaları gizle
# web.config'e ekleyin

<security>
    <requestFiltering>
        <hiddenSegments>
            <add segment="wp-config.php" />
            <add segment=".git" />
            <add segment=".htaccess" />
        </hiddenSegments>
        <fileExtensions>
            <add fileExtension=".log" allowed="false" />
            <add fileExtension=".bak" allowed="false" />
        </fileExtensions>
    </requestFiltering>
</security>

WordPress için önerilen ek güvenlik başlıkları:

  • X-Frame-Options: SAMEORIGIN: Clickjacking saldırılarını engeller
  • X-Content-Type-Options: nosniff: MIME type sniffing’i engeller
  • X-XSS-Protection: 1; mode=block: Eski tarayıcılarda XSS koruması
  • Referrer-Policy: strict-origin-when-cross-origin: Referrer bilgisini kısıtlar

Bu başlıkları IIS Manager’daki HTTP Response Headers bölümünden ya da web.config üzerinden ekleyebilirsiniz.

Sorun Giderme

Kaçınılmaz olarak bir şeyler ters gider. En sık karşılaşılan durumlar:

500 Internal Server Error:

# IIS loglarını kontrol edin
Get-Content "C:inetpublogsLogFilesW3SVC1*.log" -Tail 50

# PHP hata logunu kontrol edin
Get-Content "C:PHPlogsphp_errors.log" -Tail 50

# Olay görüntüleyicisini kontrol edin
Get-EventLog -LogName Application -Source "PHP*" -Newest 20

PHP çalışmıyor, dosya indiriyor: Handler mapping doğru eklenmemiş demektir. IIS Manager’da Handler Mappings listesinde PHP_via_FastCGI girişini kontrol edin.

WordPress admin paneli çalışmıyor ama anasayfa açılıyor: URL Rewrite Module yüklenmemiş ya da web.config yanlış dizinde olabilir.

Dosya yükleme çalışmıyor: upload_max_filesize ve post_max_size değerlerini kontrol edin, aynı zamanda application pool identity’nin wp-content/uploads dizinine yazma izni olduğundan emin olun.

Sonuç

IIS üzerinde PHP ve WordPress kurulumu, ilk bakışta göz korkutucu görünse de adımları sırayla takip ettiğinizde son derece düzgün çalışan bir sistem ortaya çıkıyor. Özellikle kurumsal Windows altyapısında bu kurulumun bazı avantajları var: Windows kimlik doğrulaması, merkezi log yönetimi, Active Directory entegrasyonu bunların başında geliyor.

Kritik noktalara tekrar bakalım: FastCGI kullanın, Thread Safe PHP versiyonunu seçin, OPcache’i aktifleştirin, dosya izinlerini application pool identity üzerinden verin ve URL Rewrite Module’ü kurmayı unutmayın. Bu beş noktayı atlamamak kurulumun yüzde seksenini doğru yapmak demek.

Production’a almadan önce mutlaka bir yük testi yapın. WordPress + IIS + MySQL kombinasyonu doğru yapılandırıldığında binlerce eşzamanlı isteği rahatlıkla kaldırıyor, ama application pool ayarları ve PHP worker sayısı ortamınıza göre fine-tune edilmeli. Bu optimizasyon konusunu ayrı bir yazıda ele alacağız.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir