# Panduan Install WhatsApp Inbox di Ubuntu (Domain: app.zappcare.id) Dokumen ini menyusun langkah deployment lengkap untuk server Ubuntu dengan kondisi: - PostgreSQL sudah terinstall - Nginx sudah terinstall - Gitea berjalan di port `3001` - Aplikasi ini tidak boleh pakai port `3000` karena dipakai layanan lain Pada panduan ini, aplikasi akan jalan di **port `3002`** di loopback (`127.0.0.1:3002`) dan di-serve via Nginx ke domain `app.zappcare.id`. ## 1) Prasyarat Pastikan server sudah memenuhi: - Ubuntu 22.04/24.04 (sesuaikan) - User dengan sudo - PostgreSQL aktif - Nginx aktif - Node.js 20.x + npm - Git - domain `app.zappcare.id` mengarah ke IP server (DNS A record) ## 2) Install runtime (jika belum) ```bash sudo apt update && sudo apt upgrade -y sudo apt install -y curl ca-certificates git nginx postgresql postgresql-contrib curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs node -v npm -v ``` ## 3) Buat database PostgreSQL Masuk psql: ```bash sudo -u postgres psql ``` Jalankan: ```sql CREATE USER whatsapp_inbox WITH PASSWORD 'GANTI_PASSWORD_KUAT'; CREATE DATABASE whatsapp_inbox OWNER whatsapp_inbox; \q ``` ## 4) Setup user deploy ```bash sudo useradd --system --home /var/www/whatsapp-inbox --shell /usr/sbin/nologin whatsapp-inbox || true sudo mkdir -p /var/www/whatsapp-inbox sudo chown -R whatsapp-inbox:whatsapp-inbox /var/www/whatsapp-inbox ``` ## 5) Clone source & install dependency ```bash sudo -u whatsapp-inbox git clone /var/www/whatsapp-inbox cd /var/www/whatsapp-inbox sudo -u whatsapp-inbox npm ci ``` > Ganti `` dengan URL repo Anda. ## 6) Buat `.env` production Buat file dari template: ```bash sudo cp /var/www/whatsapp-inbox/.env.example /var/www/whatsapp-inbox/.env sudo chown whatsapp-inbox:whatsapp-inbox /var/www/whatsapp-inbox/.env sudo -u whatsapp-inbox nano /var/www/whatsapp-inbox/.env ``` Isi `.env` yang wajib: ```env NODE_ENV=production PORT=3002 HOST=127.0.0.1 DATABASE_URL="postgresql://whatsapp_inbox:GANTI_PASSWORD_KUAT@127.0.0.1:5432/whatsapp_inbox?schema=public" AUTH_SECRET="ganti_secret_acak_minimal_32_karakter" APP_URL="https://app.zappcare.id" NEXT_PUBLIC_APP_URL="https://app.zappcare.id" OPS_BASE_URL="https://app.zappcare.id" CAMPAIGN_RETRY_JOB_URL="https://app.zappcare.id" CAMPAIGN_RETRY_JOB_TOKEN="ganti_token_acak" HEALTHCHECK_TOKEN="ganti_token_health" WHATSAPP_WEBHOOK_VERIFY_TOKEN="token_verify_webhook_anda" WHATSAPP_WEBHOOK_SECRET="webhook_secret_anda" WHATSAPP_API_TOKEN="meta_whatsapp_api_token" WHATSAPP_API_VERSION="v22.0" WHATSAPP_ALLOW_SIMULATED_SEND="false" CAMPAIGN_RETRY_BATCH_SIZE="100" CAMPAIGN_RETRY_MAX_CAMPAIGNS="20" CAMPAIGN_RETRY_JOB_LOCK_TTL_SECONDS="300" CAMPAIGN_RETRY_DAEMON_INTERVAL_SECONDS="300" CAMPAIGN_RETRY_DAEMON_TIMEOUT_MS="30000" CAMPAIGN_RETRY_ALERT_ON_FAILURE="true" CAMPAIGN_RETRY_ALERT_WEBHOOK_URL="" WEBHOOK_FAILURE_RATE_THRESHOLD_PER_HOUR="20" RETRY_WORKER_STALE_MINUTES="30" LOGIN_RATE_LIMIT_ATTEMPTS="10" LOGIN_RATE_LIMIT_WINDOW_MS="900000" CAMPAIGN_RETRY_JOB_RATE_LIMIT_GET="60" CAMPAIGN_RETRY_JOB_RATE_LIMIT_POST="20" CAMPAIGN_RETRY_JOB_RATE_LIMIT_WINDOW_MS="60000" WHATSAPP_WEBHOOK_RATE_LIMIT_GET="60" WHATSAPP_WEBHOOK_RATE_LIMIT_POST="120" WHATSAPP_WEBHOOK_RATE_LIMIT_WINDOW_MS="60000" AUTH_TOKEN_CONSUMED_RETENTION_HOURS="24" CAMPAIGN_RETRY_STALE_LOCK_MINUTES="120" WEBHOOK_EVENT_RETENTION_DAYS="30" AUDIT_LOG_RETENTION_DAYS="365" ``` > Pastikan nilai `DATABASE_URL` sesuai username/password/password database Anda. ## 7) Pastikan Prisma pakai PostgreSQL ### Cek `schema.prisma` Buka `prisma/schema.prisma` dan pastikan datasource: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Jika masih `sqlite`, migrasi ke Postgres harus dibangun ulang. Catatan: perubahan provider dan migration bisa dilakukan di environment staging/dev sebelum deploy production. ### Jalankan migration + seed ```bash cd /var/www/whatsapp-inbox sudo -u whatsapp-inbox npm run db:deploy sudo -u whatsapp-inbox npm run db:seed ``` ## 8) Build & verifikasi ```bash cd /var/www/whatsapp-inbox sudo -u whatsapp-inbox npm run ci:verify ``` Jika berhasil, lanjut ke service. ## 9) Test manual port 3002 ```bash cd /var/www/whatsapp-inbox sudo -u whatsapp-inbox npm run start -- --hostname 127.0.0.1 --port 3002 ``` Di terminal lain: ```bash curl -I http://127.0.0.1:3002 curl -s http://127.0.0.1:3002/api/health ``` ## 10) Buat service systemd (Next.js app) Buat file `/etc/systemd/system/whatsapp-inbox.service`: ```ini [Unit] Description=WhatsApp Inbox (Next.js App) After=network.target postgresql.service [Service] Type=simple User=whatsapp-inbox Group=whatsapp-inbox WorkingDirectory=/var/www/whatsapp-inbox EnvironmentFile=/var/www/whatsapp-inbox/.env ExecStart=/usr/bin/npm run start -- --hostname 127.0.0.1 --port 3002 Restart=always RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target ``` Enable dan start: ```bash sudo systemctl daemon-reload sudo systemctl enable --now whatsapp-inbox sudo systemctl status whatsapp-inbox ``` ## 11) Service retry worker (daemon) Buat file `/etc/systemd/system/whatsapp-inbox-retry.service`: ```ini [Unit] Description=WhatsApp Inbox Campaign Retry Daemon After=network.target whatsapp-inbox.service [Service] Type=simple User=whatsapp-inbox Group=whatsapp-inbox WorkingDirectory=/var/www/whatsapp-inbox EnvironmentFile=/var/www/whatsapp-inbox/.env ExecStart=/usr/bin/npm run job:campaign-retry:daemon Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable --now whatsapp-inbox-retry sudo systemctl status whatsapp-inbox-retry ``` ## 12) Konfigurasi Nginx reverse proxy Buat file `/etc/nginx/sites-available/app.zappcare.id`: ```nginx server { listen 80; server_name app.zappcare.id; location /.well-known/acme-challenge/ { root /var/www/html; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name app.zappcare.id; client_max_body_size 20m; proxy_buffering off; ssl_certificate /etc/letsencrypt/live/app.zappcare.id/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app.zappcare.id/privkey.pem; location / { proxy_pass http://127.0.0.1:3002; proxy_http_version 1.1; proxy_set_header Connection ""; 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_set_header X-Forwarded-Host $host; proxy_read_timeout 120s; proxy_send_timeout 120s; } } ``` Aktifkan site dan reload: ```bash sudo ln -s /etc/nginx/sites-available/app.zappcare.id /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` ## 13) Install SSL (Let's Encrypt) ```bash sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d app.zappcare.id ``` ## 14) Cek akhir deployment ```bash curl -I https://app.zappcare.id curl -I https://app.zappcare.id/api/health curl -s https://app.zappcare.id/api/health | jq ``` Ops check: ```bash APP_URL=https://app.zappcare.id NEXT_PUBLIC_APP_URL=https://app.zappcare.id OPS_BASE_URL=https://app.zappcare.id npm run ops:readiness APP_URL=https://app.zappcare.id NEXT_PUBLIC_APP_URL=https://app.zappcare.id OPS_BASE_URL=https://app.zappcare.id npm run ops:smoke ``` ## 15) Update rutin ```bash cd /var/www/whatsapp-inbox git pull origin main sudo -u whatsapp-inbox npm ci sudo -u whatsapp-inbox npm run ci:verify sudo -u whatsapp-inbox npm run db:deploy sudo systemctl restart whatsapp-inbox sudo systemctl restart whatsapp-inbox-retry ``` ## 16) Rollback cepat ```bash cd /var/www/whatsapp-inbox git log --oneline -n 10 git checkout sudo systemctl restart whatsapp-inbox ``` ## 17) Hal penting untuk environment produksi - Pastikan semua token tidak lagi `change-me`/`your-*`. - Monitor `ops:readiness` + `ops:smoke` tiap hari / saat deploy. - Jalankan `ops:maintenance` berkala (cron harian/mingguan). - Pastikan job retry tetap hidup: - `sudo systemctl status whatsapp-inbox-retry` ```bash sudo systemctl status whatsapp-inbox sudo systemctl status whatsapp-inbox-retry journalctl -u whatsapp-inbox -f journalctl -u whatsapp-inbox-retry -f ``` ## 18) Troubleshooting cepat ### 18.1 Domain menjawab 502 Bad Gateway ```bash sudo systemctl status whatsapp-inbox sudo ss -ltnp | rg "127.0.0.1:3002" sudo nginx -t sudo systemctl reload nginx ``` - Jika service app tidak jalan, cek log: `journalctl -u whatsapp-inbox -n 200 --no-pager` - Pastikan Nginx proxy ke `127.0.0.1:3002` (bukan 3000/3001). - Jika app jalan, cek `.env` dan `PORT=3002`. ### 18.2 Halaman health 500 / tidak bisa start ```bash cd /var/www/whatsapp-inbox sudo -u whatsapp-inbox npm run ops:readiness ``` - Jika `DATABASE_URL` error: - cek service PostgreSQL: `sudo systemctl status postgresql` - cek koneksi manual: `psql "postgresql://whatsapp_inbox:GANTI_PASSWORD_KUAT@127.0.0.1:5432/whatsapp_inbox?schema=public" -c '\dt'` - Jika token/secret bermasalah: - cek value `AUTH_SECRET`, `CAMPAIGN_RETRY_JOB_TOKEN`, `WHATSAPP_WEBHOOK_SECRET` - jangan ada placeholder seperti `change-me`, `your-*` ### 18.3 Retry job tidak berjalan ```bash sudo systemctl status whatsapp-inbox-retry sudo -u whatsapp-inbox npm run job:campaign-retry ``` - Cek token pada `.env` (`CAMPAIGN_RETRY_JOB_TOKEN`) dan endpoint: - `https://app.zappcare.id/api/jobs/campaign-retry?token=` - Jika lock stuck, jalankan: - `sudo -u whatsapp-inbox npm run job:campaign-retry` - restart service: `sudo systemctl restart whatsapp-inbox-retry` ### 18.4 Webhook tidak terima event ```bash curl -i https://app.zappcare.id/api/webhooks/whatsapp ``` - Pastikan URL di Meta adalah: - `https://app.zappcare.id/api/webhooks/whatsapp` - Untuk validasi: - cek `WHATSAPP_WEBHOOK_VERIFY_TOKEN` - cek `WHATSAPP_WEBHOOK_SECRET` - cek `Signature` header dari provider sesuai konfigurasi ### 18.5 Port bentrok / service lain ```bash sudo lsof -i :3000 sudo lsof -i :3001 sudo lsof -i :3002 ``` - Jika app tidak boleh pakai 3000/3001, pastikan `.env` dan service tetap di 3002. - Jika ada proses yang tidak dikenal, stop service itu atau pindahkan port dengan service systemd yang benar. ### 18.6 Cek cepat setelah reboot atau deploy ```bash sudo systemctl restart whatsapp-inbox sudo systemctl restart whatsapp-inbox-retry sudo systemctl status whatsapp-inbox whatsapp-inbox-retry --no-pager curl -s https://app.zappcare.id/api/health | cat ``` Jika masih ada masalah: ```bash APP_URL=https://app.zappcare.id NEXT_PUBLIC_APP_URL=https://app.zappcare.id OPS_BASE_URL=https://app.zappcare.id npm run ops:readiness APP_URL=https://app.zappcare.id NEXT_PUBLIC_APP_URL=https://app.zappcare.id OPS_BASE_URL=https://app.zappcare.id npm run ops:smoke ```