31 Maret 2026

Deploy Aplikasi ke Server dengan Mudah menggunakan Kamal

Pengalaman penulis berpindah dari Dokku ke Kamal untuk deployment menunjukkan bahwa Kamal menawarkan proses build yang lebih cepat karena build dilakukan di lokal, bukan di server, serta penggunaan storage yang lebih hemat karena server hanya perlu pull image dari local registry.

Waktu baca: ~ 4 menit

Saya sudah cukup lama menggunakan Dokku sebagai deployment tool. Saya bahkan menulis e-book yang bisa diunduh secara gratis di sini.

Sebelum menggunakan Dokku, saya cukup tertarik dengan Kamal. Tools besutan 37signals ini telah sukses membantu mereka selama proses cloud exit, tanpa ada kendala yang berarti. Sayangnya, saat saya hendak mencobanya, saat itu Kamal hanya mendukung remote image registry. Saya tidak ingin menambah biaya langganan hanya untuk container registry saja. Jadi, saya pending dulu.

Sejak versi 2.8.0, Kamal sudah resmi mendukung local container registry. Meskipun begitu, saya belum ada niatan untuk migrasi deployment tool dari Dokku ke Kamal untuk project-project personal saya yang sudah live di production. Saya tidak ingin menghadapi risiko yang tidak diinginkan.

Saat saya selesai mengembangkan website ini, saya baru bisa mencobanya. Saya berani mencobanya karena server website ini berbeda dengan server personal project saya, jadi nothing to lose. Dan jujur saja, saya kaget sekaligus takjub karena hanya butuh waktu 90 detik saja untuk build dan deploy aplikasi ke sebuah VPS 2 GB 1 vCPU! Di Dokku, proses ini bisa berlangsung sekitar 2 hingga 3 menit. Ini juga kalau tidak ada perubahan terhadap dependensinya ya. Kalau ada penambahan dependensi, proses instal dependensinya memakan waktu yang lebih lama lagi.

Kenapa Bisa Lebih Cepat?

Proses deploy lebih cepat karena proses build dilakukan di runtime yang sama dengan kamal diinstal, yang berarti komputer saya pribadi dengan spesifikasi yang pastinya jauh lebih mumpuni ketimbang spesifikasi di server. Sementara itu, di Dokku, proses build dilakukan di server.

Oleh karena itu, kalau pakai Dokku memang harus sering-sering membersihkan build cache supaya storage server tidak menumpuk. Sedangkan, Kamal tidak harus melakukannya, karena server sekarang tugasnya hanya pull image dari local registry dan menjalankan container baru berdasarkan image terbaru.

Kamal menggunakan SSH port forwarding supaya server bisa pull image dari local registry. Kalau belum kebayang dengan mekanisme SSH port forwarding, bayangkan ada sebuah terowongan rahasia yang hanya bisa diakses oleh server dan komputer dengan local registry. Server akan melakukan pull image dari local registry via terowongan/tunnel ini.

Jadi, pakai Kamal untuk deployment jauh lebih cepat dan hemat penyimpanan server ketimbang Dokku.

Prerequisite

Untuk deploy aplikasi ke VPS menggunakan Kamal, ada dua hal yang harus terpenuhi terlebih dahulu:

  1. Kamal sudah terinstall di komputer
  2. Komputer memiliki akses SSH ke server.

Kamal bisa digunakan dan diinstal menggunakan dua cara: via Ruby gem atau Docker.

Install via Ruby Gem:

gem install kamal

Install via Docker untuk MacOS:

alias kamal='docker run -it --rm -v "${PWD}:/workdir" -v "/run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock" -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/basecamp/kamal:latest'

Install via Docker untuk Linux:

alias kamal='docker run -it --rm -v "${PWD}:/workdir" -v "${SSH_AUTH_SOCK}:/ssh-agent" -v /var/run/docker.sock:/var/run/docker.sock -e "SSH_AUTH_SOCK=/ssh-agent" ghcr.io/basecamp/kamal:latest'

Saya asumsikan bahwa kamu sudah punya akses ke server via SSH, jadi kita lanjut saja.

Inisialisasi & Konfigurasi

