Kegagalan rilis ke server produksi paling sering bukan karena kode, melainkan karena lingkungan yang tidak konsisten dengan mesin pengembangan. Topik ini membahas daftar periksa deployment aplikasi catatan, yaitu mode aplikasi pada berkas .env, penerapan migration dengan opsi --force, pembangunan cache konfigurasi, route, dan view, serta skrip pemeriksaan yang dapat dijalankan ulang. Setelah topik ini dibaca, urutan langkah rilis dapat dieksekusi berulang dan setiap tahapnya memiliki keluaran yang dapat dicocokkan.
Mode aplikasi dan berkas .env#
Berkas .env menyimpan konfigurasi yang berbeda antara mesin pengembangan dan server produksi, seperti kredensial database dan kunci aplikasi. Berkas ini tidak pernah dimasukkan ke repository karena isinya berlaku per lingkungan, sehingga server produksi selalu memiliki salinannya sendiri. Dua kunci yang paling menentukan keamanan rilis adalah APP_ENV dan APP_DEBUG.
APP_ENV=production
APP_DEBUG=false
APP_URL=https://catatan.example.test
DB_CONNECTION=sqlite
QUEUE_CONNECTION=database
SESSION_DRIVER=databaseNilai APP_ENV=production mengaktifkan perilaku yang lebih ketat di seluruh framework, misalnya perintah Artisan yang mengubah data akan menuntut konfirmasi terlebih dahulu. Nilai APP_DEBUG=false menonaktifkan halaman pelaporan error yang rinci, karena halaman itu menampilkan isi konfigurasi dan lingkungan aplikasi kepada siapa pun yang membuka URL-nya saat terjadi error. Kedua nilai ini dapat diperiksa tanpa membuka berkas .env melalui perintah about.
# memeriksa mode aplikasi tanpa membuka berkas .env
cd ~/aplikasi-catatan
php artisan about --only=environment Environment ................................................................
Application Name ................................................... Laravel
Laravel Version .................................................... 13.39.0
PHP Version ......................................................... 8.3.29
Composer Version .................................................... 2.11.1
Environment .......................................................... local
Debug Mode ......................................................... ENABLED
URL ......................................................... localhost:8000
Maintenance Mode ....................................................... OFF
Timezone ............................................................... UTC
Locale .................................................................. enKeluaran di atas diambil dari proyek uji yang masih menggunakan mode local dengan Debug Mode ENABLED, sehingga keduanya perlu diganti pada server produksi sesuai contoh .env sebelumnya. Opsi --only menyaring keluaran ke bagian tertentu, sehingga pemeriksaan tetap ringkas meskipun keluaran lengkapnya panjang. Pemeriksaan ini menjadi langkah pertama daftar periksa karena seluruh langkah berikutnya menyesuaikan diri dengan mode aplikasi.
Migration pada server#
Migration pada server produksi dijalankan dengan perintah php artisan migrate --force. Opsi --force diperlukan karena pada mode production Artisan meminta konfirmasi sebelum menerapkan migration, dan konfirmasi interaktif semacam itu membuat proses rilis otomatis menggantung tanpa pernah selesai. Sebelum perintahnya dijalankan, status migration yang sudah berjalan diperiksa terlebih dahulu.
# memeriksa status migration pada database
cd ~/aplikasi-catatan
php artisan migrate:status Migration name .............................................. Batch / Status
0001_01_01_000000_create_users_table ............................... [1] Ran
0001_01_01_000001_create_cache_table ............................... [1] Ran
0001_01_01_000002_create_jobs_table ................................ [1] Ran
2026_11_03_003023_create_categories_table .......................... [1] Ran
2026_11_03_003024_create_notes_table ............................... [1] Ran
2026_11_03_085521_create_notifications_table ....................... [1] Ran
2026_11_03_212653_create_personal_access_tokens_table .............. [1] RanSetiap baris menunjukkan migration beserta nomor batch-nya, yaitu gelombang rilis saat migration itu diterapkan. Nomor batch yang naik berarti database di server mengikuti ritme rilis, sedangkan migration yang hilang dari daftar menandakan rilis belum menyentuh server tersebut. Setelah daftar status selaras dengan kode, perintah migrate --force menjadi pemeriksaan penutup.
# menerapkan migration tanpa konfirmasi interaktif
cd ~/aplikasi-catatan
php artisan migrate --force INFO Nothing to migrate.Pesan Nothing to migrate. berarti skema database di server sudah sama dengan definisi migration pada kode, sehingga rilis tanpa migration baru memang tidak mengubah apa pun. Rilis yang membawa migration baru akan menampilkan daftarnya pada keluaran yang sama. Perintah ini tetap dijalankan pada setiap rilis karena keluarannya konsisten, baik ketika ada maupun ketika tidak ada pekerjaan tersisa.
Cache konfigurasi, route, dan view#
Setiap permintaan yang masuk mendorong Laravel membaca banyak berkas, mulai dari .env, berkas konfigurasi di config/, daftar route, hingga templat Blade. Perintah caching menggabungkan sumber-sumber itu menjadi berkas jadi yang dibaca sekali, sehingga jumlah pembacaan berkas pada setiap permintaan turun drastis. Ketiganya dibangun pada setiap rilis karena isinya mengikuti kode terbaru.
# meng-cache konfigurasi lalu membersihkannya agar proyek uji tetap bersih
cd ~/aplikasi-catatan
php artisan config:cache
php artisan config:clear INFO Configuration cached successfully.
INFO Configuration cache cleared successfully.Perintah config:cache menyalin seluruh nilai konfigurasi, termasuk yang dibaca dari .env, ke dalam satu berkas cache. Sejak itu .env tidak dibaca lagi pada setiap permintaan, sehingga penyuntingan .env di server tidak berpengaruh sebelum cache dibangun ulang atau dibersihkan. Perilaku ini berlaku pula pada nilai APP_KEY yang digunakan session, sehingga proses yang membaca konfigurasi selama cache aktif dapat berperilaku berbeda dari biasanya. Pada proyek uji, cache langsung dibersihkan agar percobaan dapat diulang tanpa efek sisa, sedangkan pada server produksi hasilnya dibiarkan terpasang.
Dua cache lainnya bekerja dengan pola yang sama. Cache route memadatkan daftar rute menjadi satu berkas, sedangkan cache view mengompilasi seluruh templat Blade lebih dahulu. Keduanya diuji pada proyek uji dengan pola cache dan clear yang berpasangan, sebagaimana cache konfigurasi sebelumnya.
# meng-cache daftar route lalu membersihkannya kembali
cd ~/aplikasi-catatan
php artisan route:cache
php artisan route:clear INFO Routes cached successfully.
INFO Route cache cleared successfully.# mengompilasi templat Blade lalu membersihkannya kembali
cd ~/aplikasi-catatan
php artisan view:cache
php artisan view:clear INFO Blade templates cached successfully.
INFO Compiled views cleared successfully.Seluruh langkah caching di atas dapat digantikan dengan satu perintah php artisan optimize, yang membangun cache konfigurasi, event, route, dan view sekaligus.
# tidak-dijalankan
# membangun seluruh cache aplikasi sekaligus
cd ~/aplikasi-catatan
php artisan optimizeKeluaran berikut menunjukkan empat tahap yang dikerjakan perintah tersebut, lengkap dengan durasinya.
INFO Caching framework bootstrap, configuration, and metadata.
config ......................................................... 7.92ms DONE
events ......................................................... 0.94ms DONE
routes ......................................................... 7.34ms DONE
views ......................................................... 34.62ms DONEKeempat baris DONE pada keluaran itu adalah keadaan yang diharapkan pada akhir rilis, sedangkan pembongkaran kembali ke keadaan awal dilakukan dengan php artisan optimize:clear.
Skrip pemeriksaan otomatis#
Langkah yang mengandalkan ingatan mudah terlewat, sehingga pemeriksaan konfigurasi sebaiknya diotomatisasi menjadi skrip. Skrip berikut membaca kunci utama pada .env, memeriksa keberadaan APP_KEY tanpa menampilkan nilainya, dan menguji apakah direktori storage dapat ditulis. Yang ditampilkan hanya konfigurasi yang tidak sensitif, sehingga skripnya aman untuk ditempelkan pada keluaran rilis.
#!/usr/bin/env bash
# Pemeriksaan konfigurasi produksi dasar untuk aplikasi Laravel.
# Pemakaian: bash periksa-produksi.sh [direktori-proyek]
PROYEK="${1:-$HOME/aplikasi-catatan}"
if [ ! -f "$PROYEK/.env" ]; then
echo "ERROR: berkas .env tidak ditemukan di $PROYEK"
else
ambil() {
grep -E "^$1=" "$PROYEK/.env" | tail -n 1 | cut -d= -f2- || true
}
echo "Pemeriksaan konfigurasi: $PROYEK"
echo "APP_ENV : $(ambil APP_ENV)"
echo "APP_DEBUG : $(ambil APP_DEBUG)"
echo "APP_URL : $(ambil APP_URL)"
echo "DB_CONNECTION : $(ambil DB_CONNECTION)"
echo "QUEUE_CONNECTION : $(ambil QUEUE_CONNECTION)"
echo "SESSION_DRIVER : $(ambil SESSION_DRIVER)"
if [ -z "$(ambil APP_KEY)" ]; then
echo "APP_KEY : BELUM DISET"
else
echo "APP_KEY : sudah diset (nilainya tidak ditampilkan)"
fi
if [ "$(ambil APP_DEBUG)" = "true" ]; then
echo "Peringatan : APP_DEBUG masih true, matikan sebelum rilis"
else
echo "APP_DEBUG : aman untuk produksi"
fi
if [ -w "$PROYEK/storage" ]; then
echo "storage/ : dapat ditulis"
else
echo "Peringatan : storage/ tidak dapat ditulis"
fi
fiPemeriksaan konfigurasi: /home/kal/aplikasi-catatan
APP_ENV : local
APP_DEBUG : true
APP_URL : http://localhost:8000
DB_CONNECTION : sqlite
QUEUE_CONNECTION : database
SESSION_DRIVER : database
APP_KEY : sudah diset (nilainya tidak ditampilkan)
Peringatan : APP_DEBUG masih true, matikan sebelum rilis
storage/ : dapat ditulisKeluaran di atas diambil dari proyek uji yang masih dalam mode local, sehingga skripnya menampilkan peringatan APP_DEBUG masih true. Peringatan semacam itulah yang menjadi tujuan skrip ini, yaitu membuat keadaan yang keliru terlihat sebelum rilis, bukan setelahnya. Skrip menerima satu argumen berupa direktori proyek, sehingga pada server produksi cukup dipanggil dengan bash periksa-produksi.sh /var/www/aplikasi-catatan.
Daftar periksa lengkap#
Tabel berikut merangkum urutan langkah rilis beserta perintahnya. Setiap langkahnya telah dipraktikkan sepanjang topik ini, sehingga keluaran yang diharapkan dapat dicocokkan dengan contoh di atas.
| Langkah | Perintah | Tujuan |
|---|---|---|
| Memeriksa mode aplikasi | php artisan about | memastikan APP_ENV dan APP_DEBUG sesuai produksi |
| Menyelaraskan skema | php artisan migrate --force | menerapkan migration tanpa konfirmasi interaktif |
| Meng-cache konfigurasi | php artisan config:cache | mengganti pembacaan .env pada setiap permintaan |
| Meng-cache route | php artisan route:cache | mempercepat pencocokan rute |
| Meng-cache view | php artisan view:cache | mengompilasi templat Blade lebih dahulu |
| Menyiapkan tautan penyimpanan | php artisan storage:link | menghubungkan public/storage ke storage/app/public |
Langkah terakhir pada tabel bersifat sekali jalan, tetapi tetap dimasukkan ke dalam daftar karena server yang baru disiapkan belum memilikinya. Pada proyek uji, tautan yang lama dihapus lebih dahulu sebelum perintahnya dijalankan, sehingga keluaran pembuatan tautan selalu sama pada setiap eksekusi. Pada server produksi, perintah storage:link cukup dijalankan sekali, dan apabila tautan sudah ada, perintah yang sama melaporkan bahwa tautan sudah terpasang tanpa mengubah apa pun.
# memastikan tautan penyimpanan publik sudah terpasang
cd ~/aplikasi-catatan
rm -f public/storage
php artisan storage:link INFO The [public/storage] link has been connected to [storage/app/public].Pesan INFO itu menyatakan tautan baru saja dihubungkan kembali ke storage/app/public. Apabila perintah dijalankan tanpa menghapus tautan lama terlebih dahulu, keluaran berubah menjadi pemberitahuan bahwa tautan sudah terpasang, dan kode keluar tetap 0 karena keadaan yang diminta sudah terpenuhi.
Kesalahan umum#
Kesalahan pertama adalah menyunting .env di server yang konfigurasinya masih di-cache. Seluruh perubahan tidak terlihat oleh aplikasi karena .env tidak dibaca lagi sejak config:cache dijalankan, dan gejalanya sulit dilacak karena konfigurasi lama terus digunakan. Setelah setiap penyuntingan, cache harus dibangun ulang dengan config:cache atau dilepas dengan config:clear.
Kesalahan kedua adalah menjalankan php artisan migrate tanpa opsi --force pada skrip rilis. Pada mode production, perintah itu berhenti dan menunggu masukan konfirmasi, sehingga proses rilis otomatis menggantung tanpa pesan kesalahan yang jelas. Skrip rilis selalu menggunakan --force, sedangkan konfirmasi manual hanya dilakukan ketika rilis dijalankan dari terminal oleh operator.
Kesalahan ketiga adalah meninggalkan cache eksperimen pada mesin pengembangan. Setelah bereksperimen dengan config:cache, proyek terus membaca konfigurasi basi termasuk APP_KEY lama, sehingga session dan perilaku aplikasi berubah tanpa sebab yang terlihat. Kebiasaan yang tepat adalah menutup setiap percobaan caching dengan optimize:clear, sebagaimana pasangan cache dan clear pada blok contoh sepanjang topik ini.
Ringkasan#
APP_ENV=productiondanAPP_DEBUG=falseadalah dua kunci.envyang paling menentukan keamanan rilis, dan keduanya diperiksa melaluiphp artisan about.- Migration dijalankan dengan
--forceagar rilis tidak menggantung pada konfirmasi interaktif, sedangkanmigrate:statusmenunjukkan sisa perbedaan skema. - Cache konfigurasi, route, dan view dibangun ulang pada setiap rilis, dan selama cache konfigurasi aktif, berkas
.envtidak dibaca lagi. - Skrip
periksa-produksi.shmengubah daftar periksa menjadi pemeriksaan yang dapat dijalankan ulang dengan keluaran yang mudah dibaca.
Referensi#
- Deployment — Laravel — Panduan resmi optimasi produksi, termasuk cache konfigurasi, route, dan view.
- Configuration — Laravel
— Dokumentasi berkas
.envdan perilaku cache konfigurasinya. - Migrations — Laravel
— Dokumentasi perintah migrate, opsi
--force, danmigrate:status. - File Storage — Laravel
— Dokumentasi public disk beserta perintah
storage:link.