Deploy aman di CodeIgniter 4 tidak harus rumit. Untuk banyak aplikasi, Anda bisa mendapatkan proses rilis yang stabil dengan pola sederhana: pisahkan direktori release, arahkan symlink current ke versi aktif, siapkan .env dengan benar, jalankan migrasi secara hati-hati, aktifkan maintenance mode saat perlu, lalu lakukan smoke test dan health check sebelum trafik dibuka penuh.
Masalah yang paling sering muncul saat deploy bukan karena langkah deploy itu sendiri, melainkan karena perubahan konfigurasi, migrasi database yang tidak kompatibel, cache yang basi, atau aplikasi terlihat “up” tetapi endpoint penting sebenarnya gagal. Karena itu, artikel ini fokus pada langkah yang bisa langsung diterapkan pada proyek CodeIgniter 4 tanpa bergantung pada Docker atau pipeline yang kompleks.
Tujuan deploy yang aman di CodeIgniter 4
Untuk konteks artikel ini, deploy dianggap aman jika memenuhi empat hal:
- Rilis bisa dipromosikan dan dibatalkan cepat tanpa menyalin ulang seluruh aplikasi.
- Perubahan database terkendali dan tidak memutus versi lama maupun baru secara mendadak.
- Kondisi aplikasi bisa diverifikasi lewat smoke test, health check, dan log.
- Insiden mudah diisolasi karena struktur release dan observability cukup jelas.
Pola paling praktis untuk mencapai itu adalah immutable release directory + symlink current. Setiap rilis ditempatkan di direktori baru, lalu server diarahkan ke symlink yang menunjuk ke release aktif. Jika rilis gagal, rollback cukup dengan mengubah symlink ke release sebelumnya.
Struktur direktori release yang sederhana dan efektif
Contoh struktur di server:
/var/www/myapp/
├── current -> /var/www/myapp/releases/20260613-101500
├── releases/
│ ├── 20260612-221000/
│ ├── 20260613-101500/
│ └── 20260613-154000/
├── shared/
│ ├── .env
│ ├── writable/
│ │ ├── cache/
│ │ ├── logs/
│ │ ├── session/
│ │ └── uploads/
│ └── maintenance.flag
└── scripts/
├── deploy.sh
└── rollback.shPrinsipnya:
- Source code release berada di
releases/<timestamp>. - File yang persisten seperti
.env, log, cache, session, dan upload berada dishared/. - Symlink
currentmenunjuk ke release aktif.
Kenapa pola ini bekerja? Karena pergantian versi menjadi operasi file system yang cepat dan mudah dibalik. Anda tidak menimpa source code yang sedang berjalan, sehingga rollback tidak perlu git pull ulang atau menyalin file satu per satu.
Symlink yang biasanya diperlukan
Pada release baru, hubungkan file dan direktori persisten ke shared:
cd /var/www/myapp/releases/20260613-154000
ln -s /var/www/myapp/shared/.env .env
rm -rf writable
ln -s /var/www/myapp/shared/writable writablePastikan web server dan PHP-FPM memiliki izin tulis ke shared/writable. Salah izin direktori adalah penyebab umum aplikasi terlihat blank, gagal menulis session, atau tidak bisa membuat log.
Persiapan .env yang aman sebelum deploy
Di CodeIgniter 4, kesalahan konfigurasi .env sering lebih berbahaya daripada kesalahan kode. Sebelum rilis, validasi minimal:
- Environment tidak dalam mode pengembangan di produksi.
- Koneksi database mengarah ke host, port, nama database, dan kredensial yang benar.
- Base URL sesuai domain aktual aplikasi.
- Driver cache, session, dan email konsisten dengan lingkungan server.
- APP_KEY/secret atau variabel sensitif lain tidak berubah tanpa alasan jelas.
Contoh .env yang relevan secara umum:
CI_ENVIRONMENT = production
app.baseURL = 'https://app.contoh.com/'
database.default.hostname = 127.0.0.1
database.default.database = myapp
database.default.username = myapp_user
database.default.password = ganti_dengan_rahasia
database.default.DBDriver = MySQLi
app.sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler'
app.sessionSavePath = '/var/www/myapp/shared/writable/session'Catatan: Hindari menyimpan
.envproduksi di repository. Gunakan file dishared/.envagar setiap release baru memakai konfigurasi yang sama tanpa perlu menyalin ulang rahasia aplikasi.
Kesalahan umum pada .env
app.baseURLsalah, menyebabkan redirect aneh atau URL aset tidak valid.- Session path tidak writable, pengguna tiba-tiba logout atau login gagal.
- Koneksi database berbeda dari ekspektasi, migrasi berjalan ke database yang salah.
- Mode environment salah, detail error tampil ke publik atau logging terlalu minim.
Migrasi database yang aman: kompatibilitas dulu, baru cleanup
Bagian paling berisiko dalam deploy adalah migrasi database. Rollback source code sangat cepat dengan symlink, tetapi rollback database tidak selalu mudah. Karena itu, gunakan pendekatan backward-compatible migration sedapat mungkin.
Prinsip aman untuk migrasi
- Tambahkan dulu, hapus belakangan. Menambah kolom nullable atau tabel baru biasanya lebih aman dibanding langsung menghapus/rename kolom yang dipakai kode lama.
- Jangan gabungkan perubahan skema destruktif dengan rilis aplikasi besar jika bisa dipisah.
- Pastikan versi lama masih bisa berjalan setelah migrasi awal, setidaknya selama jendela rollback.
- Backup database atau siapkan snapshot jika perubahan bersifat kritis.
Contoh urutan yang lebih aman:
- Rilis 1: tambah kolom baru, kode mulai menulis ke kolom lama dan baru bila perlu.
- Rilis 2: baca dari kolom baru setelah data valid.
- Rilis 3: hapus kolom lama setelah dipastikan tidak dipakai.
Menjalankan migrasi di CodeIgniter 4
Jalankan migrasi dari direktori release baru, bukan dari current lama:
cd /var/www/myapp/releases/20260613-154000
php spark migrate --allJika aplikasi punya seeding yang memang diperlukan untuk data referensi, jalankan terpisah dan sadar risiko:
php spark db:seed InitialReferenceDataKenapa dari release baru? Karena Anda ingin memastikan kode migrasi yang sesuai dengan versi yang akan dipromosikan benar-benar yang dijalankan. Ini mengurangi mismatch antara source code dan skema database.
Kapan perlu maintenance mode?
Jika migrasi:
- mengunci tabel besar,
- mengubah struktur yang dipakai endpoint aktif,
- atau berpotensi membuat data sementara inkonsisten,
aktifkan maintenance mode sebelum migrasi dan matikan setelah verifikasi dasar selesai.
Untuk rilis yang sangat kecil dan migrasi kompatibel, maintenance mode kadang tidak perlu. Namun jika tim Anda belum punya observability yang baik, lebih aman memakai maintenance mode singkat daripada membiarkan pengguna mengalami error acak.
Maintenance mode yang sederhana tanpa komponen berlebih
Anda tidak perlu fitur kompleks. Cukup gunakan file penanda yang dibaca sangat awal oleh aplikasi atau web server. Misalnya buat file:
/var/www/myapp/shared/maintenance.flagLalu di bootstrap atau lapisan yang dieksekusi awal, kembalikan respons 503 untuk request umum. Implementasi tepatnya bisa berbeda, tetapi pola sederhananya seperti ini:
<?php
$flag = '/var/www/myapp/shared/maintenance.flag';
if (is_file($flag)) {
http_response_code(503);
header('Retry-After: 120');
echo 'Maintenance sementara. Coba beberapa saat lagi.';
exit;
}Kalau Anda menerapkannya di level aplikasi, pastikan endpoint internal yang dipakai operator untuk verifikasi tetap bisa diakses bila diperlukan, atau siapkan pengecualian berbasis IP. Trade-off-nya, pengecualian bisa menambah kompleksitas dan risiko salah konfigurasi.
Aktif/nonaktif maintenance mode:
touch /var/www/myapp/shared/maintenance.flag
rm -f /var/www/myapp/shared/maintenance.flagHealth check endpoint untuk CodeIgniter 4
Health check berbeda dari halaman beranda. Tujuannya bukan menampilkan UI, melainkan memberi sinyal cepat apakah aplikasi masih mampu merespons dengan dependensi minimum yang Anda anggap penting.
Apa yang sebaiknya dicek?
Untuk deployment CodeIgniter 4 yang pragmatis, cukup cek:
- aplikasi dapat merespons request,
- koneksi database berhasil,
- waktu server tercatat,
- versi release aktif terlihat.
Jangan memasukkan pengecekan yang terlalu berat atau memanggil banyak layanan eksternal, karena endpoint health check harus cepat dan andal. Jika terlalu kompleks, health check justru menambah sumber kegagalan.
Contoh endpoint health check
Misalnya tambahkan route dan controller sederhana.
// app/Config/Routes.php
$routes->get('/health', 'HealthController::index');<?php
namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use Config\Database;
class HealthController extends ResourceController
{
public function index()
{
$dbOk = false;
$error = null;
try {
$db = Database::connect();
$db->query('SELECT 1');
$dbOk = true;
} catch (\Throwable $e) {
$error = $e->getMessage();
}
$releaseFile = WRITEPATH . '../REVISION';
$release = is_file($releaseFile) ? trim((string) file_get_contents($releaseFile)) : 'unknown';
$status = $dbOk ? 200 : 503;
return $this->respond([
'status' => $dbOk ? 'ok' : 'degraded',
'database' => $dbOk ? 'ok' : 'error',
'release' => $release,
'time' => date(DATE_ATOM),
'error' => $dbOk ? null : $error,
], $status);
}
}Di setiap release, buat file REVISION agar mudah mengetahui versi yang aktif:
echo '20260613-154000' > /var/www/myapp/releases/20260613-154000/REVISIONJika endpoint /health mengembalikan 200 dan payload yang sesuai, Anda punya sinyal dasar bahwa release aktif, aplikasi hidup, dan database dapat dijangkau.
Tip: Jika endpoint ini dibuka ke publik, hindari menampilkan detail error mentah pada produksi. Simpan detail di log, tampilkan status ringkas pada respons publik.
Smoke test setelah deploy: cek alur penting, bukan semua fitur
Smoke test adalah verifikasi cepat bahwa fitur inti masih berjalan setelah deploy. Fokus pada jalur yang paling penting bagi bisnis dan paling sering rusak saat rilis.
Contoh smoke test minimal
- Halaman utama atau endpoint API utama merespons 200/302 yang benar.
- Login berhasil untuk akun uji.
- Endpoint database-heavy tetap bisa membaca data.
- Form atau aksi tulis sederhana berhasil jika aman dilakukan di produksi.
- Health check mengembalikan status sehat.
Contoh perintah manual yang bisa dipakai operator:
curl -I https://app.contoh.com/
curl -s https://app.contoh.com/health
curl -I https://app.contoh.com/loginJika aplikasi API, tambahkan satu request autentikasi atau request ke endpoint yang kritis. Tidak perlu menguji semua skenario; tujuan smoke test adalah mendeteksi kerusakan besar secepat mungkin sebelum dampaknya meluas.
Observability dasar: log, metrik, dan tanda error pasca-deploy
Setelah deploy, pertanyaan utama adalah: apakah aplikasi benar-benar sehat setelah menerima trafik nyata? Untuk menjawabnya, Anda butuh observability dasar, tidak harus sistem monitoring yang rumit.
Logging yang wajib ada
- Application log dari CodeIgniter 4 di
writable/logs. - Web server access/error log dari Nginx atau Apache.
- PHP-FPM log jika menggunakan PHP-FPM.
Saat deploy selesai, amati 5-15 menit pertama. Cari lonjakan:
- HTTP 500, 502, 503
Uncaught ExceptionDatabase connection failedAllowed memory size exhaustedPermission deniedSessionataucache write failed
Metrik yang relevan untuk pasca-deploy
Tanpa membahas tool tertentu, metrik dasar yang perlu dilihat:
- Error rate: persentase request gagal.
- Latency: apakah respons jadi jauh lebih lambat setelah rilis.
- Throughput: apakah jumlah request normal, turun, atau ada lonjakan retry.
- Database errors: koneksi putus, timeout, deadlock, query gagal.
- Resource server: CPU, memory, disk usage, terutama pada
writabledan log.
Jika Anda belum punya dashboard penuh, mulai dari yang sederhana: tail log, hitung error web server, dan cek status endpoint berkala via cron atau monitor eksternal.
Tanda-tanda error pasca-deploy yang sering terlewat
- Status 200 tetapi halaman rusak karena aset tidak termuat atau data kosong.
- Lonjakan login ulang karena session path salah atau cookie berubah.
- Query lambat mendadak karena indeks belum ada atau migrasi memengaruhi rencana eksekusi query.
- Hanya sebagian endpoint gagal karena route, middleware, atau konfigurasi base URL tidak konsisten.
- Health check lolos tetapi proses bisnis gagal karena health check terlalu dangkal.
Contoh alur deploy praktis dengan symlink current
Berikut contoh alur yang realistis dan mudah diaudit.
1. Siapkan release baru
RELEASE=20260613-154000
APP_DIR=/var/www/myapp
RELEASE_DIR=$APP_DIR/releases/$RELEASE
mkdir -p $RELEASE_DIR
cd $RELEASE_DIR
# Ambil source code sesuai mekanisme Anda
# misalnya git clone / rsync / artifact extract
echo $RELEASE > REVISION
ln -s $APP_DIR/shared/.env .env
rm -rf writable
ln -s $APP_DIR/shared/writable writable2. Install dependency dan optimasi seperlunya
cd $RELEASE_DIR
composer install --no-dev --prefer-dist --optimize-autoloaderJika proyek Anda memakai langkah build tambahan, jalankan di tahap ini. Pastikan build tidak bergantung pada file yang hanya ada di release lama.
3. Aktifkan maintenance mode bila diperlukan
touch /var/www/myapp/shared/maintenance.flag4. Jalankan migrasi
cd $RELEASE_DIR
php spark migrate --all5. Promosikan release dengan mengubah symlink
ln -sfn $RELEASE_DIR $APP_DIR/currentGunakan opsi yang membuat pembaruan symlink berlangsung atomik atau sedekat mungkin dengan itu di sistem Anda. Setelah symlink berubah, web server akan melayani kode dari release baru.
6. Lakukan smoke test dan health check
curl -I https://app.contoh.com/
curl -s https://app.contoh.com/health7. Matikan maintenance mode
rm -f /var/www/myapp/shared/maintenance.flag8. Pantau log setelah deploy
tail -f /var/www/myapp/shared/writable/logs/*Jika Anda menggunakan PHP-FPM atau web server terpisah, pantau juga log dari sana agar error bootstrap atau permission tidak terlewat.
Rollback cepat saat rilis gagal
Rollback harus dianggap sebagai fitur utama proses deploy, bukan rencana cadangan yang dipikirkan belakangan. Karena menggunakan symlink, rollback source code bisa sangat cepat.
Langkah rollback yang aman
- Aktifkan maintenance mode jika aplikasi sedang error berat atau menulis data yang berisiko inkonsisten.
- Alihkan symlink
currentke release sebelumnya yang diketahui stabil. - Verifikasi health check dan smoke test dasar.
- Biarkan maintenance mode tetap aktif sesaat jika ada dugaan masalah database yang belum jelas.
- Analisis log release gagal sebelum mencoba deploy ulang.
Contoh rollback:
APP_DIR=/var/www/myapp
PREV_RELEASE=/var/www/myapp/releases/20260613-101500
touch $APP_DIR/shared/maintenance.flag
ln -sfn $PREV_RELEASE $APP_DIR/current
curl -s https://app.contoh.com/health
rm -f $APP_DIR/shared/maintenance.flagBatasan rollback
Rollback source code tidak selalu menyelesaikan masalah jika migrasi database bersifat destruktif. Misalnya:
- kolom lama sudah dihapus,
- data sudah ditransformasikan tanpa jalur balik,
- seed mengganti data referensi penting.
Itulah alasan pendekatan migrasi kompatibel jauh lebih aman daripada mengandalkan rollback database penuh pada setiap rilis.
Cek status aplikasi setelah release aktif
Setelah symlink dipindah, verifikasi status aplikasi dari beberapa sudut:
- Endpoint publik: apakah home/login/API utama merespons sesuai harapan.
- Health check: apakah aplikasi dan database sehat.
- Release marker: apakah versi yang tampil sesuai release baru.
- Log: apakah ada error baru yang tidak muncul sebelum deploy.
- Database: apakah migrasi sudah tercatat dan tidak ada error lanjutan.
Checklist cepat status pasca-deploy:
[ ] current mengarah ke release yang benar
[ ] .env terbaca dari shared
[ ] writable dapat ditulis aplikasi
[ ] /health mengembalikan 200
[ ] login atau endpoint inti lolos smoke test
[ ] log aplikasi tidak menunjukkan exception baru
[ ] error rate dan latency tidak naik signifikanPostmortem ringan: format praktis setelah insiden deploy
Jika deploy gagal atau sempat menyebabkan gangguan, buat postmortem ringan. Tujuannya bukan mencari siapa yang salah, tetapi mencegah masalah yang sama terulang.
Contoh format postmortem
Gejala
- Setelah deploy, endpoint
/loginmengembalikan 500. - Health check awal 200, tetapi error meningkat saat trafik nyata masuk.
Dugaan akar masalah
- Session path di
.envmengarah ke direktori yang tidak writable. - Smoke test tidak mencakup login, hanya homepage dan health check.
Langkah isolasi
- Cek log CodeIgniter 4 di
writable/logs. - Konfirmasi error
Permission deniedpada session write. - Bandingkan
.envrelease baru dengan konfigurasi release stabil.
Tindakan rollback
- Aktifkan maintenance mode.
- Kembalikan symlink
currentke release sebelumnya. - Verifikasi login normal kembali.
Tindakan pencegahan
- Tambahkan validasi permission
shared/writableke script deploy. - Masukkan login ke smoke test wajib.
- Tambahkan health check internal untuk menulis session uji jika memang relevan dan aman.
Dengan format sesingkat ini pun, tim Anda sudah punya rekam jejak yang berguna untuk perbaikan proses deploy berikutnya.
Checklist deploy CodeIgniter 4 yang bisa langsung dipakai
- Pastikan backup/snapshot tersedia jika deploy menyentuh data penting.
- Siapkan release baru di
releases/<timestamp>. - Hubungkan
.envdanwritablekeshared. - Install dependency produksi.
- Validasi permission pada
shared/writable. - Aktifkan maintenance mode jika migrasi berisiko.
- Jalankan migrasi dari release baru.
- Ubah symlink
currentke release baru. - Jalankan smoke test dan cek endpoint
/health. - Nonaktifkan maintenance mode.
- Pantau log, error rate, dan latency 5-15 menit pertama.
- Jika ada masalah signifikan, rollback segera dan lakukan postmortem ringan.
Penutup
Deploy aman dengan rollback, log, dan health check di CodeIgniter 4 bisa dibangun dengan pendekatan yang sederhana, tanpa infrastruktur yang berlebihan. Kunci utamanya adalah memisahkan release dari data persisten, memakai symlink current untuk promosi dan rollback cepat, menjalankan migrasi yang kompatibel, serta memverifikasi hasil deploy lewat smoke test, health check, dan observability dasar.
Jika Anda baru ingin merapikan proses rilis, mulai dari tiga hal ini dulu: struktur release + symlink, endpoint health check, dan checklist rollback. Tiga komponen itu biasanya sudah cukup untuk mengurangi banyak insiden deploy yang umum pada proyek CodeIgniter 4.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!