Apache HTTP Server adalah web server tertua yang masih merajai sebagian besar internet, dan selama dua dekade ia adalah rumah utama PHP. Dunia shared hosting dibangun di atasnya: jutaan situs berjalan di server cPanel tempat ratusan pengguna berbagi satu Apache tanpa akses root. Meski deployment modern banyak beralih ke kombinasi nginx + PHP-FPM yang kita bahas sebelumnya, Anda akan tetap bertemu Apache di perusahaan besar, aplikasi warisan, dan penyedia hosting — jadi memahami cara PHP hidup di dalamnya adalah keahlian yang tetap relevan. Chapter ini membahas dua mode integrasi PHP di Apache, konfigurasi virtual host, kebiasaan .htaccess, dan kapan Apache masih menjadi pilihan yang tepat.
Sama seperti chapter Nginx, binary apache2 maupun httpd tidak terpasang di lingkungan penulisan chapter ini, sehingga konfigurasi disajikan sebagai blok bacaan — sementara logika yang menyertainya (pembacaan konfigurasi dan penghitungan perilaku) diuji dengan PHP murni.
Dua Cara Menjalankan PHP di Apache #
Apache mengenal dua cara menjalankan PHP, dan keduanya mewakili dua zaman berbeda. Cara lama, mod_php, menanamkan interpreter PHP langsung ke dalam setiap proses worker Apache: sederhana dan cepat disetel, tetapi semua worker ikut memuat interpreter meskipun sedang melayani berkas statis. Cara modern, mod_proxy_fcgi, meneruskan permintaan PHP ke PHP-FPM lewat protokol FastCGI — arsitektur yang sama seperti pada chapter PHP-FPM
, hanya kali ini Apache yang berperan sebagai web servernya.
| Aspek | mod_php | mod_proxy_fcgi + PHP-FPM |
|---|---|---|
| Letak interpreter | Menempel di setiap proses worker Apache | Terpisah di master dan worker FPM |
| Memori saat melayani statis | Setiap worker tetap memuat interpreter | Interpreter hanya ada di FPM |
| MPM | Secara historis terikat prefork karena tidak thread-safe | Kompatibel dengan event dan worker |
| Perubahan konfigurasi PHP | Menuntut restart Apache | FPM di-reload terpisah |
| Isolasi antar aplikasi | Satu konfigurasi global | Pool terpisah dengan user berbeda |
| Cocok untuk | Aplikasi lama, setup minimalis | Mayoritas aplikasi modern |
Kolom MPM pada tabel di atas menyentuh hal yang penting: mod_php tidak aman terhadap thread, sehingga selama bertahun-tahun distribusi memaksa Apache berjalan dalam mode prefork yang paling boros — mode yang membatasi kemampuan Apache menangani koneksi banyak. Dengan PHP-FPM, batasan itu hilang dan Apache dapat memakai MPM event yang efisien, sehingga jarak kinerjanya terhadap nginx menyempit tajam.
Virtual Host dengan PHP-FPM #
Konfigurasi standar sebuah situs berbasis Apache + FPM adalah virtual host seperti berikut:
<VirtualHost *:80>
ServerName toko.example.com
DocumentRoot /var/www/toko/public
<Directory /var/www/toko/public>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/toko-error.log
CustomLog ${APACHE_LOG_DIR}/toko-access.log combined
</VirtualHost>Bagian yang menghubungkan Apache dengan PHP adalah blok FilesMatch: setiap berkas yang namanya cocok dengan pola \.php$ diberi handler proxy: yang menunjuk socket PHP-FPM — peran yang di nginx dipegang fastcgi_pass. Nilai handler itu sendiri punya format khas: soket Unix sebagai jalur utama, tanda |, lalu URL fcgi://localhost sebagai fallback acuan protokol. Karena format ini mudah salah ketik, kita bisa menguji cara membacanya dengan sebuah pemeriksa kecil:
<?php
$vhost = <<<'APACHE'
<VirtualHost *:80>
ServerName toko.example.com
DocumentRoot /var/www/toko/public
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
APACHE;
if (preg_match('/SetHandler\s+"proxy:([^"]+)"/', $vhost, $cocok) !== 1) {
echo "SetHandler proxy tidak ditemukan\n";
} else {
$target = $cocok[1];
echo "Target proxy: $target\n";
if (str_starts_with($target, 'unix:')) {
echo "Jenis koneksi: Unix domain socket\n";
} elseif (str_starts_with($target, 'fcgi://')) {
echo "Jenis koneksi: TCP FastCGI\n";
}
[$soket, $fallback] = explode('|', $target, 2);
echo "Soket: $soket\n";
echo "Fallback TCP: $fallback\n";
}Output yang Dihasilkan:
Target proxy: unix:/run/php/php8.4-fpm.sock|fcgi://localhost
Jenis koneksi: Unix domain socket
Soket: unix:/run/php/php8.4-fpm.sock
Fallback TCP: fcgi://localhostMari kita bedah skrip pemeriksa tersebut:
- Baris 13 (
preg_match): menangkap isi dalam tanda kutip setelah kataSetHandler "proxy:...— pola([^"]+)mengambil segalanya hingga tanda kutip penutup, apa pun isinya. - Baris 19-23: awalan
unix:versusfcgi://membedakan jenis koneksi, persis seperti perbandingan soket Unix dan TCP pada chapter PHP-FPM. - Baris 25-27: pemisahan pada tanda
|menunjukkan struktur nilai handler: jalur soket dan fallback dalam satu string — pengetahuan yang berguna saat Anda menulis skrip audit yang memastikan semua vhost di server menunjuk pool FPM yang benar.
.htaccess: Fleksibilitas dengan Harga #
.htaccess adalah berkas konfigurasi Apache yang diletakkan di dalam direktori aplikasi dan dibaca tanpa perlu akses root — inilah alasan fitur ini menjadi tulang punggung shared hosting: pengguna menyusun aturan rewrite, proteksi direktori, dan header khusus sendiri. Kebebasan itu datang dengan harga yang tidak tampak: pada setiap permintaan, Apache memeriksa keberadaan .htaccess di direktori berkas yang diminta dan setiap direktori di atasnya hingga DocumentRoot. Makin dalam berkas berada, makin banyak pemeriksaan yang dilakukan — dan ini terjadi untuk semua permintaan, bukan sekali saja.
<?php
function jumlahPencarianHtaccess(string $uri): int
{
$jumlah = 1; // direktori DocumentRoot selalu diperiksa
$segmen = array_filter(explode('/', trim($uri, '/')));
return $jumlah + count($segmen);
}
foreach (['/index.php', '/produk/123', '/admin/laporan/penjualan'] as $uri) {
printf("%-30s => %d kali pencarian .htaccess\n", $uri, jumlahPencarianHtaccess($uri));
}Output yang Dihasilkan:
/index.php => 2 kali pencarian .htaccess
/produk/123 => 3 kali pencarian .htaccess
/admin/laporan/penjualan => 4 kali pencarian .htaccessSimulasi di atas menghitung beban pemeriksaan untuk tiga URI: DocumentRoot selalu diperiksa sekali, lalu setiap segmen jalur menambah satu pemeriksaan. Sebuah berkas tiga tingkat dalam seperti /admin/laporan/penjualan memicu empat kali pembacaan direktori hanya untuk mencari .htaccess yang mungkin tidak ada — kalikan dengan jutaan permintaan, overhead ini nyata terasa di server sibuk.
mod_rewrite untuk Pola Front Controller #
Saat aplikasi memakai satu titik masuk index.php, aturan pemetaan di Apache ditulis dengan mod_rewrite. Versi paling ringkasnya yang biasa tinggal di .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]Tiga baris aktif tersebut bekerja sebagai satu rangkaian syarat:
RewriteEngine On: menyalakan mesin rewrite untuk konteks berkas ini.RewriteCond %{REQUEST_FILENAME} !-f: lanjutkan hanya jika URI bukan berkas yang benar-benar ada (!-f) — berkas statis tetap disajikan apa adanya.RewriteCond %{REQUEST_FILENAME} !-d: dan hanya jika URI bukan direktori yang ada (!-d) — sama seperti syarat kedua.RewriteRule ^ index.php [QSA,L]: pola^cocok dengan URI apa pun, semuanya ditulis ulang keindex.php. FlagQSAmenempelkan query string asli ke tujuan, danLmenghentikan pemrosesan aturan berikutnya.
Hasil akhirnya setara dengan try_files $uri $uri/ /index.php?$query_string; pada nginx (lihat chapter Nginx dan PHP
) — dua mesin berbeda, logika front controller yang sama. Bedanya, mod_rewrite mengevaluasi aturan secara berurutan pada setiap permintaan yang lolos syarat, sehingga vhost dengan puluhan aturan perlu disusun hati-hati agar tidak saling menimpa.
DirectoryIndex #
Direktif DirectoryIndex menentukan berkas mana yang dilayani saat pengguna membuka URL direktori tanpa nama berkas:
DirectoryIndex index.php index.htmlApache mencoba kandidat dari kiri ke kanan: index.php lebih dulu, dan index.html hanya dipakai bila yang pertama tidak ada. Untuk aplikasi PHP, menempatkan index.php di urutan pertama membuat / langsung mengeksekusi aplikasi; urutan terbalik membuat halaman index.html yang terlupakan tiba-tiba muncul menutupi aplikasi Anda. Di beberapa distribusi, nilai bawaannya masih index.html — periksa dan setel eksplisit di virtual host Anda.
MPM Sekilas #
Multi-Processing Module (MPM) menentukan cara Apache mengelola koneksi, dan pilihannya berdampak langsung pada integrasi PHP:
| MPM | Model | Catatan |
|---|---|---|
prefork | Satu proses per koneksi, tanpa thread | Pasangan tradisional mod_php; paling boros memori |
worker | Multi-thread dalam tiap proses | Hemat memori; tidak kompatibel dengan mod_php |
event | Seperti worker, koneksi idle dipindah ke thread khusus | Bawaan distribusi modern; pasangan ideal PHP-FPM |
Sebagaimana disinggung di bagian awal, mod_php memaksa pilihan mundur ke prefork — itulah warisan arsitektur lama yang membuat citra Apache “boros” tertanam begitu lama. Begitu PHP dipindahkan ke FPM, Anda bebas memakai event dan mendapatkan efisiensi koneksi yang setara dengan web server modern lainnya. Periksa MPM aktif server Anda dengan apachectl -V | grep MPM sebelum menyetel batas proses dan memori.
Kapan Masih Memakai Apache #
Tiga situasi membuat Apache tetap menjadi pilihan rasional. Pertama, shared hosting: bila anggaran atau kebijakan menempatkan aplikasi Anda di layanan cPanel tanpa akses root, .htaccess adalah satu-satunya kendali konfigurasi yang tersedia — dan aplikasi Anda harus hidup damai dengannya. Kedua, aplikasi warisan: sistem yang ditulis era mod_php sering menyimpan kebiasaan tertentu, misalnya membaca konfigurasi lewat apache_getenv() atau mengandalkan apache_note(), sehingga migrasi menuntut penyesuaian kode yang tidak selalu worth it. Ketiga, ekosistem modul: mod_auth_basic untuk autentikasi, mod_security untuk firewall aplikasi, dan integrasi SVN lama adalah alat yang matang dan sudah teruji di dalam Apache.
Untuk proyek baru yang Anda kendalikan infrastrukturnya, kombinasi Apache event + PHP-FPM punya kinerja yang patut diacungi jempol — namun bila membangun dari nol, pola nginx + FPM dari chapter sebelumnya umumnya lebih ramping. Keputusan yang jauh lebih penting daripada memilih web server adalah memastikan konfigurasi yang sama dapat direproduksi di mana saja — dan di sinilah container masuk: chapter Docker dan PHP
berikutnya menunjukkan cara mengemas Apache, nginx, PHP-FPM, beserta seluruh konfigurasi chapter ini menjadi citra yang identik antara laptop dan produksi.