ZenRadius Panduan Instalasi

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.

Node.js 20 LTS SQLite (WAL) PM2 Ubuntu 22.04 / 24.04 ± 20–30 menit

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
Port yang wajib terbuka ke perangkat jaringan Anda (bukan ke internet): 1812/1813 UDP (RADIUS ke MikroTik), 3001 TCP atau port ACS untuk ONT TR-069 (/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.

SkalaPelangganvCPURAMDiskCatatan
Minimum≤ 30011 GB (+1 GB swap)20 GB SSDBaileys WhatsApp memakan ± 250 MB RAM; wajib swap.
Direkomendasikan300 – 2.00022–4 GB40 GB SSD/NVMeNyaman untuk RADIUS + ACS + WA + cron billing.
Besar> 2.00048 GB80 GB NVMeBackup 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

KomponenVersiDipasang oleh
OSUbuntu 22.04 / 24.04 LTS atau Debian 12 (64-bit)Anda (VPS provider)
Node.js20 LTS (>=20)install.sh (NodeSource)
Build toolspython3, make, g++ (untuk better-sqlite3)install.sh
PM2terbaruinstall.sh
Nginx + Certbotdari repo Ubuntuinstall.sh (mode normal saja)
cloudflaredterbaruAnda (mode Cloudflare) — lihat bagian H
git, curlinstall.sh
Jangan memasang GenieACS/FreeRADIUS terpisah kecuali Anda memang menginginkannya. ZenRadius sudah membawa RADIUS server dan ACS (TR-069) built-in.

DDomain & DNS

Siapkan domain/subdomain sebelum instalasi, misal billing.isp-anda.com. Lisensi ZenRadius terikat pada domain ini.

Mode Normal (IP publik)

DNS record
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.

Cek propagasi DNS
dig +short billing.isp-anda.com
nslookup billing.isp-anda.com 1.1.1.1

EPersiapan Server

Login SSH & update sistem

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

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

bash
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

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

bash
cd /opt/zenradius
chmod +x install.sh
sudo ./install.sh billing.isp-anda.com

Pilihan 2 — Mode Cloudflare Tunnel (VPS NAT / tanpa IP publik)

bash
cd /opt/zenradius
chmod +x install.sh
sudo ./install.sh --cloudflare

Yang dilakukan skrip

  1. Validasi: harus sudo, OS Ubuntu/Debian, dijalankan dari folder repo.
  2. Validasi domain (menolak URL lengkap). Dilewati pada --cloudflare.
  3. Install Node.js 20, python3/make/g++, PM2; Nginx & Certbot hanya di mode normal.
  4. npm ci --omit=dev (kompilasi better-sqlite3).
  5. Salin .env.example.env jika belum ada; isi otomatis SESSION_SECRET & SETTINGS_MASTER_KEY acak bila masih placeholder.
  6. Buat settings.json awal {"server_port": PORT} jika belum ada.
  7. Inisialisasi skema DB (node -e "require('./config/database')") + scripts/verify-database.js. DB baru disalin dari database/seed/zenradius-seed.db.
  8. Nginx vhost + Certbot (mode normal). Dilewati jika sudah ada.
  9. pm2 start/reload, pm2 save, pm2 startup.
Verifikasi setelah install
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.

.env (contoh production)
# 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
Generate secret acak
openssl rand -hex 32   # jalankan 2x: untuk SESSION_SECRET dan SETTINGS_MASTER_KEY
SETTINGS_MASTER_KEY tidak boleh diubah setelah ada data terenkripsi (token WA, API key payment, dll di settings.json). Jika berubah, data lama tidak bisa didekripsi. Simpan salinannya di password manager.
Terapkan perubahan .env
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

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

bash
cloudflared tunnel login
cloudflared tunnel create zenradius
cloudflared tunnel list        # catat UUID tunnel

Konfigurasi ingress

/etc/cloudflared/config.yml
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
EOF

Arahkan DNS & jalankan sebagai service

bash
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
Di dashboard Cloudflare → SSL/TLS set Full. Aplikasi sudah 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.

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

Container 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.

Fitur Update GitHub di panel admin tidak me-restart container. Untuk update: 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).

Panel admin, teknisi, kolektor, dan agen bisa di-install sebagai PWA ke home screen (butuh HTTPS). Portal pelanggan: /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.

