Halo Sobat Online! Kalau kamu baru selesai mengembangkan aplikasi dengan Next.js 16, langkah berikutnya adalah menaruhnya di tempat yang bisa diakses orang banyak. Salah satu cara paling hemat adalah deploy Next.js di VPS milik sendiri: aplikasi berjalan di server kita, biayanya tetap per bulan, dan hampir semua pengaturannya ada di tangan kita. Supaya aplikasi itu tetap hidup ketika laptop kita tutup atau VPS-nya reboot, kita serahkan tugasnya ke PM2.
Di artikel ini kita kerjakan satu alur lengkap: menyiapkan output standalone, membangun aplikasi di VPS, menjalankannya lewat PM2, memasang Nginx di depannya, sampai membuat aplikasi menyala sendiri setiap kali server dihidupkan ulang. Semua perintahnya bisa langsung kamu salin.
Kenapa Deploy Next.js di VPS Pakai PM2?
Tiga alasan yang paling terasa di dunia nyata:
- Biaya tetap dan bisa diprediksi. VPS kelas kecil sampai menengah sudah cukup untuk satu aplikasi Next.js, berapa pun jumlah pengunjungnya — berbeda dengan penagihan per request yang naik-turun mengikuti trafik.
- Kontrol penuh. Versi Node.js, environment variable, port, sampai pengaturan cache ada di tangan kita sendiri.
- Bisa berbagi server. Aplikasi Next.js bisa hidup damai berdampingan dengan n8n, Uptime Kuma, atau database di VPS yang sama.
Analogi gampangnya begini: platform hosting terkelola itu seperti hotel — praktis, tapi bayar per malam dan kita tidak boleh memindahkan perabot. VPS plus PM2 itu seperti menyewa rumah: perlu membeli perabot sekali, tapi setelah itu kita tenang dan bisa menata sesuka hati.
PM2 sendiri adalah process manager untuk aplikasi Node.js. Tugasnya: menjalankan aplikasi di latar belakang, menghidupkannya ulang kalau mati, menyimpan log, dan ikut menyala saat server boot.
Satu Catatan Versi: Next.js 16 Butuh Node.js 20.9+
Sejak Next.js 16 (rilis stabil Oktober 2025), Node.js 18 tidak didukung lagi. Minimumnya adalah Node.js 20.9 dan TypeScript 5.1. Turbopack kini menjadi bundler bawaan, dan perintah next lint sudah dihapus — lint dijalankan langsung lewat ESLint. Jadi, pastikan node -v di VPS menjawab v20.9.0 atau lebih baru sebelum mulai.
Yang Perlu Disiapkan
- VPS Linux (Ubuntu/Debian) dengan akses
sudo. Semua perintah di artikel ini memakai keluarga Debian. - Node.js 20.9 atau lebih baru. Cek cepat dengan
node -v && npm -v. - Domain atau subdomain yang A record-nya sudah menunjuk ke IP VPS.
- Nginx dan Certbot untuk HTTPS. Kalau belum terpasang, langkahnya pernah kita bahas di artikel Yuk, Pasang Nginx Reverse Proxy di VPS Plus HTTPS Gratis Pakai Certbot.
- Berkas
.envversi produksi yang berisi kredensial aplikasi.
Langkah 1: Aktifkan Output Standalone
Next.js bisa menyalin hanya berkas yang benar-benar dibutuhkan aplikasi, bukan seluruh isi node_modules. Caranya dengan menambahkan satu opsi di konfigurasi:
// next.config.ts
const nextConfig = {
output: "standalone",
};
export default nextConfig;
Setelah next build, muncul folder .next/standalone yang berisi server.js plus node_modules versi minimal. Hasilnya jauh lebih ringan karena hanya dependency runtime yang ikut, sementara alat build seperti TypeScript dan ESLint ditinggalkan.
Dua folder ini tidak ikut tersalin otomatis, jadi harus disalin manual setelah build:
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
Kalau langkah ini kelewat, halaman tetap terbuka, tapi CSS dan gambar akan 404 — situsnya tampil seperti kehilangan semua gayanya.
Langkah 2: Build di VPS dan Uji Sebelum Dijadikan Layanan
Masuk ke folder proyek, lalu jalankan:
git pull
npm ci
npm run build
Pakai npm ci, bukan npm install, supaya versi paket yang terpasang persis sama dengan package-lock.json. Setelah build selesai, uji dulu langsung dari terminal sebelum menambah lapisan apa pun:
cd .next/standalone
HOSTNAME=127.0.0.1 PORT=3000 node server.js
Buka terminal kedua, lalu panggil curl -I http://127.0.0.1:3000. Kalau jawabannya HTTP/1.1 200 OK (atau 307/308 untuk halaman yang di-redirect), aplikasimu sudah sehat. Hentikan dengan Ctrl+C.
Kenapa
HOSTNAME=127.0.0.1? Supaya aplikasi hanya mendengarkan di dalam server, bukan langsung dari internet. Nanti Nginx yang menjadi pintu depannya. Ini juga sesuai anjuran resmi Next.js: gunakan reverse proxy di depan server Next.js agar pemeriksaan request, batas ukuran payload, dan rate limit tidak membebani aplikasi.
Langkah 3: Jalankan dengan PM2
Pasang PM2 secara global, lalu buat berkas ecosystem.config.js di root proyek:
npm install -g pm2
module.exports = {
apps: [
{
name: "nextjs-app",
script: ".next/standalone/server.js",
cwd: "/var/www/appkamu",
exec_mode: "fork",
instances: 1,
env: {
NODE_ENV: "production",
PORT: 3000,
HOSTNAME: "127.0.0.1",
},
max_memory_restart: "512M",
time: true,
},
],
};
Lalu nyalakan dan periksa:
pm2 start ecosystem.config.js
pm2 status
pm2 logs nextjs-app --lines 50
Tiga pengaturan itu punya alasan masing-masing:
exec_mode: "fork"daninstances: 1adalah titik awal paling aman untuk Next.js. Modeclustermemang bisa memakai semua core CPU, tapi setiap worker memuat salinan server Next.js-nya sendiri di memori — di VPS 1–2 GB RAM, dua worker saja sudah cukup membuat server kehabisan memori. Naikkan jumlahnya hanya kalau RAM masih lega dan kamu sudah menguji beban.max_memory_restartmembuat PM2 me-restart aplikasi ketika memori menembus batas, sehingga satu proses yang bocor tidak menyeret seluruh VPS.cwdwajib diisi karenaserver.jsmembaca berkas relatif terhadap folder kerjanya.
Langkah 4: Pasang Nginx di Depannya
Buat satu berkas konfigurasi situs, misalnya /etc/nginx/sites-available/appkamu:
server {
listen 80;
server_name app.domainmu.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
}
Aktifkan, uji, lalu minta sertifikat HTTPS:
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d app.domainmu.com
nginx -t wajib dijalankan sebelum reload. Satu titik koma yang lupa ditulis sudah cukup membuat Nginx menolak menyala.
Langkah 5: Bikin Aplikasi Hidup Lagi Setelah Reboot
Ini bagian yang paling sering dilupakan, padahal akibatnya paling menyakitkan: aplikasi mati total setelah VPS di-restart.
pm2 save
pm2 startup
Perintah pm2 startup akan mencetak satu baris perintah sudo env PATH=... pm2 startup systemd -u <user> --hp <home>. Salin dan jalankan baris itu apa adanya. pm2 save menyimpan daftar aplikasi yang sedang berjalan, dan skrip systemd itulah yang membangkitkannya kembali setiap kali server menyala.
Kalau nanti versi Node.js di VPS di-upgrade, jalankan pm2 unstartup lalu pm2 startup lagi supaya PATH di dalam skrip systemd ikut diperbarui.
Langkah 6: Update Aplikasi Tanpa Downtime
Setiap kali ada perubahan kode, ulangi alur ini:
git pull
npm ci
npm run build
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
pm2 reload nextjs-app
pm2 reload mengganti proses lama dengan yang baru tanpa mematikan aplikasi lebih dulu, berbeda dengan pm2 restart yang memutus koneksi sesaat.
Kesalahan yang Sering Terjadi
- Halaman 502 Bad Gateway dari Nginx. Hampir selalu berarti aplikasi tidak mendengarkan di port yang dipanggil
proxy_pass. Uji dulucurl -I http://127.0.0.1:3000, lalu lihatpm2 logs. - CSS dan gambar 404. Folder
publicdan.next/staticbelum disalin ke dalam.next/standalone. - Environment variable terasa tidak berubah. Variabel berawalan
NEXT_PUBLIC_ditanam ke dalam bundle saat build, jadi mengubahnya butuh build ulang, bukan hanya restart. - Aplikasi mati sendiri setelah VPS reboot. Berarti
pm2 savedanpm2 startupbelum dijalankan. - Perintah
next linterror. Perintah itu memang sudah dihapus di Next.js 16; panggil ESLint langsung.
Kesimpulan
Deploy Next.js di VPS itu sekali pasang, lalu tinggal dirawat. Kuncinya hanya empat: aktifkan output standalone, jalankan lewat PM2 dengan konfigurasi yang jelas, letakkan Nginx di depannya, dan jangan lupa pm2 save plus pm2 startup supaya aplikasi bangun sendiri tiap kali server menyala. Setelah itu kamu punya rumah sendiri untuk aplikasimu — tanpa tagihan per request, dan semua pengaturan ada di tanganmu. Selamat mencoba, Sobat Online!

