Berpindah Era: Dari Web PHP ke Jamstack, Server less
Berawal dari PHP ke Node.js, menggunakan teknologi baru seperti Docker, JAMstack, dan Next.js. Ini berisi tips dan manfaat dari teknologi baru untuk mempermudah migrasi.
Background
Saya sangat ingin membuat sebuah blog pribadi yang mana saya bebas
mencurahkan dan mencatat apa - apa yang ada di pikiran saya sekarang.
Yang pada akhirnya beberapa waktu lalu (atau tahun lalu) akhirnya saya
sukses membuat domain gratis saya sendiri. Saya membuat blog saya yang
ke sekian kali dihostingan gratis juga. Semua berjalan
lumayan lancar, hanya saja saya ingin menggunakan CMS yang tidak ribet.
Ketemulah beberapa cms yang menarik, namun karena keterbatasan hosting
gratis an, akhirnya mau tidak mau terikat script PHP saja. Padahal CMS
lain keren - keren lho! static site generator terasa sangat cepat,
keren, tapi.. ah sudahlah.
Web dengan PHP
Semua baik-baik saja, atau mungkin tidak. Sesuai dengan beberapa postingan yang ada di blog saya, saya beberapa kali mengganti CMS karena saya kesulitan dalam membuat blog saya tampil seperti yang saya inginkan. Di poin ini, sekarang, saya sadar bahwa saya bukan front-end developer, tidak perlu menginginkan tampilan blog yang muluk-muluk, yang penting nyaman dilihat!
Terakhir saya menggunakan Bludit, sangat sederhana, saya menemukan tema sederhana yang enak dilihat (Notebook). Akan tetapi hostingan gratis saya malah berulah, mulai konten yang tiba - tiba hilang, sampai kena suspend padahal saya tidak ngapa-ngapain.
Ide Pindah Server
Setelah kejadian itu, saya berpikir untuk melirik static site
generator. Ya tinggal pilih saja mau di mana, paling GitHub.
Ternyata saya baru ingat bahwa ada Fly.io, yang mendukung Docker lho!
Kan tinggal buat Dockerfile, terus fly deploy
dong!
Dari hasil lirik kanan-kiri, saya dapat CMS yang sebetulnya sudah saya temukan sebelum melihat-lihat static site generator, yaitu Ghost, yang mana CMS ini bekerja dengan backend Node. Berdasarkan screenshot dan showcase web yang menggunakan Ghost, ini terlihat baik, enak dibaca, dan sangat fleksibel (kalau di layar smartphone), membuat saya tertarik. Saya putuskan untuk mencoba Ghost dan mau saya deploy di Fly.io.
Web Node, tapi Docker
Kalau deploy Node, kok sepertinya agak susah. Ketika saya coba secara lokal, ada masalah sqlite3 yang gagal di build. Frustrasi, saya langsung ambil Docker saja. Cara saya sama seperti ketika deploy vaultwarden, tinggal saya tambahkan saja.
[build]
image = "ghost:latest"
[[mounts]]
destination = "/var/lib/ghost/content/data"
source = "ghost_db"
[env]
url=<URL_WEBNYA> # isi url webnya, kalau di fly.io biasanya namaapp.fly.dev
NODE_ENV="development" # kalau tidak development, nanti harus pakai MySQL
database__connection__filename='/var/lib/ghost/content/data/ghost.db'
[[services]]
internal_port = 2368
Tentunya saya sudah membuat persistent storage sebesar 1GB.
Setelah itu, fly deploy
, jadi! Saatnya migrasi konten.
Input dan Migrasi
Tanpa cap-cip-cup, saya langsung copy paste konten blog saya yang sudah saya backup ke Ghost. Nyaman sekali, tampilan minimalis mungkin mirip WordPress, dan mendukung Markdown! Jadi, saya tidak perlu pusing-pusing mengatur teks harus seperti apa karena sekali paste, langsung jadi.
Setelah hampir setengah saya copas teks blog saya, saya berpikir bagaimana dengan gambar/aset saya? Persistent Storage yang diberikan Fly.io maksimal adalah 3GB, di mana beberapa bagiannya sudah saya alihkan ke aplikasi lain seperti Vaultwarden.
Kalau pun di-upload ke Ghost, nanti saya ambilnya bagaimana? Backup
di Ghost ada pada menu Labs
, di mana hasilnya adalah JSON,
dan gambar saya tentunya tidak ada di dalam JSON tersebut.
Apalagi Fly.io tidak memberikan akses terhadap persistent storagenya, kalau seumpama fly.io harus berbayar, saya harus bagaimana mengamankan asetnya?
Penyimpanan Terbatas?
Awalnya saya berpikir apakah saya harus menginput aset gambar secara manual. Apakah lebih baik saya mengunggah gambar-gambar tersebut di Google Drive, kemudian membuat indeks Drive dengan Cloudflare, atau bagaimana?
Namun keberuntungan sepertinya sedang berpihak kepada saya, saya iseng-iseng mencari tempat hosting untuk aset saya, dan ketemulah Cloudinary. Yang mengagumkan lagi, Ghost memiliki kemampuan untuk mengintegrasikan filenya ke Cloudinary! Kita sambut dengan meriah Cloudinary Ghost Storage Adapter.
Ya, meskipun Cloudinary Free tier-nya hanya memberikan kapasitas penyimpanan 1GB (dan batasan-batasan lain), tapi kan tidak terikat dengan Fly.io, jadi kalau ada apa-apa bisa diselamatkan. Cloudinary juga merupakan penyimpanan yang revolusioner; edit-edit gambar tinggal ganti URL, sangat dinamis!
Ghost + Cloudinary
Caranya mudah, kita tinggal copas saja contoh yang diberikan di
GitHubnya dan simpan ke dalam file Dockerfile
.
Misalnya.
FROM ghost:5-alpine as cloudinary
RUN su-exec node yarn add ghost-storage-cloudinary
FROM ghost:5-alpine
COPY --chown=node:node --from=cloudinary $GHOST_INSTALL/node_modules $GHOST_INSTALL/node_modules
COPY --chown=node:node --from=cloudinary $GHOST_INSTALL/node_modules/ghost-storage-cloudinary $GHOST_INSTALL/content/adapters/storage/ghost-storage-cloudinary
Karena kita tidak lagi menggunakan image Ghost vanilla, maka kita
perlu mengubah isi dari fly.toml
.
[env]
NODE_ENV = "development"
database__client = "sqlite3"
database__connection__filename = "/var/lib/ghost/content/data/ghost.db"
imageOptimization__resize = "false"
paths__contentPath = "/var/lib/ghost/content/"
storage__active = "ghost-storage-cloudinary"
storage__ghost-storage-cloudinary__auth__api_key = <cloudinary api>
storage__ghost-storage-cloudinary__auth__api_secret = <cloudinary secret>
storage__ghost-storage-cloudinary__auth__cloud_name = <cloudinary cloudname>
storage__ghost-storage-cloudinary__fetch__cdn_subdomain = "true"
storage__ghost-storage-cloudinary__fetch__secure = "false"
storage__ghost-storage-cloudinary__upload__folder = "blog"
storage__ghost-storage-cloudinary__upload__overwrite = "false"
storage__ghost-storage-cloudinary__upload__unique_filename = "false"
storage__ghost-storage-cloudinary__upload__use_filename = "true"
url = <url dari flyio>
[[mounts]]
destination = "/var/lib/ghost/content/data"
source = "ghost_data"
[[services]]
internal_port = 2368
Kok jadi banyak? untuk info jelasnya bisa di lihat di contoh resmi config cloudinary.
Serverless?
Apakah perjalanan kita berhenti sampai ini saja? Tentu saja, tidak.
Entah kenapa saya masih kurang puas dengan Ghost ini; saya tertarik dengan klaim bahwa Ghost adalah CMS Headless open-source terbaik. Saya ingin membuktikannya!
Saya sudah menggunakan salah satu penyedia layanan serverless bernama Vercel. Dan untuk membuktikan Headless CMS ini, saya mencari tahu mengenai JAMstack dan NextJS. Ternyata ada, next-cms-ghost.
Publish flaring fast blogs with Next.js and Ghost CMS
Begitu slogan dari next-cms-ghost
, dan untuk
konfigurasinya sendiri, sangat mudah. Tinggal clone, buat pengaturan
Environment Variable di Vercel, dan lalu deploy.
Hasilnya? next-cms-ghost
akan mengambil konten dari
instalasi Ghost saya dan mengubahnya menjadi halaman statis. Dan
lihatlah kecepatan blog saya!
PageSpeed Insight untuk perangkat Mobile
PageSpeed Insight untuk perangkat Desktop
Istimewa!