🚀 Salfanet Radius — Install Wizard
Panduan instalasi manual lengkap untuk deploy Salfanet Radius ISP Management di VPS Ubuntu.
Ringkasan Instalasi
Step 1 — System Packages
Install dependencies, kernel module, timezone, NTP
Step 2 — Node.js 20 LTS
Install Node.js via NodeSource PPA
Step 3 — MySQL 8.0
Install MySQL, buat database & user
Step 4 — Deploy Aplikasi
Copy files, .env, npm install, Prisma migrate, seed
Step 5 — FreeRADIUS 3.x
Install & konfigurasi RADIUS server + SQL module
Step 6 — Nginx
Reverse proxy ke Next.js port 3000
Step 7 — PM2 & Build
Install PM2, buat swap, build Next.js, start app
Step 9 — Mobile APK (Opsional)
Build APK customer Android
Instalasi Otomatis (1 Command)
Jika tidak ingin manual, jalankan installer otomatis:
cd /root/salfanet-radius/vps-install
bash vps-installer.shInstaller otomatis akan menjalankan semua step di bawah secara berurutan dengan UI interaktif.
📦 System Requirements
Minimum Hardware
| Resource | Minimum | Rekomendasi |
|---|---|---|
| CPU | 1 core | 2 core |
| RAM | 2 GB | 4 GB |
| Disk | 15 GB | 30 GB+ |
| Network | Public IP / Cloudflare Tunnel | Static Public IP |
Supported OS
| OS | Status |
|---|---|
| Ubuntu 24.04 LTS | Recommended |
| Ubuntu 22.04 LTS | Supported |
| Ubuntu 20.04 LTS | Legacy |
| Debian 11/12 | Experimental |
Supported Environment
| Environment | Catatan |
|---|---|
| VPS (KVM/Dedicated) | Full support, UFW aktif |
| Proxmox LXC | Perlu TUN/TAP device di host, UFW di-skip (pakai host firewall) |
| VM (VirtualBox/VMware) | Full support |
| Bare Metal | Full support |
echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >> /etc/pve/lxc/<CTID>.conf dan echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >> /etc/pve/lxc/<CTID>.confSoftware yang Akan Di-Install
| Package | Versi | Fungsi |
|---|---|---|
| Node.js | 20 LTS | JavaScript runtime |
| MySQL | 8.0 | Database server |
| FreeRADIUS | 3.x | RADIUS authentication server |
| Nginx | latest | Reverse proxy & static files |
| PM2 | latest | Process manager (Node.js) |
| strongSwan | latest | IPSec/L2TP VPN |
| xl2tpd | latest | L2TP daemon |
| Chrony | latest | NTP time sync |
| Certbot | latest | SSL/TLS certificates |
⚙️ Konfigurasi
Sesuaikan nilai konfigurasi di bawah. Nilai ini akan digunakan di semua command pada step berikutnya.
Server
Database MySQL
Aplikasi
Step 1 — System Packages
Install semua system dependencies, kernel module, konfigurasi timezone dan NTP.
1.1 Update System & Install Packages
apt-get update && apt-get upgrade -yapt-get install -y \
curl wget git build-essential software-properties-common \
ufw nginx certbot python3-certbot-nginx \
sudo vim htop chrony ntpdate sshpass \
xl2tpd strongswan strongswan-pki \
libcharon-extra-plugins libstrongswan-standard-plugins1.2 Setup PPP & TUN Device
Diperlukan untuk VPN (L2TP/PPTP) dan PPPoE.
# Buat device /dev/ppp dan /dev/net/tun
[ ! -e /dev/ppp ] && mknod /dev/ppp c 108 0 && chmod 600 /dev/ppp
mkdir -p /dev/net
[ ! -e /dev/net/tun ] && mknod /dev/net/tun c 10 200 && chmod 666 /dev/net/tun
# Auto-load kernel modules
cat > /etc/modules-load.d/ppp.conf << 'EOF'
ppp_generic
ppp_async
ppp_mppe
ppp_deflate
l2tp_core
l2tp_ppp
l2tp_netlink
tun
EOF
# Load modules sekarang
for mod in ppp_generic ppp_async ppp_mppe ppp_deflate tun; do
modprobe $mod 2>/dev/null || true
done
# xl2tpd runtime directory
mkdir -p /var/run/xl2tpd
cat > /etc/tmpfiles.d/xl2tpd.conf << 'EOF'
d /var/run/xl2tpd 0755 root root -
EOF1.3 Enable IP Forwarding
# Tambahkan ke sysctl.conf
cat >> /etc/sysctl.conf << 'EOF'
# IP Forwarding - Salfanet Radius
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.tcp_syncookies=1
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.all.send_redirects=0
EOF
sysctl -p1.4 Timezone & NTP
# Set timezone Asia/Jakarta (WIB)
timedatectl set-timezone Asia/Jakarta
# Konfigurasi NTP servers Indonesia
cat > /etc/chrony/chrony.conf << 'EOF'
server 0.id.pool.ntp.org iburst
server 1.id.pool.ntp.org iburst
server 2.id.pool.ntp.org iburst
server 3.id.pool.ntp.org iburst
server asia.pool.ntp.org iburst
server time.google.com iburst
server time.cloudflare.com iburst
driftfile /var/lib/chrony/chrony.drift
makestep 1.0 3
rtcsync
allow 127.0.0.1
local stratum 10
EOF
systemctl restart chrony && systemctl enable chrony
chronyc makestep
hwclock --systohcStep 2 — Node.js 20 LTS
# Install Node.js 20 via NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejsVerifikasi
node --version # Harus v20.x.x
npm --version # Harus v10.x.xOptimasi npm untuk VPS
npm config set fetch-timeout 600000
npm config set fetch-retries 5
npm config set fetch-retry-mintimeout 10000
npm config set fetch-retry-maxtimeout 60000Step 3 — MySQL 8.0
3.1 Install MySQL
apt-get install -y mysql-server mysql-client
systemctl start mysql && systemctl enable mysql3.2 Secure MySQL
mysql -u root << 'SQLEOF'
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root123';
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
SQLEOF3.3 Buat Database & User
mysql -u root -p'root123' << 'SQLEOF'
CREATE DATABASE IF NOT EXISTS salfanet_radius CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'salfanet_user'@'localhost' IDENTIFIED BY 'salfanetradius123';
GRANT ALL PRIVILEGES ON salfanet_radius.* TO 'salfanet_user'@'localhost';
FLUSH PRIVILEGES;
SQLEOF3.4 Set Timezone MySQL
cat > /etc/mysql/mysql.conf.d/timezone.cnf << 'EOF'
[mysqld]
default-time-zone = '+07:00'
log_bin_trust_function_creators = 1
EOF
systemctl restart mysqlVerifikasi
mysql -u salfanet_user -p'salfanetradius123' salfanet_radius -e "SELECT NOW(), @@global.time_zone;"Step 4 — Deploy Aplikasi
4.1 Upload & Extract
Upload ZIP production dari PC lokal ke VPS:
# Dari PC lokal (PowerShell/Terminal):
scp salfanet-radius-v*.zip root@VPS_IP:/root/# Di VPS:
cd /root
apt-get install -y unzip
unzip salfanet-radius-v*.zip
# Copy ke app directory
mkdir -p /var/www/salfanet-radius
cp -r /root/salfanet-radius/* /var/www/salfanet-radius/
cp -r /root/salfanet-radius/.next /var/www/salfanet-radius/ 2>/dev/null || true
cp /root/salfanet-radius/.env* /var/www/salfanet-radius/ 2>/dev/null || true4.2 Buat App User
# Buat user dedicated (opsional, bisa pakai root)
useradd -r -m -s /bin/bash -d /home/salfanet salfanet
usermod -aG sudo salfanet4.3 Buat File .env
.env berisi kredensial sensitif. Pastikan permission chmod 600.cat > /var/www/salfanet-radius/.env << 'EOF'
DATABASE_URL="mysql://salfanet_user:salfanetradius123@localhost:3306/salfanet_radius?connection_limit=10&pool_timeout=20"
TZ="Asia/Jakarta"
NEXT_PUBLIC_TIMEZONE="Asia/Jakarta"
NEXT_PUBLIC_APP_NAME="SALFANET RADIUS ISP"
NEXT_PUBLIC_APP_URL="http://YOUR_VPS_IP"
NEXTAUTH_SECRET="GENERATE_ME"
NEXTAUTH_URL="http://YOUR_VPS_IP"
NODE_ENV="production"
EOF
chmod 600 /var/www/salfanet-radius/.env4.4 Upload Firebase Service Account
# Dari PC lokal:
scp src/lib/firebase-service-account.json root@YOUR_VPS_IP:/var/www/salfanet-radius/src/lib/4.5 Install Dependencies
cd /var/www/salfanet-radius
npm install --production=false4.6 Setup Prisma (Database Schema)
cd /var/www/salfanet-radius
# Generate Prisma client
npx prisma generate
# Push schema ke database (buat tabel)
npx prisma db push --accept-data-loss --skip-generate
# Verifikasi tabel dibuat
mysql -u salfanet_user -p'salfanetradius123' salfanet_radius -e "SHOW TABLES;"4.7 Seed Database (Data Awal)
cd /var/www/salfanet-radius
# Seed semua data awal (admin user, permissions, templates)
npx tsx prisma/seeds/seed-all.ts4.8 Fix Permissions
chown -R salfanet:salfanet /var/www/salfanet-radius
find /var/www/salfanet-radius -type f -exec chmod 644 {} \;
find /var/www/salfanet-radius -type d -exec chmod 755 {} \;
chmod +x /var/www/salfanet-radius/node_modules/.bin/*
chmod +x /var/www/salfanet-radius/node_modules/@prisma/engines/* 2>/dev/null || trueStep 5 — FreeRADIUS 3.x
5.1 Install FreeRADIUS
apt-get install -y freeradius freeradius-mysql freeradius-utils freeradius-rest
systemctl stop freeradius5.2 Detect Config Directory
# Cari lokasi config FreeRADIUS
FR_DIR=""
for dir in /etc/freeradius/3.0 /etc/freeradius; do
[ -d "$dir" ] && FR_DIR="$dir" && break
done
echo "FreeRADIUS config: $FR_DIR"5.3 Konfigurasi SQL Module
cat > $FR_DIR/mods-available/sql << 'EOF'
sql {
driver = "rlm_sql_mysql"
dialect = "mysql"
server = "localhost"
port = 3306
login = "salfanet_user"
password = "salfanetradius123"
radius_db = "salfanet_radius"
read_clients = yes
client_table = "nas"
pool {
start = 5
min = 3
max = 32
spare = 3
uses = 0
retry_delay = 30
lifetime = 0
idle_timeout = 60
}
}
EOF
# Enable SQL module
ln -sf $FR_DIR/mods-available/sql $FR_DIR/mods-enabled/sql5.4 Konfigurasi REST Module
cat > $FR_DIR/mods-available/rest << 'EOF'
rest {
connect_uri = "http://localhost:3000"
connect_timeout = 5.0
authorize {
uri = "${..connect_uri}/api/radius/authorize"
method = "post"
body = "json"
data = '{"username": "%{User-Name}", "nasIp": "%{NAS-IP-Address}"}'
tls = {}
}
post-auth {
uri = "${..connect_uri}/api/radius/post-auth"
method = "post"
body = "json"
data = '{"username": "%{User-Name}", "reply": "%{reply:Packet-Type}", "nasIp": "%{NAS-IP-Address}", "framedIp": "%{reply:Framed-IP-Address}"}'
tls = {}
}
accounting {
uri = "${..connect_uri}/api/radius/accounting"
method = "post"
body = "json"
data = '{"username": "%{User-Name}", "statusType": "%{Acct-Status-Type}", "sessionId": "%{Acct-Session-Id}", "nasIp": "%{NAS-IP-Address}", "framedIp": "%{Framed-IP-Address}", "sessionTime": "%{Acct-Session-Time}", "inputOctets": "%{Acct-Input-Octets}", "outputOctets": "%{Acct-Output-Octets}"}'
tls = {}
}
}
EOF5.5 Copy FreeRADIUS Config dari Project
# Copy konfigurasi dari project (sites, clients, policy)
cp /var/www/salfanet-radius/freeradius-config/clients.conf $FR_DIR/clients.conf 2>/dev/null
cp /var/www/salfanet-radius/freeradius-config/sites-available/default $FR_DIR/sites-available/default 2>/dev/null
cp /var/www/salfanet-radius/freeradius-config/policy.d/filter $FR_DIR/policy.d/filter 2>/dev/null5.6 Setup Sudoers
cat > /etc/sudoers.d/salfanet-freeradius << 'EOF'
salfanet ALL=(ALL) NOPASSWD: /bin/systemctl restart freeradius
salfanet ALL=(ALL) NOPASSWD: /bin/systemctl start freeradius
salfanet ALL=(ALL) NOPASSWD: /bin/systemctl stop freeradius
salfanet ALL=(ALL) NOPASSWD: /bin/systemctl status freeradius
EOF
chmod 440 /etc/sudoers.d/salfanet-freeradius5.7 Test & Start FreeRADIUS
# Test konfigurasi
freeradius -XC 2>&1 | tail -5
# Start & enable
systemctl start freeradius
systemctl enable freeradius
systemctl status freeradiusStep 6 — Nginx Reverse Proxy
6.1 Buat Site Config
cat > /etc/nginx/sites-available/salfanet-radius << 'NGINX'
server {
listen 80;
listen [::]:80;
server_name YOUR_VPS_IP _;
client_max_body_size 100M;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
# Gzip
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# APK download
location /downloads/ {
alias /var/www/salfanet-radius/public/downloads/;
autoindex off;
}
# Next.js static assets (cache 1 tahun)
location /_next/static/ {
alias /var/www/salfanet-radius/.next/static/;
expires 365d;
add_header Cache-Control "public, immutable";
}
# Main proxy ke Next.js
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}
NGINX6.2 Enable Site & Restart
# Hapus default, enable salfanet
rm -f /etc/nginx/sites-enabled/default
ln -sf /etc/nginx/sites-available/salfanet-radius /etc/nginx/sites-enabled/
# Test & restart
nginx -t && systemctl restart nginx && systemctl enable nginxStep 7 — PM2, Swap & Build
7.1 Install PM2
npm install -g pm2
pm2 --version7.2 Buat Swap (WAJIB untuk VPS 2GB RAM)
# Cek apakah sudah ada swap
swapon --show
# Jika belum ada, buat 2GB swap
dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# Permanent (survive reboot)
echo '/swapfile none swap sw 0 0' >> /etc/fstab
# Verifikasi
free -h7.3 Build Next.js
npm run build:vps — BUKAN npm run build. Command biasa menggunakan 4GB heap yang melebihi RAM.cd /var/www/salfanet-radius
# Stop PM2 dulu untuk bebaskan RAM
pm2 stop all 2>/dev/null || true
# Bersihkan cache build lama
rm -rf .next .turbo node_modules/.cache
# Build dengan VPS memory limit (1.5GB heap)
NEXT_TELEMETRY_DISABLED=1 npm run build:vps7.4 Buat PM2 Ecosystem Config
cat > /var/www/salfanet-radius/ecosystem.config.js << 'EOF'
module.exports = {
apps: [
{
name: 'salfanet-radius',
script: 'node_modules/next/dist/bin/next',
args: 'start',
cwd: '/var/www/salfanet-radius',
instances: 1,
exec_mode: 'cluster',
max_memory_restart: '400M',
node_args: ['--max-old-space-size=350', '--optimize-for-size'],
env: {
NODE_ENV: 'production',
PORT: 3000,
TZ: 'Asia/Jakarta'
},
error_file: './logs/error.log',
out_file: './logs/out.log',
merge_logs: true,
autorestart: true,
cron_restart: '0 */6 * * *'
},
{
name: 'salfanet-cron',
script: './cron-service.js',
cwd: '/var/www/salfanet-radius',
instances: 1,
exec_mode: 'fork',
max_memory_restart: '150M',
node_args: ['--max-old-space-size=120', '--optimize-for-size'],
env: {
NODE_ENV: 'production',
API_URL: 'http://localhost:3000',
TZ: 'Asia/Jakarta'
},
error_file: './logs/cron-error.log',
out_file: './logs/cron-out.log',
merge_logs: true,
autorestart: true
}
]
};
EOF
mkdir -p /var/www/salfanet-radius/logs7.5 Start Aplikasi dengan PM2
cd /var/www/salfanet-radius
# Start sebagai app user
sudo su - salfanet -c "cd /var/www/salfanet-radius && pm2 start ecosystem.config.js"
sudo su - salfanet -c "pm2 save"
# Setup auto-start saat boot
sudo /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u salfanet --hp /home/salfanet
# Verifikasi
sudo su - salfanet -c "pm2 status"7.6 Enable FreeRADIUS REST Module
Sekarang app sudah running, enable REST module agar FreeRADIUS bisa memanggil API:
ln -sf $FR_DIR/mods-available/rest $FR_DIR/mods-enabled/rest
systemctl restart freeradiusVerifikasi Semua Berjalan
# Cek PM2
pm2 status
# Cek Next.js merespons
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
# Cek FreeRADIUS
systemctl status freeradius
# Cek Nginx
systemctl status nginx
# Cek app dari browser
echo "Buka: http://$(hostname -I | awk '{print $1}')"http://VPS_IP di browser. Login default: admin / admin123Step 8 — Redis Cache (Opsional, Direkomendasikan)
Redis meningkatkan performa signifikan: cache RADIUS auth, dashboard real-time, rate limiting terdistribusi, tracking online users, dan distributed lock untuk cron job.
8.1 Install Redis
apt-get install -y redis-server8.2 Konfigurasi Redis
Edit konfigurasi Redis untuk produksi:
# Backup config asli
cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
# Set bind hanya localhost (keamanan)
sed -i 's/^bind .*/bind 127.0.0.1 -::1/' /etc/redis/redis.conf
# Aktifkan maxmemory (sesuaikan dengan RAM VPS, contoh 256MB)
sed -i 's/^# maxmemory .*/maxmemory 256mb/' /etc/redis/redis.conf
sed -i 's/^# maxmemory-policy .*/maxmemory-policy allkeys-lru/' /etc/redis/redis.confmaxmemory dengan RAM VPS Anda: 128mb untuk 1GB RAM, 256mb untuk 2GB+, 512mb untuk 4GB+.8.3 Enable & Start Redis
systemctl enable redis-server
systemctl start redis-server
systemctl status redis-server
# Test koneksi
redis-cli ping
# Output harus: PONG8.4 Tambahkan REDIS_URL ke .env
Buka file .env dan tambahkan baris berikut:
echo '' >> /var/www/salfanet-radius/.env
echo '# Redis - Cache & Performance' >> /var/www/salfanet-radius/.env
echo 'REDIS_URL=redis://127.0.0.1:6379' >> /var/www/salfanet-radius/.env
# Verifikasi
grep REDIS_URL /var/www/salfanet-radius/.env8.5 Restart Aplikasi
pm2 restart salfanet-radius
pm2 restart salfanet-cron
pm2 status8.6 Verifikasi Redis Berjalan
# Cek Redis keys diisi oleh aplikasi (setelah beberapa request)
redis-cli keys "*"
# Monitor real-time
redis-cli monitor
# Tekan Ctrl+C untuk keluarFitur yang Di-cache Redis
| Fitur | TTL | Manfaat |
|---|---|---|
| RADIUS Auth Cache | 60 detik | PPPoE login jauh lebih cepat |
| Dashboard Stats | 30 detik | Kurangi query DB berat |
| Online Users Tracking | 2 jam | Hitungan online real-time tanpa query radacct |
| Rate Limiting | Per window | Proteksi API terdistribusi |
| Cron Distributed Lock | Per job | Cegah double-run jika multi-instance |
Step 9 — Mobile APK Build (Opsional)
Build APK customer Android langsung di VPS. Membutuhkan 3GB+ disk space dan 20-40 menit.
9.1 Install Java 17
apt-get install -y openjdk-17-jdk
java -version9.2 Install Android SDK
mkdir -p /opt/android-sdk/cmdline-tools
cd /opt/android-sdk/cmdline-tools
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O tools.zip
unzip -q tools.zip && mv cmdline-tools latest && rm tools.zip
# Environment variables
cat > /etc/profile.d/android-sdk.sh << 'EOF'
export ANDROID_HOME=/opt/android-sdk
export ANDROID_SDK_ROOT=/opt/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools
EOF
source /etc/profile.d/android-sdk.sh
# Accept licenses & install components
yes | sdkmanager --licenses
sdkmanager "platforms;android-35" "build-tools;35.0.0" "platform-tools"9.3 Build APK
cd /var/www/salfanet-radius/mobile-app
# Set API URL
cat > .env << EOF
API_URL=http://YOUR_VPS_IP:3000
API_TIMEOUT=30000
APP_NAME=SALFANET RADIUS
EOF
# Install dependencies & build
npm install
cd android && chmod +x gradlew
./gradlew assembleRelease --max-workers=2 -Dorg.gradle.jvmargs="-Xmx1536m"
# Copy APK ke public downloads
mkdir -p /var/www/salfanet-radius/public/downloads
cp app/build/outputs/apk/release/app-release.apk /var/www/salfanet-radius/public/downloads/salfanet-radius.apk
echo "APK tersedia di: http://YOUR_VPS_IP/downloads/salfanet-radius.apk"🔥 Firewall & Ports
Port Map Lengkap
| Port | Protocol | Service | Akses |
|---|---|---|---|
| 22 | TCP | SSH | External |
| 80 | TCP | HTTP (Nginx) | External |
| 443 | TCP | HTTPS (Nginx) | External |
| 1812 | UDP | RADIUS Auth | MikroTik only |
| 1813 | UDP | RADIUS Accounting | MikroTik only |
| 3799 | UDP | RADIUS CoA | MikroTik only |
| 500 | UDP | IPSec IKE | VPN |
| 4500 | UDP | IPSec NAT-T | VPN |
| 1701 | UDP | L2TP Tunnel | VPN |
| 3000 | TCP | Next.js (internal) | Localhost |
| 3306 | TCP | MySQL (internal) | Localhost |
| 6379 | TCP | Redis (internal) | Localhost |
Setup UFW (VPS/VM)
# Enable UFW dengan rules
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw allow 1812/udp # RADIUS Auth
ufw allow 1813/udp # RADIUS Accounting
ufw allow 3799/udp # RADIUS CoA
ufw allow 500/udp # IPSec IKE
ufw allow 4500/udp # IPSec NAT-T
ufw allow 1701/udp # L2TP
# Enable (ketik 'y' untuk konfirmasi)
ufw --force enable
ufw status verbose🔧 Post-Install
Login Default
| Field | Value |
|---|---|
| URL | http://VPS_IP/admin/login |
| Username | admin |
| Password | admin123 |
Setup MikroTik RADIUS
Di MikroTik, tambahkan RADIUS server:
/radius add service=ppp address=VPS_IP secret=testing123 authentication-port=1812 accounting-port=1813 timeout=3000
/radius incoming set accept=yes port=3799
# Enable RADIUS pada PPP
/ppp profile set default use-radius=yes
/ppp aaa set use-radius=yes accounting=yes interim-update=5mSetup SSL — Certbot (Opsional, Direkomendasikan)
dig +short {{domain}}# Pastikan DNS sudah pointing ke IP VPS
dig +short DOMAIN_OPSIONAL
# Request SSL certificate
certbot --nginx -d DOMAIN_OPSIONAL -m admin@yourdomain.com --agree-tos --non-interactive --redirect
# Verifikasi
nginx -t && systemctl reload nginx
# Test auto-renew
certbot renew --dry-runUpdate .env Setelah SSL Aktif
Setelah SSL terpasang, update NEXTAUTH_URL dan NEXT_PUBLIC_APP_URL ke HTTPS:
# Update .env dengan HTTPS URL
sed -i 's|NEXTAUTH_URL=.*|NEXTAUTH_URL="https://DOMAIN_OPSIONAL"|' /var/www/salfanet-radius/.env
sed -i 's|NEXT_PUBLIC_APP_URL=.*|NEXT_PUBLIC_APP_URL="https://DOMAIN_OPSIONAL"|' /var/www/salfanet-radius/.env
# Restart app
pm2 restart salfanet-radius salfanet-cronDeploy Update Script
/dev/null || true
echo \"[DEPLOY] Installing dependencies...\"
npm install --production=false
echo \"[DEPLOY] Generating Prisma client...\"
npx prisma generate
npx prisma db push --accept-data-loss --skip-generate
echo \"[DEPLOY] Building...\"
pm2 stop all
rm -rf .next node_modules/.cache
NEXT_TELEMETRY_DISABLED=1 npm run build:vps
echo \"[DEPLOY] Fixing permissions...\"
chown -R {{user}}:{{user}} {{appdir}}
echo \"[DEPLOY] Restarting PM2...\"
sudo su - {{user}} -c 'pm2 restart ecosystem.config.js'
echo \"[DEPLOY] Done!\"
DEPLOY
chmod +x {{appdir}}/deploy.sh">cat > /var/www/salfanet-radius/deploy.sh << 'DEPLOY'
#!/bin/bash
cd /var/www/salfanet-radius
echo "[DEPLOY] Pulling latest code..."
git pull origin main 2>/dev/null || true
echo "[DEPLOY] Installing dependencies..."
npm install --production=false
echo "[DEPLOY] Generating Prisma client..."
npx prisma generate
npx prisma db push --accept-data-loss --skip-generate
echo "[DEPLOY] Building..."
pm2 stop all
rm -rf .next node_modules/.cache
NEXT_TELEMETRY_DISABLED=1 npm run build:vps
echo "[DEPLOY] Fixing permissions..."
chown -R salfanet:salfanet /var/www/salfanet-radius
echo "[DEPLOY] Restarting PM2..."
sudo su - salfanet -c "pm2 restart ecosystem.config.js"
echo "[DEPLOY] Done!"
DEPLOY
chmod +x /var/www/salfanet-radius/deploy.shUseful Commands
| Perintah | Fungsi |
|---|---|
pm2 status | Lihat status semua proses |
pm2 logs | Lihat log realtime |
pm2 restart all | Restart semua proses |
pm2 monit | Monitor CPU/RAM realtime |
systemctl status freeradius | Status FreeRADIUS |
systemctl status nginx | Status Nginx |
systemctl status mysql | Status MySQL |
radtest user pass localhost 0 testing123 | Test RADIUS auth |
free -h | Cek penggunaan RAM & swap |
df -h | Cek disk space |
🔧 Troubleshooting
Build Gagal — OOM Killed
Error: "Killed" atau "JavaScript heap out of memory"
Penyebab: RAM tidak cukup untuk build Next.js (butuh minimal 1.5GB free)
Solusi:
- Pastikan swap sudah aktif:
swapon --show - Stop semua service dulu:
pm2 stop all - Free memory:
sync && echo 3 > /proc/sys/vm/drop_caches - Gunakan
npm run build:vps(1.5GB) ataunpm run build:low-mem(1GB) - Jika masih gagal, tambah swap:
dd if=/dev/zero of=/swapfile2 bs=1M count=2048 && mkswap /swapfile2 && swapon /swapfile2
# Panduan lengkap fix OOM:
pm2 stop all
sync && echo 3 > /proc/sys/vm/drop_caches
swapon --show # Pastikan swap aktif
free -h # Pastikan ada minimal 1GB free (RAM + swap)
cd /var/www/salfanet-radius
rm -rf .next node_modules/.cache
NEXT_TELEMETRY_DISABLED=1 npm run build:vpsFreeRADIUS Gagal Start
Error: "Failed to start FreeRADIUS"
Debug:
# Jalankan debug mode
freeradius -X
# Cek log
journalctl -u freeradius -n 50 --no-pager
# Common fixes:
# 1. SQL module gagal connect → cek DB credentials di mods-available/sql
# 2. Port sudah terpakai → fuser -k 1812/udp
# 3. Permission error → chown -R freerad:freerad /etc/freeradius/3.0Nginx 502 Bad Gateway
Error: "502 Bad Gateway" di browser
Penyebab: Next.js (PM2) belum running atau crash.
# Cek PM2
pm2 status
pm2 logs salfanet-radius --lines 50
# Cek port 3000
ss -tlnp | grep 3000
# Restart jika perlu
pm2 restart salfanet-radius
# Cek Nginx config
nginx -t
cat /var/log/nginx/error.log | tail -20Prisma Error
Error: "spawn schema-engine EACCES" atau Prisma client error
# Fix executable permissions
chmod +x node_modules/@prisma/engines/*
chmod +x node_modules/.prisma/client/*
# Regenerate Prisma client
npx prisma generate
# Fix schema push
npx prisma db push --accept-data-loss --skip-generate
# Nuclear option: reinstall
rm -rf node_modules/.prisma
npm installMySQL Connection Refused
Error: "Can't connect to MySQL" atau "Access denied"
# Cek MySQL running
systemctl status mysql
# Test koneksi
mysql -u salfanet_user -p'salfanetradius123' salfanet_radius -e "SELECT 1;"
# Jika access denied, reset user:
mysql -u root -p'root123' << 'EOF'
DROP USER IF EXISTS 'salfanet_user'@'localhost';
CREATE USER 'salfanet_user'@'localhost' IDENTIFIED BY 'salfanetradius123';
GRANT ALL PRIVILEGES ON salfanet_radius.* TO 'salfanet_user'@'localhost';
FLUSH PRIVILEGES;
EOF
# Cek DATABASE_URL di .env
cat /var/www/salfanet-radius/.env | grep DATABASE_URLPort 3000 Already in Use
Error: "EADDRINUSE: address already in use :::3000"
# Cari proses yang pakai port 3000
lsof -i :3000 || ss -tlnp | grep 3000
# Kill proses
fuser -k 3000/tcp
# Restart PM2
pm2 restart salfanet-radiusRADIUS Auth Gagal dari MikroTik
MikroTik: "RADIUS server not responding" atau "Access-Reject"
# 1. Cek FreeRADIUS jalan
systemctl status freeradius
# 2. Test lokal
radtest testuser testpass localhost 0 testing123
# 3. Cek firewall (port 1812/1813 terbuka?)
ufw status | grep -E "1812|1813"
# 4. Cek NAS terdaftar di database
mysql -u salfanet_user -p'salfanetradius123' salfanet_radius \
-e "SELECT * FROM nas;"
# 5. Cek log realtime saat MikroTik auth
journalctl -u freeradius -f
# 6. Pastikan IP MikroTik terdaftar di NAS (via admin panel)
# Admin → Network → Routers → tambahkan NASL2TP VPN Tidak Konek
VPN L2TP tidak bisa establish tunnel
# 1. Cek port IPSec
ufw status | grep -E "500|4500|1701"
# 2. Cek strongSwan
systemctl status strongswan-starter
ipsec statusall
# 3. Cek xl2tpd
systemctl status xl2tpd
# 4. Cek IP forwarding
sysctl net.ipv4.ip_forward # Harus = 1
# 5. Cek kernel modules
lsmod | grep -E "l2tp|ppp"
# 6. Log debug
journalctl -u strongswan-starter -f
journalctl -u xl2tpd -fPermission Denied
Error: "EACCES: permission denied" pada berbagai operasi
# Fix semua permission
chown -R salfanet:salfanet /var/www/salfanet-radius
find /var/www/salfanet-radius -type f -exec chmod 644 {} \;
find /var/www/salfanet-radius -type d -exec chmod 755 {} \;
chmod +x /var/www/salfanet-radius/node_modules/.bin/*
chmod +x /var/www/salfanet-radius/node_modules/@prisma/engines/* 2>/dev/null
chmod 600 /var/www/salfanet-radius/.env
# Fix PM2
mkdir -p /home/salfanet/.pm2/logs /home/salfanet/.pm2/pids
chown -R salfanet:salfanet /home/salfanet/.pm2
# Fix Node.js binaries
chmod 755 /usr/bin/node /usr/bin/npm /usr/bin/pm2 2>/dev/null🗑 Uninstall
Backup Database
mysqldump -u root -p'root123' salfanet_radius > /root/salfanet_radius_backup_$(date +%Y%m%d).sql
echo "Backup tersedia di: /root/salfanet_radius_backup_*.sql"Hapus Semua
# Stop PM2
sudo su - salfanet -c "pm2 delete all" 2>/dev/null
sudo su - salfanet -c "pm2 kill" 2>/dev/null
# Hapus app
rm -rf /var/www/salfanet-radius
userdel -r salfanet 2>/dev/null
# Hapus FreeRADIUS
systemctl stop freeradius
apt-get purge -y freeradius freeradius-mysql freeradius-utils freeradius-rest
rm -rf /etc/freeradius
# Hapus MySQL (HATI-HATI: semua DB hilang!)
systemctl stop mysql
apt-get purge -y mysql-server mysql-client
rm -rf /etc/mysql /var/lib/mysql /var/log/mysql
# Hapus Nginx config
rm -f /etc/nginx/sites-enabled/salfanet-radius
rm -f /etc/nginx/sites-available/salfanet-radius
systemctl restart nginx
# Hapus PM2
npm uninstall -g pm2
# Hapus swap (opsional)
swapoff /swapfile && rm -f /swapfile
sed -i '/swapfile/d' /etc/fstab
echo "Uninstall selesai."