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:
| Pemeriksaan | Mengapa | Verifikasi |
|---|---|---|
APP_ENV=production | Mode produksi menolak perintah berbahaya tanpa --force | php artisan config:show app.env |
APP_DEBUG=false | true membocorkan stack trace, path, dan kredensial ke pengunjung | php artisan config:show app.debug |
APP_KEY terpasang dan bukan nilai bawaan | Enkripsi session dan cookie bergantung padanya | potongan pemeriksa di bawah |
Kita jalankan keduanya di sandbox dengan .env bergaya produksi:
php artisan config:show app.env
php artisan config:show app.debugOutput yang Dihasilkan:
app.env ......................................................... production
app.debug ............................................................ false Untuk kunci aplikasi, pemeriksaan cukup memastikan prefix base64: ada tanpa mencetak nilainya ke terminal:
$key = config('app.key');
echo 'app.key terpasang : '.(str_starts_with($key, 'base64:')
? 'ya (base64, panjang '.strlen($key).' karakter)'
: 'TIDAK');Output yang Dihasilkan:
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:
curl -sI http://127.0.0.1:8018/Output yang Dihasilkan (isi cookie dipangkas):
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=laxBaris 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:
| Pemeriksaan | Mengapa | Verifikasi |
|---|---|---|
| HTTPS dipaksa untuk semua request | Tanpa TLS, kredensial berjalan polos di jaringan | curl -I http://domain → 301 ke https |
| HSTS aktif | Browser menolak downgrade HTTP di kunjungan berikutnya | header Strict-Transport-Security |
X-Powered-By disembunyikan | Mengurangi sidik jari server | lihat temuan di atas |
Header X-Frame-Options/frame-ancestors | Mencegah clickjacking lewat iframe | curl -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:
php artisan config:show session.secure
php artisan config:show session.http_only
php artisan config:show session.same_siteOutput yang Dihasilkan:
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 #
| Pemeriksaan | Mengapa | Verifikasi |
|---|---|---|
| Kredensial kuat + user khusus per aplikasi | Blast radius insiden menyempit | tinjau DB_USERNAME/DB_PASSWORD |
User database tanpa hak DROP/GRANT | Aplikasi hanya butuh DML + DDL terkontrol | SHOW GRANTS di MySQL |
| Backup terjadwal dan pernah dipulihkan | Backup yang tak teruji bukan backup | uji 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:
| Pemeriksaan | Mengapa | Verifikasi |
|---|---|---|
/up terjangkau dari luar | Uptime monitoring punya kontrak | curl https://domain/up → 200 |
| Halaman error kustom tanpa detail teknis | Error 500 tanpa jejak internal | Custom Error Pages |
| Alert error menyala | Insiden diketahui dalam menit | kirim exception uji seperti di Logging dan Monitoring |
| Rotasi log aktif | Disk tidak habis diam-diam | ls 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:
grep -n "^\.env" .gitignoreOutput yang Dihasilkan:
3:.env
4:.env.backup
5:.env.productionrg -n "DB_PASSWORD=|APP_KEY=base64" --glob '!.env' --glob '!vendor' .Output yang Dihasilkan:
(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.