Lisensi Resmi • 1 Domain
Rp 300.000 / seumur hidup
Sekali bayar • Pembaruan berkelanjutan • Tanpa biaya tersembunyi
Order Lisensi via WhatsApp
  1. 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, tanpa https://).
  2. Setelah pembayaran, Developer menerbitkan Serial Kunci Aktivasi untuk domain Anda.
  3. Login sebagai Super Admin, buka Pengaturan → Lisensi Domain, tempel key, klik Aktivasi Lisensi.
  4. Status berubah menjadi Valid; heartbeat pertama dikirim otomatis.
Lisensi terikat 1 domain. Jika berpindah domain, hubungi Developer untuk migrasi key. Key tidak dapat dipindahkan antar domain secara mandiri.
Cek status lisensi dari log
pm2 logs zenradius --lines 200 | grep -i -E "license|lisensi|grace"
Akses via 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)

Di RouterOS (Winbox / terminal)
/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:

RouterOS
/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
Uji dari server
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

GatewayKonfigurasi
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 APIIsi Phone Number ID, Access Token, Verify Token; webhook https://domain/webhook/meta-whatsapp.
Fonnte / Wablas / HTTP genericIsi 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); cookie HttpOnly, Secure, SameSite=Lax.
  • Backup otomatis aktif + salin ke luar server (Telegram/rclone).
Hardening SSH & fail2ban
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
Auto security update
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).

Backup manual seluruh data ke luar server
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 .
Restore dari panel / manual
# 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
Setelah restore database dari panel, aplikasi menampilkan peringatan: restart PM2/Docker diperlukan agar koneksi database memakai data hasil restore.

OUpdate Aplikasi

Cara resmi: panel admin → Update GitHub (/admin/update). Alternatif manual:

bash
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

AksiPerintah
Status prosespm2 status
Log realtimepm2 logs zenradius
Restart / reload tanpa downtimepm2 restart zenradius / pm2 reload zenradius
Monitor CPU/RAMpm2 monit
Simpan daftar proses (setelah perubahan)pm2 save
Health checkcurl -s http://127.0.0.1:3001/health
Rotasi log PM2pm2 install pm2-logrotate
Nginx test & reloadnginx -t && systemctl reload nginx
Perpanjang SSL (otomatis, uji)certbot renew --dry-run
Status tunnelsystemctl status cloudflared
Integritas DBsqlite3 database/zenradius.db "PRAGMA integrity_check;"

QTroubleshooting

GejalaPenyebabSolusi
App tidak start: SESSION_SECRET wajib…Secret kosong/placeholder di productionIsi SESSION_SECRET & SETTINGS_MASTER_KEY di .env, pm2 restart zenradius --update-env
502 Bad GatewayApp mati / port bedapm2 logs; pastikan server_port di settings.json = PORT = target Nginx/Tunnel
Certbot gagal (HTTP-01)VPS tanpa IP publik / DNS di-proxyGunakan Cloudflare Tunnel (H) atau set DNS “DNS only” sementara
Login admin selalu gagalKredensial .env nonaktif karena admin_password sudah terisiHapus admin_username/admin_password di settings.json, restart
Login sukses tapi terlempar ke loginCookie secure tapi akses via HTTPAkses via HTTPS; atau untuk uji lokal set cookie_secure: false di settings.json
better-sqlite3 gagal buildBuild tools hilangapt install -y python3 make g++ && npm rebuild better-sqlite3
GET /acs 404 (versi lama) / ONT tidak munculSalah URL, port tertutupACS URL = http://IP:3001/acs; buka port 3001 dari subnet ONT
Peringatan GenieACS 127.0.0.1:7557Monitoring GenieACS eksternal aktif tanpa serverNonaktifkan monitoring GenieACS di Pengaturan atau isi URL yang benar
Lisensi “grace period”Key belum diisi / domain tidak cocokLihat bagian K
WhatsApp sering logoutSesi Baileys / nomor dipakai multi-device lainHapus auth_info_baileys/, scan ulang; gunakan nomor khusus
Diagnosa cepat
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 5

ZChecklist Go-Live

  • VPS sesuai spek, swap aktif, NTP & timezone benar
  • install.sh selesai tanpa error, pm2 status online, /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
Selesai! ZenRadius Anda siap production. Simpan dokumen ini bersama .env dan key lisensi di tempat aman.