# Deploy Debian 12 for `portal.bizone.id`

Panduan ini menyiapkan `bizone-web` di server Debian 12 kosong dengan topologi berikut:

- `nginx` sebagai reverse proxy publik
- `frontend` Next.js pada `127.0.0.1:3000`
- `backend` NestJS pada `127.0.0.1:3001`
- `PostgreSQL` dan `Redis` via Docker Compose
- TLS dari Let's Encrypt

## URL Production Final

- Aplikasi: `https://portal.bizone.id`
- Backend API public base URL: `https://portal.bizone.id/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_TOKEN` yang sama persis dengan env production

Catatan penting:

- Route backend memakai global prefix `/api`, jadi endpoint controller `GET /webhooks/whatsapp` menjadi `GET /api/webhooks/whatsapp`.
- Jika Anda ingin verifikasi tanda tangan resmi dari Meta, isi `META_WEBHOOK_APP_SECRET`.
- Bila `META_WEBHOOK_APP_SECRET` terisi, request ke `POST /api/webhooks/whatsapp/meta` menuntut header `x-hub-signature-256`.
- Endpoint `POST /api/webhooks/whatsapp` tetap 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 menyimpan `META_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

```bash
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:

```bash
node -v
npm -v
docker --version
docker compose version
```

## 3. Siapkan user dan direktori aplikasi

```bash
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:

```bash
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:

```bash
cd /srv/bizone-web
npm install
```

Backend:

```bash
cd /srv/bizone-web/backend
npm install
npm run build
```

Frontend:

```bash
cd /srv/bizone-web/frontend
npm install
npm run build
```

## 5. Siapkan `.env` production

Salin template:

```bash
cp /srv/bizone-web/deploy/debian12/app.env.example /srv/bizone-web/.env
```

Lalu ubah semua placeholder, terutama:

- `DATABASE_URL`
- `JWT_SECRET`
- `JWT_REFRESH_SECRET`
- `WEBHOOK_VERIFY_TOKEN`
- `WEBHOOK_SHARED_SECRET`
- `META_WEBHOOK_APP_SECRET`
- `MAIL_*`

Nilai yang wajib dipakai untuk domain ini:

```dotenv
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:

```bash
openssl rand -hex 32
openssl rand -hex 32
openssl rand -hex 32
openssl rand -hex 32
```

Gunakan hasil berbeda untuk:

- `JWT_SECRET`
- `JWT_REFRESH_SECRET`
- `WEBHOOK_VERIFY_TOKEN`
- `WEBHOOK_SHARED_SECRET`

## 6. Jalankan PostgreSQL dan Redis

```bash
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

```bash
cd /srv/bizone-web/backend
npm run db:generate
npm run db:migrate:deploy
```

Jika database masih kosong total, Anda bisa seed admin:

```bash
npm run seed:admin
```

Seed default saat ini:

- Email: `admin@example.com`
- Password: `ChangeMe123!`

Masuk lalu segera ganti password.

## 8. Pasang service `systemd`

Salin file service:

```bash
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:

```bash
sudo systemctl status bizone-backend
sudo systemctl status bizone-frontend
```

Lihat log:

```bash
sudo journalctl -u bizone-backend -f
sudo journalctl -u bizone-frontend -f
```

## 9. Pasang `nginx`

Salin config:

```bash
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:

```bash
curl -I http://portal.bizone.id
curl http://portal.bizone.id/api/health
```

## 10. Aktifkan HTTPS

```bash
sudo certbot --nginx -d portal.bizone.id
```

Setelah cert aktif, uji:

```bash
curl -I https://portal.bizone.id
curl https://portal.bizone.id/api/health
```

Respons health ideal:

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

- `messages`
- `message_deliveries`
- `message_read`
- `message_sent`
- `message_failed`
- `template_category_update`
- `account_update`

Mapping internal saat ini:

- `messages` -> `message.inbound`
- `message_deliveries` -> `message.delivered`
- `message_read` -> `message.read`
- `message_sent` -> `message.sent`
- `message_failed` -> `message.failed`
- `template_category_update` -> `template.updated`
- `account_update` -> `account.updated`

## 12. Urutan test live yang saya sarankan

1. Pastikan `https://portal.bizone.id/api/health` mengembalikan `200`.
2. Coba buka `https://portal.bizone.id`.
3. Lakukan webhook verification dari Meta dengan callback URL production.
4. Kirim test webhook dari Meta.
5. Login ke dashboard dan buka `Dashboard > Webhooks Logs`.
6. Kirim pesan WhatsApp sungguhan ke nomor bisnis yang terhubung.
7. Pastikan inbound message masuk ke inbox conversation.
8. Balas dari dashboard bila access token dan `phoneNumberId` sudah terisi.
9. Cek status `sent`, `delivered`, `read`, atau `failed` kembali masuk lewat webhook.

## 13. Command update deploy berikutnya

Setelah ada perubahan code:

```bash
cd /srv/bizone-web
git pull
npm install
cd backend && npm install && npm run build && npm run db:generate && 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:

```bash
git config user.name "Wira Irawan"
git config user.email "wira.irawan@gmail.com"
```

## 14. Smoke check minimal

```bash
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
```
