---
title: "Dari GitHub hingga online: deploy Next.js, PostgreSQL, dan domain kustom"
description: "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."
date: 2026-11-10
language: id-ID
url: https://zenavo.app/id-ID/blog/deploy-nextjs-postgresql
---

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

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](https://docs.zenavo.app/id-ID/servers/add-a-server) 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:

```json
{
  "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:

```dotenv
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](https://docs.zenavo.app/id-ID/frameworks/nextjs).

## 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:

```json
{
  "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](https://docs.zenavo.app/id-ID/networking/domains)). 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](https://docs.zenavo.app/id-ID/deploy/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](https://zenavo.app): jalankan PostgreSQL terlebih dahulu, hubungkan repositori GitHub, atur `DATABASE_URL` serta domain, dan alur dari `git push` hingga online siap dalam beberapa menit.
