Dari GitHub hingga online: deploy Next.js, PostgreSQL, dan domain kustom

Deploy aplikasi Next.js dan PostgreSQL di server Anda sendiri dengan Zenavo, atur koneksi jaringan privat, variabel saat build vs runtime, migrasi database Prisma, domain HTTPS, dan deploy otomatis.

Artikel ini juga tersedia dalam English, 简体中文, 繁體中文, 日本語, dan Español.

Membawa aplikasi Next.js dari lokal hingga online biasanya mencakup lima hal: skrip start, koneksi database, variabel lingkungan (membedakan waktu build dan runtime), migrasi tabel database, serta pemasangan domain HTTPS.

Panduan ini menggunakan repositori Next.js yang sudah ada dan menjalankannya bersama PostgreSQL di server Anda sendiri. Sebelum mulai, hubungkan server Linux ke Zenavo terlebih dahulu.

1. Periksa package.json di repositori Anda

Jika repositori tidak memiliki Dockerfile khusus, Zenavo akan memakai zbpack untuk mengenali dan mem-build Next.js secara otomatis. Pastikan file lock (package-lock.json, pnpm-lock.yaml, yarn.lock, atau bun.lockb) sudah ikut di-commit dan package.json memiliki skrip produksi standar:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "engines": {
    "node": ">=20"
  }
}

Jalankan npm run build di komputer lokal satu kali sebelum deploy agar error tipe TypeScript atau masalah saat build terlihat sejak awal.

2. Deploy PostgreSQL

Buat proyek di Zenavo, pilih server, lalu klik Tambah Layanan → Database → PostgreSQL, pilih versi, dan deploy.

Database berjalan di jaringan privat proyek dan secara bawaan tidak membuka port ke internet publik. Setelah siap, layanan ini membagikan variabel koneksi ke layanan lain di proyek yang sama; bila nama layanannya postgresql, variabel string koneksi lengkapnya adalah POSTGRESQL_CONNECTION_STRING.

3. Tambahkan aplikasi Next.js dari GitHub

Di proyek yang sama, klik Tambah Layanan → GitHub, beri izin Zenavo GitHub App untuk membaca repositori Anda, lalu pilih repositori, branch, dan direktori root (jika memakai monorepo, misalnya aplikasi berada di apps/web, isi direktori root dengan apps/web).

Referensikan database tadi di variabel lingkungan:

DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}

${POSTGRESQL_CONNECTION_STRING} adalah referensi variabel lintas layanan di Zenavo yang saat runtime otomatis diisi dengan string koneksi jaringan internal yang sebenarnya (jika Anda mengubah nama layanan database, gunakan nama variabel yang ditampilkan di konsol).

Secara bawaan, next start otomatis membaca variabel lingkungan PORT dari platform. Jika Anda menulis Dockerfile atau server.js sendiri, pastikan aplikasi mendengarkan pada 0.0.0.0 dengan port yang sama seperti port HTTP pada layanan Zenavo. Detail selengkapnya ada di panduan deploy Next.js.

4. Bedakan NEXT_PUBLIC_* dan variabel sisi server

Next.js memiliki dua jenis variabel lingkungan dengan perilaku yang sangat berbeda:

  • Variabel sisi server (seperti DATABASE_URL, kunci pembayaran, atau API key AI): hanya dibaca di kode server dan jangan pernah diberi awalan NEXT_PUBLIC_. Setelah diubah di tab Variabel Zenavo, cukup restart layanan agar nilai baru berlaku.
  • Variabel NEXT_PUBLIC_*: langsung disisipkan ke dalam bundel JS frontend saat next build dijalankan. Setelah mengubah variabel NEXT_PUBLIC_*, Anda wajib melakukan deploy ulang (build ulang); sekadar me-restart kontainer tidak akan mengubah nilai yang diterima browser.

Selain itu, mesin build Zenavo tidak dapat mengakses database di jaringan internal server Anda selama tahap next build. Karena itu:

  • Jangan menulis next build yang mengharuskan koneksi ke database produksi agar build berhasil;
  • Halaman yang perlu membaca database sebaiknya memakai dynamic rendering saat ada permintaan, bukan membuat halaman statis saat build.

5. Jalankan migrasi database secara otomatis (contoh Prisma)

Karena database internal tidak bisa diakses saat build, migrasi tabel database sebaiknya dijalankan sesaat sebelum kontainer dimulai, bukan di dalam skrip build.

Saat mem-build dengan zbpack, Anda bisa menambahkan skrip predeploy di package.json, yang akan dijalankan setiap kali kontainer mulai sebelum start dieksekusi:

{
  "scripts": {
    "build": "prisma generate && next build",
    "predeploy": "prisma migrate deploy",
    "start": "next start"
  }
}

Perhatikan dua hal:

  • Untuk produksi, gunakan prisma migrate deploy (yang hanya menerapkan file migrasi yang sudah di-commit ke repositori), jangan gunakan prisma migrate dev atau db push --force-reset.
  • Jika Anda memakai Dockerfile sendiri, hook predeploy milik zbpack tidak otomatis berjalan; cukup masukkan npx prisma migrate deploy && npm start ke dalam perintah start kontainer (CMD atau ENTRYPOINT).

6. Pasang domain dan aktifkan deploy otomatis

Setelah aplikasi berjalan, buka tab Jaringan pada layanan untuk memasang domain Anda (misalnya app.example.com), arahkan record DNS A ke IP server, dan tunggu sertifikat HTTPS terbit otomatis (lihat Domain & HTTPS). Jika aplikasi Anda memakai NextAuth / Auth.js, Clerk, atau login OAuth, jangan lupa memperbarui variabel URL situs seperti NEXTAUTH_URL serta alamat callback di penyedia OAuth.

Buka situsnya, coba login dan lakukan pembuatan, pembacaan, pengeditan, serta penghapusan satu data uji coba untuk memastikan baca-tulis ke PostgreSQL berjalan lancar.

Di Pengaturan layanan, aktifkan Deploy otomatis saat push ke branch ini agar setiap git push otomatis memicu build dan pembaruan tanpa downtime; untuk monorepo, Anda bisa mengatur watch path agar build hanya berjalan saat direktori tersebut berubah (lihat Deploy dari GitHub).

Pertanyaan umum

Log build menampilkan error Can't reach database server at postgresql.zenavo.internal:5432? Skrip build atau salah satu halaman Anda mencoba menghubungi database internal saat proses static generation (SSG). Pindahkan migrasi database ke predeploy atau perintah start, dan tambahkan export const dynamic = 'force-dynamic' pada halaman yang perlu membaca database.

Sudah mengubah NEXT_PUBLIC_API_URL dan restart, tetapi di halaman masih alamat lama? Variabel NEXT_PUBLIC_* dibundel ke dalam kode frontend pada waktu build. Klik Deploy ulang (Redeploy) untuk menjalankan build baru.

Bagaimana cara kembali ke versi sebelumnya jika deploy baru bermasalah? Di riwayat deploy, Anda bisa melakukan rollback aplikasi ke image versi sebelumnya dengan satu klik. Perhatikan bahwa rollback layanan hanya mengembalikan image dan pengaturan aplikasi, bukan database. Jika versi baru berisi migrasi database yang menghapus kolom atau mengubah struktur secara permanen, buat backup database terlebih dahulu di tab Backup & Pemulihan pada layanan PostgreSQL.

Setelah repositori siap, buat proyek baru di konsol Zenavo: jalankan PostgreSQL terlebih dahulu, hubungkan repositori GitHub, atur DATABASE_URL serta domain, dan alur dari git push hingga online siap dalam beberapa menit.