Saya memutuskan untuk deploy Jekyll dengan Kamal

Saya memutuskan untuk deploy Jekyll dengan Kamal
Foto dibuat dengan Grok

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:

  1. beri nama aplikasimu pada service
  2. beri nama pada image aplikasimu pada image
  3. beri IP address pada servers > web > hosts
  4. 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 kepada kamal-proxy
  5. pastikan SSL true supaya kamal-proxy membuatkan SSL certificate otomatis dengan Let's Encrypt.
  6. ganti path healthcheck ke / karena Jekyll biasanya tidak punya /health secara default
  7. ganti app_port ke 4000 default port untuk Jekyll
  8. beri username dan password 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
  9. jika servermu punya user yang berbeda dengan root, maka berikan username pada ssh > 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:

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.

Read more

Mastodon