Daftar periksa deployment

Env, migration, dan caching config, route, serta view sebelum rilis.

Daftar isi

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.

env Contoh: kunci utama pada .env untuk server produksi
APP_ENV=production
APP_DEBUG=false
APP_URL=https://catatan.example.test
DB_CONNECTION=sqlite
QUEUE_CONNECTION=database
SESSION_DRIVER=database

Nilai 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.

bash
# memeriksa mode aplikasi tanpa membuka berkas .env
cd ~/aplikasi-catatan
php artisan about --only=environment
text Keluaran
  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 .................................................................. en

Keluaran 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.

bash
# memeriksa status migration pada database
cd ~/aplikasi-catatan
php artisan migrate:status
text Keluaran
  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] Ran

Setiap 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.

bash
# menerapkan migration tanpa konfirmasi interaktif
cd ~/aplikasi-catatan
php artisan migrate --force
text Keluaran
   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.

bash
# meng-cache konfigurasi lalu membersihkannya agar proyek uji tetap bersih
cd ~/aplikasi-catatan
php artisan config:cache
php artisan config:clear
text Keluaran
   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.

bash
# meng-cache daftar route lalu membersihkannya kembali
cd ~/aplikasi-catatan
php artisan route:cache
php artisan route:clear
text Keluaran
   INFO  Routes cached successfully.

   INFO  Route cache cleared successfully.
bash
# mengompilasi templat Blade lalu membersihkannya kembali
cd ~/aplikasi-catatan
php artisan view:cache
php artisan view:clear
text Keluaran
   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.

bash
# tidak-dijalankan
# membangun seluruh cache aplikasi sekaligus
cd ~/aplikasi-catatan
php artisan optimize

Keluaran berikut menunjukkan empat tahap yang dikerjakan perintah tersebut, lengkap dengan durasinya.

text Hasil perintah php artisan optimize
   INFO  Caching framework bootstrap, configuration, and metadata.

  config ......................................................... 7.92ms DONE
  events ......................................................... 0.94ms DONE
  routes ......................................................... 7.34ms DONE
  views ......................................................... 34.62ms DONE

Keempat 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.

bash periksa-produksi.sh
#!/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
fi
text Keluaran
Pemeriksaan 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 ditulis

Keluaran 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.

LangkahPerintahTujuan
Memeriksa mode aplikasiphp artisan aboutmemastikan APP_ENV dan APP_DEBUG sesuai produksi
Menyelaraskan skemaphp artisan migrate --forcemenerapkan migration tanpa konfirmasi interaktif
Meng-cache konfigurasiphp artisan config:cachemengganti pembacaan .env pada setiap permintaan
Meng-cache routephp artisan route:cachemempercepat pencocokan rute
Meng-cache viewphp artisan view:cachemengompilasi templat Blade lebih dahulu
Menyiapkan tautan penyimpananphp artisan storage:linkmenghubungkan 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.

bash
# memastikan tautan penyimpanan publik sudah terpasang
cd ~/aplikasi-catatan
rm -f public/storage
php artisan storage:link
text Keluaran
   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=production dan APP_DEBUG=false adalah dua kunci .env yang paling menentukan keamanan rilis, dan keduanya diperiksa melalui php artisan about.
  • Migration dijalankan dengan --force agar rilis tidak menggantung pada konfirmasi interaktif, sedangkan migrate:status menunjukkan sisa perbedaan skema.
  • Cache konfigurasi, route, dan view dibangun ulang pada setiap rilis, dan selama cache konfigurasi aktif, berkas .env tidak dibaca lagi.
  • Skrip periksa-produksi.sh mengubah daftar periksa menjadi pemeriksaan yang dapat dijalankan ulang dengan keluaran yang mudah dibaca.

Referensi#