Gunakan perintah kamal init untuk menginisialisasi Kamal di project kamu. Perintah ini akan menambahkan beberapa file berikut:

  • config/deploy.yml : file konfigurasi yang diperlukan untuk deployment
  • .kamal/secrets : file untuk mengatur environment variable yang bersifat confidential/rahasia.
  • kamal/hooks/ : folder berisi hook untuk menjalankan custom script di beberapa poin saat deployment berlangsung.

Secara default, perintah kamal deploy akan membaca file config/deploy.yml. Namun, kita juga bisa menambahkan config per environment. Misal, file config/deploy.staging.yml untuk environment staging. Perintah kamal deploy -d staging akan membaca konfigurasi tersebut.

Setelah inisialisasi, saatnya menyesuaikan file config/deploy.yml . Buka file tersebut, lalu:

  • Sesuaikan IP server ke servers/web
  • Sesuaikan domain ke proxy/host
  • Sesuaikan registry/server, registry/username, serta uncomment registry/password.
  • Tambahkan environment variable yang diperlukan. Di sini ada dua jenis environment variable:
    • clear: environment yang bersifat publik
    • secret: environment yang bersifat konfidensial
  • Sesuaikan ssh/user jika user yang akan digunakan untuk SSH ke server bukanlah user root

Clear environment variable nilainya di-set langsung di file konfigurasi, sedangkan secret environment variable nilainya di-set via .kamal/secrets, dan variable-nya dideklarasikan di file konfigurasi.

Setidaknya ada beberapa cara yang bisa digunakan untuk mengatur nilai-nilai secret environment variable.

  1. Set di environment variable di komputer lokal.
  2. Memakai password manager. Kamal secara resmi mendukung provider-provider berikut:
    1. 1Password
    2. LastPass
    3. Bitwarden
    4. Bitwarden Secrets Manager
    5. AWS Secrets Manager
    6. Doppler
    7. GCP Secrets Manager
    8. Passbolt

Selengkapnya, bisa cek https://kamal-deploy.org/docs/commands/secrets/.

Integrasi dengan pass Password Manager

Beberapa layanan password manager menyediakan free tier yang sangat cukup untuk project-project personal. Tapi, berkaca pada pengalaman-pengalaman sebelumnya, akan sangat repot kalau suatu waktu akun saya diblokir oleh penyedia layanan, yang pastinya akan sangat memengaruhi proses deployment.

Oleh karena itu, terbesit ide untuk menggunakan pass password manager. Saya pernah menulis tentang ini di sini. Rencana awal, saya hendak menyimpannya di dalam satu password store entry yang berisi JSON environment variable. Tapi pendekatan ini rawan terjadi error. Typo sedikit saja, deployment bisa gagal.

Sehingga, saya menggunakan pendekatan kedua: setiap pass entry hanya menyimpan nilai dari satu environment variable dengan format web/app-name/ENV_VAR. Misal, baik local registry dan remote registry, kita perlu mengatur nilai dari KAMAL_REGISTRY_PASSWORD. Nilai ini lalu disimpan di web/example/KAMAL_REGISTRY_PASSWORD dengan perintah pass insert -e web/example/KAMAL_REGISTRY_PASSWORD. Perintah tersebut akan menampilkan prompt untuk menginput nilai dari pass entry. Ketik/paste password-nya, lalu ketik Enter. Pass entry sudah berhasil dibuat.

Buka .kamal/secrets, lalu ubah KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD menjadi KAMAL_REGISTRY_PASSWORD=$(pass show web/example/KAMAL_REGISTRY_PASSWORD). Lakukan hal yang sama untuk environment variable yang lain.

Deployment

Setelah file konfigurasi dan secrets selesai diatur, jalankan perintah kamal setup. Perintah ini akan menyiapkan semuanya secara otomatis, dimulai dari instalasi Docker di server jika belum terinstal, sampai deployment untuk pertama kali berhasil dilakukan. Setelah proses deployment berhasil, untuk deployment-deployment selanjutnya bisa menjalankan perintah kamal deploy.

Kalau tidak ada error selama deployment, maka selamat! Website/webapp kamu sekarang sudah go live.

#Deployment