Deploy & Instalasi
Pasang ZenRadius di VPS atau server sendiri dalam 3 mode: normal (Nginx + SSL otomatis), Cloudflare Tunnel (NAT/IP private), atau Docker Compose.
Arsitektur Deployment
ZenRadius berjalan sebagai satu proses Node.js di 127.0.0.1:3001 yang dikelola PM2, lalu diteruskan ke pengguna melalui Nginx atau Cloudflare Tunnel. Dalam satu aplikasi Anda mendapatkan billing ISP, RADIUS server, ACS TR-069, WhatsApp gateway, PPOB, dan monitoring operasional.
Mode Normal (IP publik)
- Nginx reverse proxy port 80/443
- SSL otomatis via Certbot (Let's Encrypt)
- Domain A-record → IP VPS
- Perintah:
sudo ./install.sh domain.com
Mode Cloudflare Tunnel
- Tanpa Nginx & Certbot
- HTTPS & domain ditangani Cloudflare
- Wajib jika VPS di belakang NAT / tanpa IP publik
- Perintah:
sudo ./install.sh --cloudflare
/acs) serta akses API MikroTik 8728 dari server ke router.Spesifikasi Server
Gunakan rekomendasi berikut sebagai baseline. Kebutuhan bertambah mengikuti jumlah pelanggan, sesi RADIUS, perangkat ONT, dan trafik WhatsApp.
| Skala | Pelanggan | vCPU | RAM | Disk | Catatan |
|---|---|---|---|---|---|
| Minimum | ≤ 300 | 1 | 1 GB (+1 GB swap) | 20 GB SSD | Baileys WhatsApp ± 250 MB RAM; wajib swap. |
| Direkomendasikan | 300 – 2.000 | 2 | 2–4 GB | 40 GB SSD/NVMe | Nyaman untuk RADIUS + ACS + WA + cron billing. |
| Besar | > 2.000 | 4 | 8 GB | 80 GB NVMe | Backup harian ± 1–5 MB/hari; log dirotasi PM2. |
Jaringan
- Koneksi stabil ke router MikroTik (API 8728/8729)
- Latensi rendah ke NAS untuk RADIUS (< 50 ms)
- Bandwidth ≥ 10 Mbps cukup
Penyimpanan
- SSD wajib — SQLite sensitif I/O
- Folder penting:
database/,backups/,public/uploads/,auth_info_baileys/
Waktu
- NTP aktif — tagihan, cron & isolir bergantung jam server
- Timezone aplikasi diatur di Pengaturan (default Asia/Jakarta)
Software & Sistem Operasi
| Komponen | Versi | Dipasang oleh |
|---|---|---|
| OS | Ubuntu 22.04/24.04 LTS atau Debian 12 (64-bit) | Anda (VPS provider) |
| Node.js / npm | 20 LTS (npm 10.x selaras Node 20) | install.sh (NodeSource & npm 10.9.9) |
| Build tools | python3, make, g++ (untuk better-sqlite3) | install.sh |
| PM2 | terbaru | install.sh |
| Nginx + Certbot | dari repo Ubuntu | install.sh (mode normal saja) |
| cloudflared | terbaru | Anda (mode Cloudflare) |
| git, curl | — | install.sh |
Domain & DNS
Siapkan domain/subdomain sebelum instalasi, misal billing.isp-anda.com. Lisensi ZenRadius terikat pada domain ini beserta Kode Instalasi server (instalasi tanpa domain via IP lokal juga didukung).
Mode Normal (IP publik)
Type : A Name : billing (atau @ untuk root domain) Value: <IP_PUBLIK_VPS> TTL : Auto / 300 Proxy: DNS only (awan abu-abu) saat Certbot berjalan pertama kali
Mode Cloudflare Tunnel
Tidak perlu A-record manual — record CNAME dibuat otomatis oleh perintah cloudflared tunnel route dns. Domain wajib sudah menggunakan nameserver Cloudflare.
dig +short billing.isp-anda.com nslookup billing.isp-anda.com 1.1.1.1
Persiapan Server
Login SSH & update sistem
ssh root@<IP_VPS> apt update && apt upgrade -y apt install -y git curl ufw timedatectl set-timezone Asia/Jakarta timedatectl set-ntp true
Buat swap (wajib untuk RAM ≤ 2 GB)
fallocate -l 2G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile none swap sw 0 0' >> /etc/fstab free -h
Firewall dasar (UFW)
Buka SSH, HTTP/HTTPS (mode normal), RADIUS untuk subnet router Anda, dan port ACS bila ONT inform langsung ke server.
ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp # Mode normal (Nginx). Lewati dua baris ini jika memakai Cloudflare Tunnel ufw allow 80/tcp ufw allow 443/tcp # RADIUS: ganti 10.0.0.0/8 dengan subnet router MikroTik Anda ufw allow from 10.0.0.0/8 to any port 1812 proto udp ufw allow from 10.0.0.0/8 to any port 1813 proto udp # ACS TR-069 (ONT inform ke http://IP:3001/acs) — batasi ke subnet ONT ufw allow from 10.0.0.0/8 to any port 3001 proto tcp ufw enable ufw status verbose
Clone repository
cd /opt git clone https://github.com/zenradius/zenradius.git cd zenradius
Instalasi via install.sh
Skrip resmi memasang Node.js 20, build tools, PM2, (Nginx + Certbot pada mode normal), dependensi aplikasi, menyiapkan .env & settings.json, menginisialisasi database, lalu menjalankan aplikasi lewat PM2 dengan auto-start saat reboot. Aman dijalankan ulang (idempoten).
Pilihan 1 — Mode Normal (IP publik, Nginx + SSL otomatis)
cd /opt/zenradius chmod +x install.sh sudo ./install.sh billing.isp-anda.com
Pilihan 2 — Mode Cloudflare Tunnel (VPS NAT / tanpa IP publik)
cd /opt/zenradius chmod +x install.sh sudo ./install.sh --cloudflare
Yang dilakukan skrip
- Validasi: harus
sudo, OS Ubuntu/Debian, dijalankan dari folder repo. - Validasi domain (menolak URL lengkap). Dilewati pada
--cloudflare. - Install Node.js 20, python3/make/g++, PM2; Nginx & Certbot hanya di mode normal.
npm ci --omit=dev(kompilasibetter-sqlite3).- Salin
.env.example→.envjika belum ada; isi otomatisSESSION_SECRET&SETTINGS_MASTER_KEYacak bila masih placeholder. - Buat
settings.jsonawal{"server_port": PORT}jika belum ada. - Inisialisasi skema DB +
scripts/verify-database.js. DB baru disalin daridatabase/seed/zenradius-seed.db. - Nginx vhost + Certbot (mode normal). Dilewati jika sudah ada.
pm2 start/reload,pm2 save,pm2 startup.
pm2 status
pm2 logs zenradius --lines 30
curl -s http://127.0.0.1:3001/health
# Harus: {"status":"ok","version":"ZenRadius V.x","database":"ok",...}Konfigurasi .env
Berkas .env berisi rahasia sistem dan kredensial bootstrap admin. Pada NODE_ENV=production aplikasi menolak start jika SESSION_SECRET atau SETTINGS_MASTER_KEY kosong/placeholder.
# ZenRadius — Konfigurasi Environment (/opt/zenradius/.env) PORT=3001 NODE_ENV=production LOG_LEVEL=info # Login Admin Bootstrap MASTER_ADMIN_USERNAME=<USERNAME_ADMIN> MASTER_ADMIN_PASSWORD=<PASSWORD_KUAT> # Rahasia Sistem (Wajib Unik & Acak) SESSION_SECRET=ganti-dengan-string-acak-64-karakter SETTINGS_MASTER_KEY=ganti-dengan-string-acak-64-karakter # Webhook Pembayaran MY_WEBHOOK_SECRET=ganti-dengan-string-acak-64-karakter # GenieACS (Opsional) GENIEACS_URL=http://localhost:7557 GENIEACS_USERNAME= GENIEACS_PASSWORD= # Path Data (Opsional) ZENRADIUS_DB_PATH= ZENRADIUS_SETTINGS_PATH= # Lisensi & Status ZENRADIUS_HEARTBEAT=on HEALTH_CHECK_URL=http://127.0.0.1:3001/health
Edit .env langsung di terminal VPS
cd /opt/zenradius sudo nano .env
Tempel isi .env lengkap, tekan Ctrl+O → Enter untuk menyimpan, lalu Ctrl+X untuk keluar.
sudo chmod 600 /opt/zenradius/.env sudo chown root:root /opt/zenradius/.env pm2 restart zenradius --update-env pm2 status curl -s http://127.0.0.1:3001/health
settings.json). Jika berubah, data lama tidak bisa didekripsi. Simpan salinannya di password manager.Cloudflare Tunnel (VPS NAT / IP private)
cloudflared memungkinkan VPS diakses aman dari publik dengan SSL gratis — tanpa IP publik statis, tanpa port forwarding, tanpa Certbot. Aplikasi tetap berjalan di localhost:3001.
Opsi A — Via Cloudflare Zero Trust Dashboard (disarankan)
- Buka dashboard Cloudflare Zero Trust → Networks → Tunnels.
- Klik Add a tunnel → pilih Cloudflare Managed → beri nama tunnel (mis.
zenradius-tunnel). - Pilih OS Debian/Ubuntu dan arsitektur CPU VPS (mis. 64-bit).
- Salin perintah Install and run a connector (berisi token khusus Anda) dan jalankan di VPS:
sudo cloudflared service install <TOKEN_KHUSUS_DARI_DASHBOARD>
- Klik Next → tambahkan Public Hostname: subdomain/domain Anda (mis.
billing.isp-anda.com), Service TypeHTTP, URLlocalhost:3001. - Klik Save Hostname. Tunnel langsung aktif dan domain bisa diakses via HTTPS!
Opsi B — Manual via Terminal (CLI)
1. Install repositori & paket cloudflared:
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list sudo apt update && sudo apt install -y cloudflared cloudflared --version
2. Otentikasi & buat tunnel baru:
cloudflared tunnel login cloudflared tunnel create zenradius cloudflared tunnel list # Catat UUID tunnel yang muncul
3. Buat berkas konfigurasi ingress:
sudo mkdir -p /etc/cloudflared
sudo tee /etc/cloudflared/config.yml >/dev/null <<'EOF'
tunnel: <GANTI_DENGAN_UUID_TUNNEL>
credentials-file: /root/.cloudflared/<GANTI_DENGAN_UUID_TUNNEL>.json
ingress:
- hostname: billing.isp-anda.com
service: http://127.0.0.1:3001
originRequest:
noTLSVerify: true
httpHostHeader: billing.isp-anda.com
- service: http_status:404
EOF4. Hubungkan ke DNS & jalankan service:
cloudflared tunnel route dns zenradius billing.isp-anda.com sudo cloudflared service install sudo systemctl enable --now cloudflared sudo systemctl status cloudflared --no-pager curl -I https://billing.isp-anda.com/health
trust proxy dan cookie secure bawaan sehingga sesi login dan webhook berjalan lancar melalui tunnel.Alternatif: Docker Compose
Untuk yang lebih nyaman dengan container. Data persisten di-bind ke folder host sehingga aman saat rebuild.
curl -fsSL https://get.docker.com | sh
git clone https://github.com/zenradius/zenradius.git /opt/zenradius && cd /opt/zenradius
cp .env.example .env
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=$(openssl rand -hex 32)|" .env
sed -i "s|^SETTINGS_MASTER_KEY=.*|SETTINGS_MASTER_KEY=$(openssl rand -hex 32)|" .env
# settings.json WAJIB dibuat lebih dulu (kalau tidak, Docker membuat DIREKTORI kosong bernama settings.json)
echo '{"server_port": 3001}' > settings.json
mkdir -p database data public/uploads auth_info_baileys backups logs
chown -R 1000:1000 database data public/uploads auth_info_baileys backups logs settings.json
docker compose up -d --build
docker compose ps
docker compose logs -f zenradiusContainer mem-bind 127.0.0.1:3001. Expose ke publik tetap lewat Nginx + Certbot (mode normal) atau Cloudflare Tunnel yang mengarah ke http://127.0.0.1:3001.
git pull && docker compose up -d --build.Troubleshooting & Operasional
| Gejala | Penyebab | Solusi |
|---|---|---|
| App tidak start: SESSION_SECRET wajib… | Secret kosong/placeholder di production | Isi SESSION_SECRET & SETTINGS_MASTER_KEY di .env, pm2 restart zenradius --update-env |
| 502 Bad Gateway | App mati / port beda | pm2 logs; pastikan server_port di settings.json = PORT = target Nginx/Tunnel |
| Certbot gagal (HTTP-01) | VPS tanpa IP publik / DNS di-proxy | Gunakan Cloudflare Tunnel atau set DNS "DNS only" sementara |
| Login admin selalu gagal | Kredensial .env nonaktif karena admin_password sudah terisi | Hapus admin_username/admin_password di settings.json, restart |
better-sqlite3 gagal build | Build tools hilang | apt install -y python3 make g++ && npm rebuild better-sqlite3 |
| GET /acs 404 / ONT tidak muncul | Salah URL, port tertutup | ACS URL = http://IP:3001/acs; buka port 3001 dari subnet ONT |
| QR WhatsApp tidak muncul | whatsapp_enabled = false atau bot belum start | Pengaturan → WhatsApp → set Aktif lalu Simpan. Cek pm2 logs zenradius | grep WA |
Checklist Go-Live
- VPS sesuai spek, swap aktif, NTP & timezone benar
install.shselesai tanpa error,pm2 statusonline,/health= ok- Domain diakses via HTTPS (Nginx+Certbot atau Cloudflare Tunnel)
.env: secret unik, kredensial bootstrap diganti,chmod 600- Password admin diganti di panel; identitas & logo perusahaan diisi
- Lisensi domain valid (bukan grace period)
- Router MikroTik terhubung (test koneksi OK), paket & profile isolir dibuat
- RADIUS NAS terdaftar & MikroTik autentikasi via RADIUS
- ACS menerima inform dari ONT uji
- WhatsApp gateway tersambung; notifikasi tagihan diuji ke nomor sendiri
- Payment gateway/QRIS webhook diuji dengan transaksi kecil
- Auto backup aktif dan file backup pertama tersimpan / terkirim ke Telegram
- UFW & fail2ban aktif; port 3001 tidak terbuka ke publik
- Snapshot VPS / backup penuh pertama sudah diunduh ke lokal
.env dan key lisensi di tempat aman.Konfigurasi Aplikasi
Login pertama, lisensi, lalu hubungkan seluruh modul: MikroTik, RADIUS, ACS, WhatsApp, payment gateway, PPOB, hingga OLT & ODP.
Login & Setup Awal
Buka panel admin
Kunjungi https://billing.isp-anda.com/admin. Login dengan MASTER_ADMIN_USERNAME/MASTER_ADMIN_PASSWORD dari .env.
Ganti kredensial admin
Pengaturan → Kredensial Admin. Setelah diisi, kredensial .env otomatis nonaktif (yang berlaku settings.json). Jika lupa password: hapus key admin_username & admin_password dari settings.json, lalu pm2 restart zenradius.
Identitas perusahaan
Pengaturan → Umum: nama ISP, alamat, logo (PNG/SVG), footer, timezone, format invoice.
Bahasa
Tersedia Bahasa Indonesia & English (locales/id.json, locales/en.json).
/customer; teknisi: /tech; kolektor: /collector; reseller: /agent.Lisensi Instalasi
ZenRadius memverifikasi lisensi secara offline menggunakan token bertanda tangan digital (Ed25519) yang terikat pada domain/IP dan Kode Instalasi server Anda, lalu mengirim heartbeat harian ke server lisensi. Tanpa token yang valid aplikasi berjalan dalam masa tenggang 30 hari, kemudian akses dikunci penuh.
Menemukan Kode Instalasi
Kode Instalasi (format XXXX-XXXX-XXXX) dibuat otomatis saat aplikasi pertama kali dijalankan dan disimpan di data/instance.json. Anda dapat melihatnya di:
- Pengaturan → Lisensi (panel admin) — klik Order Lisensi, kode otomatis disertakan dalam pesan WhatsApp.
- Halaman "Aktivasi Lisensi Diperlukan" yang muncul setelah masa tenggang habis.
data/ ikut di-backup / dipasang sebagai volume Docker. Jika instance.json hilang atau server berpindah mesin, Kode Instalasi berubah dan token perlu diterbitkan ulang.Cara Aktivasi Lisensi
- Order lisensi via portal resmi ZenRadius Web — paling mudah dari aplikasi: Pengaturan → Lisensi → Order Lisensi. Sertakan domain/IP persis (mis.
billing.isp-anda.com, tanpahttps://) dan Kode Instalasi. Untuk instalasi tanpa domain (akses IP lokal/LAN), cukup Kode Instalasi. - Setelah pembayaran, Admin menerbitkan Token Lisensi berawalan
ZRL1.(teks panjang satu baris) dan mengirimkannya ke Anda. - Login sebagai Super Admin, buka Pengaturan → Lisensi, tempel token utuh, klik Aktivasi Lisensi.
- Status berubah menjadi Lisensi Aktif; heartbeat pertama dikirim otomatis.
Integrasi MikroTik
Buat user & group khusus di RouterOS dengan policy minimal, lalu daftarkan router di panel ZenRadius.
/user group add name=zenradius policy=api,read,write,test,policy,!local,!telnet,!ssh,!ftp,!reboot,!password,!web,!sniff,!sensitive,!romon /user add name=zenradius group=zenradius password=<PASSWORD_KUAT> address=<IP_SERVER_ZENRADIUS>/32 /ip service set api address=<IP_SERVER_ZENRADIUS>/32 disabled=no port=8728
Panel: MikroTik → Tambah Router (host, port 8728, user, password) → Test Koneksi. Buat Paket dengan profile PPPoE normal & profile isolir (default isolir).
RADIUS Server Built-in
Panel: RADIUS Server → aktifkan (port 1812/1813), tambah NAS (IP router + secret). Di MikroTik:
/radius add service=ppp,hotspot address=<IP_SERVER_ZENRADIUS> secret=<SECRET_NAS> timeout=3s /ppp aaa set use-radius=yes accounting=yes interim-update=5m /radius incoming set accept=yes port=3799
ss -lunp | grep -E '1812|1813' pm2 logs zenradius --lines 50 | grep -i radius
ACS TR-069 Built-in (ONT/ONU)
Endpoint CWMP: http://<IP_SERVER>:3001/acs (POST). Buka GET /acs di browser untuk melihat status. Set di ONT: ACS URL = URL di atas, Periodic Inform = 300 s. Perangkat yang inform muncul di menu ACS. Anda juga bisa menambah GenieACS eksternal di menu GenieACS jika sudah ada.
WhatsApp Gateway
| Gateway | Konfigurasi |
|---|---|
| Baileys (default, gratis) | Menu WhatsApp → QR muncul otomatis saat aplikasi start (juga di pm2 logs zenradius). Scan dengan nomor khusus ISP via Perangkat Tertaut. Sesi tersimpan di auth_info_baileys/. Untuk nomor besar gunakan wa_gateway_type lain. |
| Meta Cloud API | Isi Phone Number ID, Access Token, Verify Token; webhook https://domain/webhook/meta-whatsapp. |
| Fonnte / Wablas / HTTP generic | Isi URL & token di Pengaturan → WhatsApp. |
Telegram Bot
Buat bot via @BotFather, isi token & chat ID admin di Pengaturan → Telegram. Bot menerima perintah monitoring dan menerima file backup harian otomatis.
Payment Gateway & QRIS
Pengaturan → Pembayaran: Tripay / Midtrans / Xendit / Duitku (API key), atau QRIS statis + notifikasi via webhook mutasi. URL callback: https://domain/webhook/<gateway>. Pastikan MY_WEBHOOK_SECRET di .env sama dengan yang disetel di aplikasi notifikasi.
Digiflazz (PPOB)
Pengaturan → Digiflazz: username, API key (production), sinkronkan produk. Webhook: https://domain/webhook/digiflazz.
OLT & ODP
Menu OLT: tambah OLT (ZTE/Huawei/VSOL/HSGQ) dengan SNMP community/telnet. Menu ODP untuk pemetaan port & peta lokasi pelanggan.
Keamanan Production
- Ganti password admin bootstrap dan semua password default (RADIUS secret, MikroTik).
- Nginx/Cloudflare hanya meneruskan ke
127.0.0.1:3001; port 3001 tidak dibuka ke internet (kecuali dibatasi ke subnet ONT untuk ACS). - Nonaktifkan login root SSH & gunakan SSH key.
- Rate limiter login sudah aktif (
middleware/rateLimiter.js); cookieHttpOnly,Secure,SameSite=Lax. - Backup otomatis aktif + salin ke luar server (Telegram/rclone).
apt install -y fail2ban systemctl enable --now fail2ban sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config sed -i 's/^#\?PermitRootLogin .*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config systemctl restart ssh chmod 600 /opt/zenradius/.env /opt/zenradius/settings.json
apt install -y unattended-upgrades dpkg-reconfigure -plow unattended-upgrades
Backup & Restore
Menu Backup di panel admin membuat snapshot database (SQLite Backup API, diverifikasi integrity_check) dan settings.json ke folder backups/. Aktifkan Auto Backup di Pengaturan (default jadwal 0 2 * * * = 02:00).
cd /opt/zenradius tar -czf /root/zenradius-full-$(date +%F).tar.gz .env settings.json database backups public/uploads auth_info_baileys data # salin ke komputer lokal: scp root@<IP_VPS>:/root/zenradius-full-*.tar.gz .
# Via panel: Backup → Restore (atau Upload & Restore) → lalu WAJIB restart: pm2 restart zenradius # Manual (server baru): cd /opt/zenradius && pm2 stop zenradius tar -xzf /root/zenradius-full-YYYY-MM-DD.tar.gz -C /opt/zenradius pm2 start zenradius
Update Aplikasi
Cara resmi: panel admin → Update GitHub (/admin/update). Alternatif manual:
cd /opt/zenradius git pull npm ci --omit=dev --no-audit --no-fund node scripts/verify-database.js pm2 reload zenradius pm2 logs zenradius --lines 30
Migrasi skema database berjalan otomatis & idempoten saat aplikasi start. .env, settings.json, database/, dan upload tidak tersentuh oleh update.
Perintah Operasional Harian
| Aksi | Perintah |
|---|---|
| Status proses | pm2 status |
| Log realtime | pm2 logs zenradius |
| Restart / reload tanpa downtime | pm2 restart zenradius / pm2 reload zenradius |
| Monitor CPU/RAM | pm2 monit |
| Simpan daftar proses (setelah perubahan) | pm2 save |
| Health check | curl -s http://127.0.0.1:3001/health |
| Rotasi log PM2 | pm2 install pm2-logrotate |
| Nginx test & reload | nginx -t && systemctl reload nginx |
| Perpanjang SSL (uji) | certbot renew --dry-run |
| Status tunnel | systemctl status cloudflared |
| Integritas DB | sqlite3 database/zenradius.db "PRAGMA integrity_check;" |
Siap merapikan operasional jaringan?
Pilih paket Server Mandiri atau Self Hosted, lalu order lisensi sekarang. Masa tenggang 30 hari penuh sebelum aktivasi diperlukan.