Request dari browser tidak mendarat langsung di Laravel — request melewati web server (nginx atau Apache), diteruskan ke PHP-FPM, dan baru dieksekusi oleh front controller public/index.php. Konfigurasi web server karena itu adalah gerbang pertama deployment, dan satu kesalahan kecil pada document root bisa membocorkan seluruh berkas proyek ke publik. Chapter ini membahas alur request tersebut, konfigurasi nginx dan Apache sebagai contoh tampilan, hingga pengaktifan HTTPS.

Document Root Harus public/ #

Struktur direktori Laravel sengaja menaruh front controller di dalam public/, dan semua berkas sensitif — .env, composer.lock, kode sumber — berada di luar direktori tersebut. Document root server web wajib diarahkan ke public/, bukan ke akar proyek. Karena tidak ada server produksi di lingkungan uji, kita mensimulasikan kedua kondisi dengan PHP built-in server dan request sungguhan lewat curl:

bash
php -S 127.0.0.1:8080            # SALAH: document root di akar proyek
php -S 127.0.0.1:8081 -t public  # BENAR: document root di public/

Lalu kita minta tiga path kritis dari masing-masing server:

text
--- SALAH (root): /composer.lock
HTTP 200 | 311723 bytes
--- SALAH (root): /.env
HTTP 200 | 1142 bytes
--- BENAR (public/): /composer.lock
HTTP 404 | 6586 bytes
--- BENAR (public/): /.env
HTTP 404 | 6586 bytes
--- BENAR (public/): /
HTTP 200 | 70403 bytes

Bedanya mencolok. Dengan document root yang salah, /.env disajikan apa adanya — 1.142 byte berisi APP_NAME, APP_ENV, hingga APP_KEY:

text
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:…

Penyerang hanya perlu satu request untuk membaca kredensial lengkap aplikasi; composer.lock yang ikut bocor (311 KB) juga membocorkan versi pasti setiap paket, peta yang sempurna untuk mencari celah versi lama. Dengan document root di public/, kedua berkas tersebut jatuh ke luar jangkauan dan Laravel merespons 404, sementara halaman utama tetap terlayani normal. Prinsip inilah yang juga ditegaskan pada dokumentasi deployment Laravel.

Server Block Nginx #

Nginx adalah pilihan paling umum untuk Laravel. Berikut contoh tampilan server block untuk tokobudi.example.com — konfigurasi ini dijalankan di server sungguhan sebagai /etc/nginx/sites-available/tokobudi.conf:

nginx
server {
    listen 80;
    server_name tokobudi.example.com;
    root /var/www/tokobudi/public;
    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }

    location ~* \.(css|js|jpg|jpeg|png|webp|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

Tiga arahan adalah tulang punggungnya. root .../public menuntaskan aturan document root dari bagian sebelumnya. try_files $uri $uri/ /index.php?$query_string melayani berkas statis yang benar-benar ada, lalu meneruskan sisanya ke front controller — inilah yang membuat URL rapi Laravel bekerja tanpa suffix .php. Blok location ~ \.php$ menyerahkan eksekusi PHP ke PHP-FPM lewat socket php8.4-fpm.sock. Terakhir, blok location ~ /\.(?!well-known).* menolak akses ke berkas berawalan titik (.env, .git) kecuali .well-known untuk validasi ACME.

Apache dan .htaccess #

Apache bisa memakai berkas .htaccess bawaan di dalam public/ selama mod_rewrite aktif dan AllowOverride All diizinkan pada virtual host. Contoh tampilan virtual host-nya:

apache
<VirtualHost *:80>
    ServerName tokobudi.example.com
    DocumentRoot /var/www/tokobudi/public

    <Directory /var/www/tokobudi/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

.htaccess bawaan Laravel kemudian menulis ulang seluruh request ke index.php selama berkas fisiknya tidak ada. Di sisi performa, nginx sedikit diunggulkan karena aturan rewrite dievaluasi sekali saat startup, bukan per request — tapi Apache tetap pilihan sah dan sering sudah tersedia di hosting bersama.

Dasar Penyetelan PHP-FPM #

PHP-FPM menjalankan sekelompok worker yang siap mengeksekusi skrip. Contoh tampilan konfigurasi pool di /etc/php/8.4/fpm/pool.d/www.conf:

ini
user = www-data
group = www-data
listen = /var/run/php/php8.4-fpm.sock
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Nilai pm.max_children membatasi jumlah worker — setiap worker PHP bisa memakan sekitar 30–60 MB memori, jadi angka ini dihitung dari RAM server, bukan disalin mentah-mentah. Kesalahan umum adalah max_children terlalu tinggi sehingga worker saling berebut memori, atau terlalu rendah sehingga antrean 502 Bad Gateway muncul saat lonjakan traffic.

HTTPS dan Redirect #

Sertifikat TLS gratis diterbitkan lewat Certbot yang otomatis menulis konfigurasi nginx. Contoh tampilan prosesnya:

bash
sudo certbot --nginx -d tokobudi.example.com -d www.tokobudi.example.com

Certbot memasang sertifikat Let’s Encrypt, mengaktifkan listen 443 ssl, dan menambahkan redirect 80→443. Dua pekerjaan sisanya ada di sisi Laravel: paksa skema HTTPS untuk seluruh URL yang dibangun aplikasi (URL::forceScheme('https') saat environment produksi) dan percayai header proxy lewat $middleware->trustProxies(at: [...]) — keduanya sudah dibahas di Secure Configuration . Untuk konsistensi domain, redirect www ke domain utama ditambahkan sebagai server block terpisah:

nginx
server {
    listen 443 ssl;
    server_name www.tokobudi.example.com;
    return 301 https://tokobudi.example.com$request_uri;
}

Web server kini menyajikan aplikasi dengan aman. Namun rilis pertama hampir selalu membawa perubahan skema — dan menjalankan migration di atas data pengguna asli butuh prosedur yang jauh lebih hati-hati, yang kita bahas di Database Migration di Production .