Kubernetes memang menyelesaikan masalah nyata, tetapi kebanyakan side project dan aplikasi produksi skala kecil tidak punya masalah sebesar itu. Yang mereka butuhkan sebenarnya hanya cara membangun image Docker, mendorongnya ke registry, dan menjalankannya di satu atau dua server tanpa downtime, tanpa perlu merawat control plane. Itulah celah yang diisi oleh Kamal 2.
Kamal adalah tool deployment dari Basecamp yang mengendalikan server yang sudah ada lewat SSH, dengan Docker biasa di baliknya. Versi 2 mengganti layer routing berbasis Traefik dengan reverse proxy khusus bernama kamal-proxy, yang akhirnya membuat rollout tanpa downtime dan rollback instan benar-benar praktis dijalankan di satu VPS. Panduan ini membahas satu siklus deployment lengkap: proxy, accessory, secrets, dan cara memulihkan rilis yang bermasalah.
Mengapa Kamal 2 Dibanding Kubernetes
Kubernetes layak dengan kompleksitasnya pada skala tertentu: banyak service, banyak tim, autoscaling di banyak node. Di bawah skala itu, control plane, etcd, dan layer networking hanya menambah beban operasional tanpa manfaat sepadan, dan kebanyakan developer solo atau tim kecil akhirnya menghabiskan lebih banyak jam belajar dialek YAML daripada merilis fitur. Kamal menyasar ruang di antara satu perintah docker run dan sebuah cluster penuh, mengambil bagian dari orkestrasi container yang benar-benar berguna untuk deployment kecil — build image, health check, dan restart yang terkoordinasi — sambil membuang bagian yang hanya bermanfaat pada skala besar.
- Tidak ada control plane yang perlu ditambal, diupgrade, atau membuat Anda terjaga tengah malam
- Berjalan di server mana pun yang bisa diakses lewat SSH — VPS murah, bare metal, atau VM cloud
- Deploy hanyalah perintah SSH yang membungkus perintah docker CLI standar, sehingga kegagalan mudah dipahami
- Rollout tanpa downtime dan rollback sudah built-in lewat kamal-proxy, bukan tambahan terpisah
Kamal tidak terikat pada satu framework. Dibangun untuk aplikasi Rails, tetapi bisa dipakai untuk aplikasi apa pun yang bisa dikemas jadi image Docker dan punya endpoint health check HTTP — Node, Next.js, Django, atau binary statis semuanya memenuhi syarat.
Menyiapkan Konfigurasi Deploy
Semua yang dilakukan Kamal diatur oleh satu file YAML, config/deploy.yml, ditambah file secrets. Konfigurasi berikut menyasar satu server, membangun image, mendorongnya ke registry, dan mengatur kamal-proxy untuk mengarahkan traffic serta menjalankan health check ke aplikasi.
# config/deploy.yml
service: myapp
image: myregistry/myapp
servers:
web:
hosts:
- 203.0.113.10
labels:
traefik.http.routers.myapp.rule: Host(`myapp.example.com`)
proxy:
ssl: true
host: myapp.example.com
app_port: 3000
healthcheck:
path: /up
interval: 1
timeout: 5
registry:
server: ghcr.io
username: myuser
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
NODE_ENV: production
secret:
- DATABASE_URL
- REDIS_URLBagian proxy adalah bagian yang paling penting. Kamal-proxy mengirim request GET ke path health check setiap satu detik, dan baru mengalihkan traffic ke container baru setelah menerima respons sukses. Traffic lama dikeringkan dari container sebelumnya sebelum dihentikan, itulah yang membuat pergantian ini tidak terasa oleh pengguna.
Apa Yang Terjadi Saat Deploy Berjalan
Menjalankan perintah deploy memicu urutan langkah yang penting dipahami, karena sebagian besar kegagalan deploy terjadi pada salah satu dari empat langkah ini, dan pesan error biasanya langsung menunjukkan langkah mana yang gagal. Membaca output Kamal baris demi baris pada beberapa deploy pertama Anda akan sangat membantu nantinya, karena Anda jadi tahu tahap mana — build, push, pull, atau health check — yang harus diperiksa saat suatu saat terjadi masalah di produksi.
- Kamal membangun image Docker secara lokal atau di remote builder, memberi tag, lalu mendorongnya ke registry yang dikonfigurasi
- Setiap server target menarik image baru dan menjalankan container baru berdampingan dengan container yang sedang berjalan
- Kamal-proxy memantau path health check container baru sampai merespons sehat, lalu mengalihkan routing secara atomik ke container tersebut
- Container sebelumnya dikeringkan dari request yang masih berjalan lalu dihentikan, dan image lama dibersihkan setelah periode retensi tertentu
| Perintah | Fungsinya | Kapan dijalankan |
|---|---|---|
| kamal setup | Menyiapkan Docker, kamal-proxy, dan direktori di server baru | Sekali saja, sebelum deploy pertama ke host baru |
| kamal deploy | Membangun, mendorong, dan merilis aplikasi tanpa downtime | Setiap kali rilis |
| kamal rollback | Mengembalikan ke tag image yang pernah dideploy sebelumnya | Segera setelah rilis bermasalah terdeteksi |
| kamal accessory boot | Menjalankan atau merestart service pendukung seperti database | Saat menyiapkan atau memperbarui container dependency |
Menjalankan Postgres Dan Redis Sebagai Accessory
Accessory adalah istilah Kamal untuk service pendukung yang dibutuhkan aplikasi tetapi bukan bagian dari rollout tanpa downtime — database, cache, queue. Semuanya dideklarasikan di file deploy.yml yang sama, tetapi dikelola dengan lifecycle terpisah lewat perintah kamal accessory, bukan kamal deploy. Pemisahan ini ada karena restart database secara mendasar berbeda dari restart aplikasi: Anda tidak bisa begitu saja menjalankan dua container Postgres berdampingan lalu mengalihkan traffic di antaranya seperti kamal-proxy mengalihkan antar container aplikasi, karena data itu sendiri berada di satu volume yang sama.
# config/deploy.yml
accessories:
postgres:
image: postgres:16
host: 203.0.113.10
port: "127.0.0.1:5432:5432"
env:
clear:
POSTGRES_DB: myapp
secret:
- POSTGRES_PASSWORD
directories:
- postgres-data:/var/lib/postgresql/data
redis:
image: redis:7
host: 203.0.113.10
port: "127.0.0.1:6379:6379"
directories:
- redis-data:/dataAccessory tidak mendapat update tanpa downtime. Merestart Postgres atau Redis lewat kamal accessory reboot menyebabkan koneksi terputus sebentar saat container direstart, jadi jadwalkan perubahan accessory di jam traffic rendah dan pastikan aplikasi Anda bisa mencoba ulang koneksi database yang terputus dengan baik.
Mengelola Secrets Dengan Aman
Secara default Kamal membaca secrets dari file .kamal/secrets, yang sebaiknya tidak pernah dimasukkan ke git. File ini mendukung override per destinasi, jadi nilai di .kamal/secrets.production hanya berlaku saat deploy ke destinasi itu, sementara .kamal/secrets-common berlaku di semua tempat.
- Referensikan nama secret di deploy.yml lewat env.secret, dan Kamal akan menyuntikkan nilai sebenarnya dari file secrets lokal saat deploy — nilainya tidak pernah menyentuh repository Anda
- Kredensial registry, API key, dan URL database semuanya mengikuti pola yang sama: deklarasikan namanya di config, simpan nilainya secara lokal atau ambil dari password manager
- Rotasi secret dilakukan dengan memperbarui file lokal lalu menjalankan kamal env push diikuti redeploy service yang terdampak
Melakukan Rollback Saat Rilis Bermasalah
Setiap deploy menyisakan image container sebelumnya di server selama periode retensi tertentu, itulah yang membuat rollback cepat — tidak perlu build ulang atau pull dari registry. Cari dulu tag image yang ingin dikembalikan, lalu rollback langsung ke tag tersebut. Sebaiknya latih perintah ini di server staging sebelum benar-benar membutuhkannya di produksi, sehingga sintaks yang tepat dan tampilan daftar container sudah familiar saat insiden nyata terjadi dan setiap detik downtime sangat berarti.
# see exited containers from previous deploys
kamal app containers -q
# roll back to a specific image tag
kamal rollback abc1234
# roll a proxy restart across hosts one at a time
kamal proxy reboot --rollingKarena rollback memakai image yang sudah ditarik sebelumnya, prosesnya hampir secepat pergantian traffic saat deploy awal. Tidak ada langkah build dan tidak ada round trip ke registry, sehingga rilis bermasalah dari sepuluh menit lalu bisa dibatalkan dalam hitungan detik.
Multi Server Dan Restart Bergilir
Untuk aplikasi yang berjalan di lebih dari satu host, secara default Kamal mendeploy ke semua server secara paralel, tetapi Anda bisa memilih strategi rolling agar hanya sebagian server yang diperbarui pada satu waktu, sementara sisanya tetap melayani traffic. Ini paling penting untuk maintenance level proxy, seperti merotasi sertifikat SSL atau memperbarui image proxy itu sendiri, di mana Anda ingin dampak yang benar-benar tidak terlihat meski infrastruktur di depan aplikasi Anda sedang direstart.
Mulailah dengan satu server meskipun Anda berencana scale out nanti. Format konfigurasi Kamal membuat penambahan host kedua atau ketiga hanya perubahan satu baris di daftar hosts — Anda tidak perlu merancang untuk multi server dari hari pertama.
Kamal 2 tidak akan menggantikan Kubernetes untuk platform besar dengan banyak tim, tetapi untuk sebagian besar side project, produk SaaS kecil, dan backend satu tim, ia menghilangkan satu kategori penuh kompleksitas operasional sambil tetap memberikan deploy tanpa downtime dan cerita rollback yang bersih, hal yang dulunya membutuhkan control plane untuk bisa dilakukan dengan benar. Jika Anda sudah punya VPS dan image Docker, cara tercepat untuk merasakan bedanya adalah menjalankan kamal setup sekali lalu menyaksikan deploy tanpa downtime pertama Anda selesai dalam waktu kurang dari satu menit.

