Server siap, migrasi aman, worker hidup, scheduler berdetak, dan rollback sudah diuji — tersisa satu gerbang terakhir sebelum aplikasi dibuka untuk publik: memastikan kita tidak membukanya dengan pintu keamanan terkunci seadanya. Bab penutup section ini berbentuk daftar periksa go-live, dikelompokkan per kategori, dengan tiga kolom yang bisa langsung dipakai: apa yang diperiksa, mengapa ia penting, dan perintah verifikasi. Konsep di balik tiap poin sudah dibahas tuntas di section Keamanan Aplikasi — di sini kita memastikan semuanya benar-benar aktif di server, bukan sekadar ada di kepala. Karena hasil verifikasi hanya berarti bila dibaca dari mesin yang tepat, perintah-perintah berikut dijalankan di server produksi setelah .env final terpasang.

Environment #

Tiga saklar ini paling fundamental karena mengubah perilaku framework secara global:

PemeriksaanMengapaVerifikasi
APP_ENV=productionMode produksi menolak perintah berbahaya tanpa --forcephp artisan config:show app.env
APP_DEBUG=falsetrue membocorkan stack trace, path, dan kredensial ke pengunjungphp artisan config:show app.debug
APP_KEY terpasang dan bukan nilai bawaanEnkripsi session dan cookie bergantung padanyapotongan pemeriksa di bawah

Kita jalankan keduanya di sandbox dengan .env bergaya produksi:

bash
php artisan config:show app.env
php artisan config:show app.debug

Output yang Dihasilkan:

text
  app.env ......................................................... production  


  app.debug ............................................................ false  

Untuk kunci aplikasi, pemeriksaan cukup memastikan prefix base64: ada tanpa mencetak nilainya ke terminal:

php
$key = config('app.key');

echo 'app.key terpasang : '.(str_starts_with($key, 'base64:')
    ? 'ya (base64, panjang '.strlen($key).' karakter)'
    : 'TIDAK');

Output yang Dihasilkan:

text
app.key terpasang : ya (base64, panjang 51 karakter)

HTTP dan Transport #

Lapisan jaringan diverifikasi dari response header — dan header yang kita tangkap di sandbox justru mengungkap satu temuan:

bash
curl -sI http://127.0.0.1:8018/

Output yang Dihasilkan (isi cookie dipangkas):

text
HTTP/1.1 200 OK
X-Powered-By: PHP/8.4.8
Content-Type: text/html; charset=utf-8
Set-Cookie: XSRF-TOKEN=...; path=/; secure; samesite=lax
Set-Cookie: laravel-session=...; path=/; secure; httponly; samesite=lax

Baris X-Powered-By: PHP/8.4.8 adalah informasi gratis untuk penyerang — versi PHP yang diketahui berarti daftar CVE yang diketahui juga. Matikan lewat expose_php = Off di php.ini. Daftar lengkap untuk kategori ini:

PemeriksaanMengapaVerifikasi
HTTPS dipaksa untuk semua requestTanpa TLS, kredensial berjalan polos di jaringancurl -I http://domain → 301 ke https
HSTS aktifBrowser menolak downgrade HTTP di kunjungan berikutnyaheader Strict-Transport-Security
X-Powered-By disembunyikanMengurangi sidik jari serverlihat temuan di atas
Header X-Frame-Options/frame-ancestorsMencegah clickjacking lewat iframecurl -sI di halaman publik

Empat poin HTTP terakhir dikonfigurasi di web server, bukan di Laravel — contoh tampilan server block Nginx-nya sudah kita susun di Web Server Configuration .

Cookies #

Header Set-Cookie di atas sekaligus membuktikan tiga atribut yang benar. Ketiganya dikendalikan konfigurasi, jadi pemeriksaannya cukup satu perintah per kunci:

bash
php artisan config:show session.secure
php artisan config:show session.http_only
php artisan config:show session.same_site

Output yang Dihasilkan:

text
  session.secure .................................................... true  


  session.http_only ................................................. true  


  session.same_site ................................................... lax  

secure menolak cookie lewat koneksi tanpa TLS, http_only melarang JavaScript membaca cookie sesi (pertahanan XSS), dan same_site=lax meredam CSRF — ketiganya sudah dibedah di Session Security .

Database dan Backup #

PemeriksaanMengapaVerifikasi
Kredensial kuat + user khusus per aplikasiBlast radius insiden menyempittinjau DB_USERNAME/DB_PASSWORD
User database tanpa hak DROP/GRANTAplikasi hanya butuh DML + DDL terkontrolSHOW GRANTS di MySQL
Backup terjadwal dan pernah dipulihkanBackup yang tak teruji bukan backupuji restore seperti di Rollback

Kode Aplikasi #

Tiga poin kategori ini diverifikasi dengan membaca kode, bukan menjalankan perintah — jadikan bagian dari review menjelang rilis. Pastikan validasi berjalan di setiap pintu masuk data (Konsep Validation ), properti $fillable di setiap model sudah diaudit terhadap kolom sensitif (Mass Assignment Protection ), dan endpoint authentikasi dibatasi rate limiter (Rate Limiting ).

Operasional dan Rahasia #

Kategori penjaga setelah aplikasi hidup:

PemeriksaanMengapaVerifikasi
/up terjangkau dari luarUptime monitoring punya kontrakcurl https://domain/up → 200
Halaman error kustom tanpa detail teknisError 500 tanpa jejak internalCustom Error Pages
Alert error menyalaInsiden diketahui dalam menitkirim exception uji seperti di Logging dan Monitoring
Rotasi log aktifDisk tidak habis diam-diamls storage/logs/ per tanggal

Terakhir, soal rahasia: satu-satunya tempat yang boleh menyimpannya adalah .env di server, dan berkas itu harus dipastikan tidak pernah menyentuh repositori. Dua pemeriksaan di sandbox kita:

bash
grep -n "^\.env" .gitignore

Output yang Dihasilkan:

text
3:.env
4:.env.backup
5:.env.production
bash
rg -n "DB_PASSWORD=|APP_KEY=base64" --glob '!.env' --glob '!vendor' .

Output yang Dihasilkan:

text
(tidak ada hasil)

Pencarian kedua menyapu seluruh repositori di luar .env dan vendor/ — hasil kosong berarti tidak ada kredensial yang tertinggal di kode, konfigurasi, ataupun skrip. Kebiasaan yang menyertainya — rotasi kredensial saat personel keluar, secrets manager untuk tim besar — sudah dibahas di Secret Management .

Proses, Bukan Hanya Config #

Dua baris terakhir daftar periksa ini tidak bisa diverifikasi dengan perintah apa pun. Audit keamanan menyeluruh pernah dijalankan (kerangkanya di Security Auditing ) dengan tanggal yang tercatat, dan jalur rollback benar-benar pernah dipraktikkan — bukan sekadar diyakini — sebagaimana diuji di Rollback dan Recovery . Checklist adalah foto kondisi hari ini; keduanya adalah jaminan bahwa besok tetap aman ketika kondisinya berubah.

Daftar panjang ini memang terasa banyak, tetapi justru itu ukuran kematangannya: setiap baris pernah dibuat kita tersandung di chapter-chapter sebelumnya, dan sekarang tinggal dicoret satu per satu. Dengan seluruh section Deployment dan Production tuntas, aplikasi Toko Budi kita siap menerima pengunjung pertama — dan saat mereka datang, semua sistem yang kita bangun sudah berjalan di belakangnya tanpa menunggu kita memegang tangan mereka.