Deploy Debian 12 for portal.bizone.id
Panduan ini menyiapkan bizone-web di server Debian 12 kosong dengan topologi berikut:
nginxsebagai reverse proxy publikfrontendNext.js pada127.0.0.1:3000backendNestJS pada127.0.0.1:3001PostgreSQLdanRedisvia Docker Compose- TLS dari Let's Encrypt
URL Production Final
- Aplikasi:
https://portal.bizone.id - Backend API browser/server base URL via reverse proxy:
https://portal.bizone.id/backend-api - Health check backend:
https://portal.bizone.id/api/health - Webhook verify URL Meta:
https://portal.bizone.id/api/webhooks/whatsapp - Webhook event URL Meta:
https://portal.bizone.id/api/webhooks/whatsapp - Alternate provider-specific webhook URL:
https://portal.bizone.id/api/webhooks/whatsapp/meta - Webhook logs UI:
https://portal.bizone.id/dashboard/webhooks/logs
Untuk integrasi Meta, gunakan URL default berikut:
- Callback URL:
https://portal.bizone.id/api/webhooks/whatsapp - Verify token: nilai
WEBHOOK_VERIFY_TOKENyang sama persis dengan env production
Catatan penting:
- Route backend memakai global prefix
/api, jadi endpoint controllerGET /webhooks/whatsappmenjadiGET /api/webhooks/whatsapp. - Di production,
nginxmengekspos backend internal aplikasi lewat prefixhttps://portal.bizone.id/backend-api. - Prefix
/api/*di browser dipakai oleh route handler Next.js untuk operasi dashboard seperti save contact, save user, export, dan aksi client-side lain. - Jika Anda ingin verifikasi tanda tangan resmi dari Meta, isi
META_WEBHOOK_APP_SECRET. - Bila
META_WEBHOOK_APP_SECRETterisi, request kePOST /api/webhooks/whatsapp/metamenuntut headerx-hub-signature-256. - Endpoint
POST /api/webhooks/whatsapptetap bisa dipakai untuk Meta bila Anda memilih verify token + shared secret non-Meta untuk test lain, tetapi untuk produksi Meta lebih aman menargetkan URL default callback dan menyimpanMETA_WEBHOOK_APP_SECRET.
1. DNS
Buat A record:
portal.bizone.id-> IP publik server Debian 12
Pastikan propagasi selesai sebelum minta sertifikat TLS.
2. Install paket dasar
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx curl git build-essential
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
Logout lalu login ulang setelah menambahkan grup docker.
Verifikasi:
node -v
npm -v
docker --version
docker compose version
3. Siapkan user dan direktori aplikasi
sudo useradd -m -s /bin/bash bizone
sudo mkdir -p /srv
sudo chown -R $USER:$USER /srv
cd /srv
git clone https://git.iptek.co/wirabasalamah/BizOne-portal.git bizone-web
cd /srv/bizone-web
Jika repo dikirim manual:
sudo mkdir -p /srv/bizone-web
sudo chown -R $USER:$USER /srv/bizone-web
Lalu salin source code ke /srv/bizone-web.
4. Install dependency dan build
Root dependency Prisma:
cd /srv/bizone-web
npm install
Jangan lewati langkah root ini. Script backend/npm run db:generate mengambil Prisma client hasil generate dari root repo.
Backend:
cd /srv/bizone-web/backend
npm install
npm run db:generate
npm run build
Jika Anda langsung menjalankan npm run build tanpa npm run db:generate, TypeScript biasanya gagal dengan error seperti Prisma.sql does not exist, Prisma.InputJsonValue, atau model Prisma tidak ditemukan.
Frontend:
cd /srv/bizone-web/frontend
npm install
npm run build
5. Siapkan .env production
Salin template:
cp /srv/bizone-web/deploy/debian12/app.env.example /srv/bizone-web/.env
Lalu ubah semua placeholder, terutama:
DATABASE_URLJWT_SECRETJWT_REFRESH_SECRETWEBHOOK_VERIFY_TOKENWEBHOOK_SHARED_SECRETMETA_WEBHOOK_APP_SECRETMAIL_*
Nilai yang wajib dipakai untuk domain ini:
NODE_ENV=production
FRONTEND_ORIGIN=https://portal.bizone.id
PUBLIC_API_URL=https://portal.bizone.id
NEXT_PUBLIC_API_URL=https://portal.bizone.id/api
PORT=3001
WEBHOOK_ALLOW_UNSIGNED=false
Generate secret aman:
openssl rand -hex 32
openssl rand -hex 32
openssl rand -hex 32
openssl rand -hex 32
Gunakan hasil berbeda untuk:
JWT_SECRETJWT_REFRESH_SECRETWEBHOOK_VERIFY_TOKENWEBHOOK_SHARED_SECRET
Sebelum menjalankan command Prisma atau backend secara manual, export env ke shell aktif:
cd /srv/bizone-web
set -a
source .env
set +a
Tanpa langkah ini, command seperti npm run db:migrate:deploy bisa gagal dengan error Environment variable not found: DATABASE_URL.
6. Jalankan PostgreSQL dan Redis
cd /srv/bizone-web/deploy/debian12
docker compose -f docker-compose.infra.yml up -d
docker compose -f docker-compose.infra.yml ps
7. Generate Prisma client dan migrasi database
cd /srv/bizone-web/backend
npm run db:generate
npm run db:migrate:deploy
Jika database masih kosong total, Anda bisa seed admin:
npm run seed:admin
Seed default saat ini:
- Email:
admin@bizone.id - Password:
ChangeMe123!
Masuk lalu segera ganti password.
8. Pasang service systemd
Salin file service:
sudo cp /srv/bizone-web/deploy/debian12/bizone-backend.service /etc/systemd/system/
sudo cp /srv/bizone-web/deploy/debian12/bizone-frontend.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable bizone-backend bizone-frontend
sudo systemctl start bizone-backend bizone-frontend
Cek status:
sudo systemctl status bizone-backend
sudo systemctl status bizone-frontend
Lihat log:
sudo journalctl -u bizone-backend -f
sudo journalctl -u bizone-frontend -f
9. Pasang nginx
Salin config:
sudo cp /srv/bizone-web/deploy/debian12/nginx.portal.bizone.id.conf /etc/nginx/sites-available/portal.bizone.id
sudo ln -s /etc/nginx/sites-available/portal.bizone.id /etc/nginx/sites-enabled/portal.bizone.id
sudo nginx -t
sudo systemctl reload nginx
Uji HTTP lokal:
curl -I http://portal.bizone.id
curl http://portal.bizone.id/api/health
curl http://portal.bizone.id/backend-api/health
10. Aktifkan HTTPS
sudo certbot --nginx -d portal.bizone.id
Setelah cert aktif, uji:
curl -I https://portal.bizone.id
curl https://portal.bizone.id/api/health
curl https://portal.bizone.id/backend-api/health
Respons health ideal:
{"status":"ok","service":"wa-dashboard-backend","database":"ok","timestamp":"..."}
11. Data Meta yang harus Anda masukkan
Di Meta App Dashboard / WhatsApp configuration:
- Callback URL:
https://portal.bizone.id/api/webhooks/whatsapp - Verify token: isi dengan nilai
WEBHOOK_VERIFY_TOKEN
Jika Anda menyimpan META_WEBHOOK_APP_SECRET, backend akan memverifikasi signature event masuk dari header x-hub-signature-256.
Subscription event yang relevan untuk aplikasi ini:
messagesmessage_deliveriesmessage_readmessage_sentmessage_failedtemplate_category_updateaccount_update
Mapping internal saat ini:
messages->message.inboundmessage_deliveries->message.deliveredmessage_read->message.readmessage_sent->message.sentmessage_failed->message.failedtemplate_category_update->template.updatedaccount_update->account.updated
12. Urutan test live yang saya sarankan
- Pastikan
https://portal.bizone.id/api/healthmengembalikan200. - Coba buka
https://portal.bizone.id. - Lakukan webhook verification dari Meta dengan callback URL production.
- Kirim test webhook dari Meta.
- Login ke dashboard dan buka
Dashboard > Webhooks Logs. - Kirim pesan WhatsApp sungguhan ke nomor bisnis yang terhubung.
- Pastikan inbound message masuk ke inbox conversation.
- Balas dari dashboard bila access token dan
phoneNumberIdsudah terisi. - Cek status
sent,delivered,read, ataufailedkembali masuk lewat webhook.
13. Command update deploy berikutnya
Setelah ada perubahan code:
cd /srv/bizone-web
git pull
npm install
set -a
source .env
set +a
cd backend && npm install && npm run db:generate && npm run build && npm run db:migrate:deploy
cd ../frontend && npm install && npm run build
sudo systemctl restart bizone-backend bizone-frontend
Jika server belum punya identity Git dan Anda ingin commit langsung dari server:
git config user.name "Wira Irawan"
git config user.email "wira.irawan@gmail.com"
14. Smoke check minimal
curl https://portal.bizone.id/api/health
curl -I https://portal.bizone.id
sudo systemctl is-active bizone-backend
sudo systemctl is-active bizone-frontend
docker compose -f /srv/bizone-web/deploy/debian12/docker-compose.infra.yml ps
##+Q&xN$86LbSA<av<
Ganti NEXT_PUBLIC_API_URL production menjadi:
NEXT_PUBLIC_API_URL=https://portal.bizone.id/backend-api
Ini penting agar frontend server-side berbicara ke backend asli, sementara browser tetap bisa memakai route handler Next.js di /api/*.