Saya memutuskan untuk deploy Jekyll dengan Kamal
Suatu hari ayah saya memberitahu saya bahwa website travel miliknya tidak bisa diakses. Singkat cerita, instance Heroku gratis yang kami pakai sudah tidak bisa diakses lagi. Mungkin karena trik untuk mencegah instance gratisan selalu tetap up tidak lagi bisa dipakai. Apapun itu, saya sudah tidak punya selera lagi untuk menggunakan Heroku.
Mengapa bukan GitHub Pages?
Karena kalau pakai GitHub Pages, maka blog ini berakhir sampai di sini. Lanjutkan membaca jika kamu ingin mengetahui bagaimana mendeploy Jekyll dengan Kamal. Lagipula di masa sekarang, bare metal VPS sudah semakin ekonomis, plus lebih trendi ("Saya bisa SSH sendiri"™️).
Instalasi Jekyll
Jekyll adalah gem di Ruby yang digunakan untuk membuat website statis, jauh dibuat sebelum Gatsby atau Astro. Yang saya sukai dari jaman dulu sampai sekarang, instalasi Jekyll tidak ada yang berubah (Nice!). Cukup pakai gem aja: https://jekyllrb.com/docs/
gem install jekyll
jekyll new myblog
cd myblog
bundle exec jekyll serve
Maka Jekyll sudah siap diakses di https://localhost:4000
Instalasi Kamal
Kamal adalah tool untuk deploy menggunakan Docker. Karena menggunakan Docker, maka aplikasi yang dibungkus tidak harus aplikasi Ruby, apapun bisa™️. Untuk menginstall Kamal, diperlukan gem https://kamal-deploy.org/docs/installation/:
gem install kamal
kamal init
kamal init
akan membuat beberapa file, pertama kita konfigurasi deploy dengan config/deploy.yml
deploy.yml
File ini adalah konfigurasi utama untuk Kamal. Beberapa hal yang diperlukan adalah:
- beri nama aplikasimu pada
service
- beri nama pada image aplikasimu pada
image
- beri IP address pada
servers > web > hosts
- beri command untuk dijalankan ketika di akhir proses deployment dengan Docker:
bin/bundle exec jekyll serve --host 0.0.0.0
. Parameter host ini penting untuk memberitahukan aplikasi untuk di-forward kepadakamal-proxy
- pastikan SSL
true
supayakamal-proxy
membuatkan SSL certificate otomatis dengan Let's Encrypt. - ganti path
healthcheck
ke/
karena Jekyll biasanya tidak punya/health
secara default - ganti
app_port
ke4000
default port untuk Jekyll - beri
username
danpassword
untuk registry Docker yang kamu punya, bisa Docker Hub, Digital Ocean atau GitHub. Saya pakai Docker Hub karena masih gratis untuk yang private.
Wajib gunakan environment variable dari.kamal/secrets
- jika servermu punya user yang berbeda dengan
root
, maka berikan username padassh > user
# Name of your application. Used to uniquely configure containers.
service: yourapp
# Name of the container image.
image: yourname/yourapp
# Deploy to these servers.
servers:
web:
hosts:
- 255.255.255.255 # your server IP address
cmd: bin/bundle exec jekyll serve --host 0.0.0.0
# Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server.
# Remove this section when using multiple web servers and ensure you terminate SSL at your load balancer.
#
# Note: If using Cloudflare, set encryption mode in SSL/TLS setting to "Full" to enable CF-to-app encryption.
proxy:
ssl: true
host: yourdomain.com
# Jekyll default path
healthcheck:
path: /
# Jekyll port forwarding
app_port: 4000
# Credentials for your image host.
registry:
# Specify the registry server, if you're not using Docker Hub
# server: registry.digitalocean.com / ghcr.io / ...
username: yourusername
# Always use an access token rather than real password (pulled from .kamal/secrets).
password:
- KAMAL_REGISTRY_PASSWORD
# Configure builder setup.
builder:
arch: amd64
context: .
# Use a different ssh user than root
#
ssh:
user: ubuntu
Dockerfile
Dockerfile untuk Jekyll cukup sederhana, saya dibantu oleh Claude untuk ini. Yang penting adalah apt-get
untuk library yang esensial dan bundle install
untuk memasang dependency bagi Jekyll:
ARG RUBY_VERSION=3.4.1
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
git \
&& rm -rf /var/lib/apt/lists/*
COPY Gemfile* .
RUN bundle install
COPY . .
EXPOSE 4000
.kamal/secrets
File ini dibuat ketika menjalankan kamal init
. Pastikan kamu tidak menuliskan credential apapun di dalamnya. File ini sama halnya dengan sebuah file Bash, jadi kamu bisa membuat environment variable yang mengeksekusi perintah Bash. Contohnya untuk mendekripsi hash untuk mendapatkan credential.
SECRETS=$(kamal secrets fetch --adapter 1password --account Your1PasswordAccount --from op://Your1Password/section KAMAL_REGISTRY_PASSWORD)
KAMAL_REGISTRY_PASSWORD=$(kamal secrets extract KAMAL_REGISTRY_PASSWORD $SECRETS)
Kamal memiliki adapter 1Password dan LastPass + bitwarden di dalam perintah kamal secrets extract
, sangat praktis jika menggunakan password manager yang aman.
Gemfile
Sudah lama saya tidak menggunakan Jekyll, ada beberapa dependency yang perlu ditambahkan secara eksplisit. Berikut ini adalah hasilnya:
source "https://rubygems.org"
ruby "3.4.1"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
gem "jekyll"
gem "webrick"
gem "kamal" # deployment
gem "base64" # safe_yaml dependency
gem "bigdecimal" # liquid dependency
gem "kramdown-parser-gfm" # kramdown dependency
Jalankan bundle install
untuk menginstal semua dependency-nya.
Deploy
Jalankan kamal setup
untuk setup SSH ke server dan push docker image untuk yang pertama kalinya. Akan lebih nyaman di kemudian hari apabila kalian meng-copy SSH keys ke server, gunakan perintah ssh-copy-id
untuk ini.
Jika alam semesta mendukung dan kalian tidak menemukan error 😬, maka jalankan kamal deploy
untuk mendeploy aplikasimu. Done!
Bacaan menarik
Kamal adalah tool yang agnostik, kita bisa men-deploy apa saja selama didukung oleh Docker. Lagipula, Kamal adalah sebuah Docker wrapper yang ditulis dengan Ruby, bahasa pemrograman yang saya gemari. Berikut adalah dokumentasi Kamal yang menarik untuk dibaca apabila kalian tertarik untuk menggunakan Kamal pada proyek pribadi kalian:
- commands, semua command yang tersedia, termasuk
kamal app logs
untuk melihat log pada aplikasi: https://kamal-deploy.org/docs/commands/view-all-commands/ - accessories, apabila kalian ingin menjalankan aplikasi lain seperti database yang tidak ikut dalam
kamal deploy
: https://kamal-deploy.org/docs/configuration/accessories/ - secrets, untuk mengetahui bagaimana mengekstrak environment variable yang terenkripsi: https://kamal-deploy.org/docs/commands/secrets/
Overengineering selagi mampu
Ada sebuah idiom mengatakan f**ked around and find out, kita tidak akan mengetahui sebuah solusi disebut overengineer atau underengineer sebelum kita mencobanya. Bekerja di sebuah perusahaan yang tidak ragu untuk overengineering a solution adalah suatu privilese. Karena begitu kita mengerjakan proyek pribadi, cost adalah batasan terbesar yang menghalangi kita untuk mencoba suatu hal.