Instalasi ZenRadius — dari A sampai Z
Panduan lengkap memasang ZenRadius (billing RT/RW Net, RADIUS, ACS TR-069, WhatsApp gateway, PPOB) di VPS hingga siap production. Semua blok kode dapat langsung di-copy. Ikuti berurutan dari atas ke bawah.
AArsitektur Deployment
Aplikasi berjalan sebagai satu proses Node.js di 127.0.0.1:3001 yang dikelola PM2. Akses publik lewat salah satu dari dua jalur:
Mode Normal (VPS punya 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 (NAT / IP private)
- 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.BSpesifikasi Hardware
SQLite dan Node.js ringan. Kebutuhan tumbuh bersama jumlah pelanggan, sesi RADIUS, dan perangkat ONT yang inform ke ACS.
| Skala | Pelanggan | vCPU | RAM | Disk | Catatan |
|---|---|---|---|---|---|
| Minimum | ≤ 300 | 1 | 1 GB (+1 GB swap) | 20 GB SSD | Baileys WhatsApp memakan ± 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)
CSoftware & Sistem Operasi
| Komponen | Versi | Dipasang oleh |
|---|---|---|
| OS | Ubuntu 22.04 / 24.04 LTS atau Debian 12 (64-bit) | Anda (VPS provider) |
| Node.js | 20 LTS (>=20) | install.sh (NodeSource) |
| 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) — lihat bagian H |
| git, curl | — | install.sh |
DDomain & DNS
Siapkan domain/subdomain sebelum instalasi, misal billing.isp-anda.com. Lisensi ZenRadius terikat pada domain ini.
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 di bagian H. Domain wajib sudah menggunakan nameserver Cloudflare.
dig +short billing.isp-anda.com nslookup billing.isp-anda.com 1.1.1.1
EPersiapan 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
FInstalasi 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 (
node -e "require('./config/database')") +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",...}GKonfigurasi .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.
# Port aplikasi — harus sama dengan server_port di settings.json & target Nginx/Tunnel PORT=3001 NODE_ENV=production # Login admin BOOTSTRAP (hanya aktif selama admin_password di settings.json kosong) MASTER_ADMIN_USERNAME=zenradius MASTER_ADMIN_PASSWORD=GantiSegeraSetelahLogin! # Wajib unik & acak (install.sh mengisi otomatis jika masih placeholder) SESSION_SECRET=isi-dengan-string-acak-64-karakter SETTINGS_MASTER_KEY=isi-dengan-string-acak-64-karakter # Secret verifikasi webhook pembayaran (QRIS/VA notifikasi) MY_WEBHOOK_SECRET=isi-secret-webhook-anda
openssl rand -hex 32 # jalankan 2x: untuk SESSION_SECRET dan SETTINGS_MASTER_KEYsettings.json). Jika berubah, data lama tidak bisa didekripsi. Simpan salinannya di password manager.chmod 600 /opt/zenradius/.env pm2 restart zenradius --update-env
HCloudflare Tunnel (untuk VPS NAT / IP private)
Gunakan jika curl ifconfig.me menunjukkan IP berbeda dengan IP interface VPS (ip a), atau Certbot gagal. Cloudflare menjadi terminasi HTTPS, aplikasi tetap di localhost:3001.
Install 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
Login & buat tunnel
Perintah login menampilkan URL — buka di browser, pilih domain Anda.
cloudflared tunnel login
cloudflared tunnel create zenradius
cloudflared tunnel list # catat UUID tunnelKonfigurasi ingress
sudo mkdir -p /etc/cloudflared
sudo tee /etc/cloudflared/config.yml >/dev/null <<'EOF'
tunnel: <UUID_TUNNEL>
credentials-file: /root/.cloudflared/<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
EOFArahkan DNS & jalankan sebagai 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 memakai cookie secure di production, sehingga login berfungsi di balik tunnel.IAlternatif: 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 (bagian H) yang mengarah ke http://127.0.0.1:3001.
git pull && docker compose up -d --build.JLogin Pertama & 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 adalah settings.json). Jika lupa password: hapus key admin_username & admin_password dari settings.json, lalu pm2 restart zenradius — kredensial .env aktif kembali.
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.KLisensi Domain
ZenRadius memverifikasi lisensi per domain secara offline (signature) dan mengirim heartbeat berkala. Tanpa key yang valid aplikasi berjalan dalam masa tenggang (grace period) 7 hari dan menampilkan peringatan, lalu akses dikunci penuh.
- Order lisensi ke Developer resmi via WhatsApp +62 851-7800-8881 — atau klik tombol Order Lisensi di panel admin (Pengaturan → Lisensi Domain). Sebutkan domain persis seperti yang dipakai (mis.
billing.isp-anda.com, tanpahttps://). - Setelah pembayaran, Developer menerbitkan Serial Kunci Aktivasi untuk domain Anda.
- Login sebagai Super Admin, buka Pengaturan → Lisensi Domain, tempel key, klik Aktivasi Lisensi.
- Status berubah menjadi Valid; heartbeat pertama dikirim otomatis.
pm2 logs zenradius --lines 200 | grep -i -E "license|lisensi|grace"
localhost/IP lokal tidak memerlukan lisensi (untuk pengujian internal). Lisensi diperlukan saat aplikasi diakses melalui domain publik.LIntegrasi Modul
Semua modul sudah terpasang dalam satu aplikasi; Anda cukup mengonfigurasinya dari panel admin.
1. MikroTik (PPPoE / Hotspot / Isolir)
/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=PasswordKuat123 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).
2. 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=SecretNAS123 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
3. 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.
4. WhatsApp Gateway
| Gateway | Konfigurasi |
|---|---|
| Baileys (default, gratis) | Menu WhatsApp → Scan QR dengan nomor khusus ISP. 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. |
5. Telegram Bot
Buat bot via @BotFather, isi token & chat ID admin di Pengaturan → Telegram. Bot menerima perintah monitoring dan menerima file backup harian otomatis.
6. 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.
7. Digiflazz (PPOB)
Pengaturan → Digiflazz: username, API key (production), sinkronkan produk. Webhook: https://domain/webhook/digiflazz.
8. OLT & ODP
Menu OLT: tambah OLT (ZTE/Huawei/VSOL/HSGQ) dengan SNMP community/telnet. Menu ODP untuk pemetaan port & peta lokasi pelanggan.
MKeamanan 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
NBackup & 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
OUpdate 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.
PPerintah 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 (otomatis, uji) | certbot renew --dry-run |
| Status tunnel | systemctl status cloudflared |
| Integritas DB | sqlite3 database/zenradius.db "PRAGMA integrity_check;" |
QTroubleshooting
| 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 (H) 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 |
| Login sukses tapi terlempar ke login | Cookie secure tapi akses via HTTP | Akses via HTTPS; atau untuk uji lokal set cookie_secure: false di settings.json |
better-sqlite3 gagal build | Build tools hilang | apt install -y python3 make g++ && npm rebuild better-sqlite3 |
| GET /acs 404 (versi lama) / ONT tidak muncul | Salah URL, port tertutup | ACS URL = http://IP:3001/acs; buka port 3001 dari subnet ONT |
Peringatan GenieACS 127.0.0.1:7557 | Monitoring GenieACS eksternal aktif tanpa server | Nonaktifkan monitoring GenieACS di Pengaturan atau isi URL yang benar |
| Lisensi “grace period” | Key belum diisi / domain tidak cocok | Lihat bagian K |
| WhatsApp sering logout | Sesi Baileys / nomor dipakai multi-device lain | Hapus auth_info_baileys/, scan ulang; gunakan nomor khusus |
pm2 logs zenradius --err --lines 100
ss -ltnp | grep 3001
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3001/health
tail -n 50 /opt/zenradius/logs/error.log
nginx -t; systemctl status nginx --no-pager | head -n 5ZChecklist 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.