PANDUAN MASTER INFRASTRUKTUR SERVER
CloudPanel + Nginx Proxy Manager + ZeroTier VPN
SOP Lengkap untuk Operator Server · Penambahan Domain · Akses SSH · Manajemen VPN · Deploy Node.js
A. Arsitektur & Gambaran Sistem
Setiap request dan akses ke server melewati jalur yang berbeda tergantung tujuannya:
JALUR WEB (HTTP/HTTPS) — Akses website dari internet
Internet → Cloudflare CDN → x.x.x.x → MikroTik → VM NPM → VM CloudPanel → Website
JALUR ADMIN (SSH/Database) — Akses pengelolaan server
Laptop/PC → ZeroTier VPN → IP Lokal VM CloudPanel → SSH masuk
💡 Dua jalur ini TERPISAH. Akses website (HTTP/HTTPS) lewat NPM dan tidak butuh VPN. Akses manajemen (SSH, database, admin panel CloudPanel) WAJIB lewat VPN.
Inventaris IP Server
| IP Publik Kantor | x.x.x.x |
| VM Nginx Proxy Manager | 192.168.x.___ ← isi sesuai kondisi |
| VM CloudPanel | 192.168.x.___ ← isi sesuai kondisi |
| VM Mailcow | 192.168.x.___ ← isi sesuai kondisi |
| CloudPanel Admin URL | https://<IP-lokal-CloudPanel>:8443 |
| NPM Admin URL | http://<IP-lokal-NPM>:81 |
B. ZeroTier VPN — Setup & Manajemen
ZeroTier membuat jaringan virtual privat antara semua device yang terdaftar. Setelah terhubung, laptop dan VM server seolah berada dalam satu LAN, meskipun berbeda lokasi.
B.1 Buat Akun & Network ZeroTier
1
Daftar akun di ZeroTier Central
https://my.zerotier.com — gratis, support hingga 25 device
2
Buat Network baru
Klik Create A Network
3
Catat Network ID
16 karakter hex, contoh: a09acf023371e45b
4
Konfigurasi Network
Atur Access Control, IPv4 Auto-Assign
| Network Name | infra-kantor (atau nama bebas) |
| Access Control | Private (setiap device harus di-approve manual) |
| IPv4 Auto-Assign | Easy (pilih range IP, contoh: 172.25.x.x/16) |
B.2 Install ZeroTier di Semua VM Server
Jalankan di setiap VM (NPM, CloudPanel, Mailcow, dll):
# Install ZeroTier
curl -s https://install.zerotier.com | sudo bash
# Join ke network (ganti dengan Network ID kamu)
sudo zerotier-cli join a09acf023371e45b
# Cek status
sudo zerotier-cli status
sudo zerotier-cli listnetworks
⚠️ Setelah join, device belum bisa komunikasi. Perlu di-approve dulu di dashboard ZeroTier Central (my.zerotier.com).
B.3 Approve Device di Dashboard ZeroTier
- Login ke my.zerotier.com
- Klik network yang sudah dibuat
- Scroll ke bagian Members
- Device yang baru join akan muncul dengan status pending
- Centang kotak Auth di sebelah kiri device
- Beri nama device (contoh: vm-cloudpanel, vm-npm)
- IP ZeroTier otomatis di-assign oleh network
💡 Catat IP ZeroTier setiap VM setelah di-approve. IP ini yang akan dipakai untuk SSH dari laptop.
B.4 Install ZeroTier di Laptop / PC Operator
| OS | Download / Cara Install |
| Windows | https://www.zerotier.com/download/ → Windows MSI |
| macOS | https://www.zerotier.com/download/ → macOS PKG |
| Linux | curl -s https://install.zerotier.com | sudo bash |
| Android / iOS | ZeroTier One di Play Store / App Store |
# Windows / macOS: klik kanan icon ZeroTier di system tray → Join Network → masukkan Network ID
# Linux:
sudo zerotier-cli join a09acf023371e45b
B.5 Verifikasi Koneksi ZeroTier
# Cek IP ZeroTier yang di-assign ke device ini
sudo zerotier-cli listnetworks
# Output contoh:
# 200 listnetworks a09acf023371e45b infra-kantor 172.25.x.x/16 OK PRIVATE
# Test ping ke VM CloudPanel via ZeroTier IP
ping 172.25.x.x
# Test SSH ke VM CloudPanel via ZeroTier
ssh servert@172.25.x.x
B.6 Manajemen User ZeroTier
Tambah operator baru:
- Operator install ZeroTier di laptop mereka
- Join ke Network ID yang sama
- Admin approve di dashboard ZeroTier Central
- Berikan IP ZeroTier VM CloudPanel ke operator tersebut
Cabut akses operator:
- Login ke my.zerotier.com
- Buka network → Members
- Unchecklist Auth pada device operator yang bersangkutan, atau klik Delete
- Akses langsung terputus tanpa perlu ubah apapun di server
🔒 Keunggulan ZeroTier — mencabut akses operator cukup dari dashboard, tidak perlu SSH ke server untuk hapus SSH key atau ubah password.
C. SSH via CloudPanel
CloudPanel menyediakan SSH user per site. Setiap site punya user Linux tersendiri dengan akses terbatas hanya ke folder site miliknya.
C.1 Cara Akses SSH yang Benar
WAJIB: Konek ZeroTier VPN dulu sebelum SSH
Langkah 1 — Pastikan ZeroTier aktif di laptop:
- Windows/macOS: cek icon ZeroTier di system tray, status harus Connected
- Linux:
sudo zerotier-cli listnetworks → status harus OK
Langkah 2 — Buat SSH User di CloudPanel:
- Login ke CloudPanel via browser (gunakan IP ZeroTier VM CloudPanel)
- Buka site yang ingin diakses
- Klik tab SSH/FTP
- Di bagian SSH Users, klik Add User
- Isi username dan password yang kuat
- Klik Save
💡 SSH User di CloudPanel punya akses terbatas hanya ke folder htdocs site tersebut — tidak bisa keluar ke folder lain.
Langkah 3 — SSH ke VM CloudPanel:
# Format: ssh <ssh-user>@<IP-ZeroTier-VM-CloudPanel>
ssh sar-dev@172.25.x.x
# Setelah masuk, langsung berada di home folder site
cd htdocs/subdomain.domain.com
ls -la
C.2 Akses sebagai Root (Untuk Maintenance)
# SSH sebagai user server biasa
ssh servert@172.25.x.x
# Masuk ke root
sudo su -
# Sekarang bisa akses semua folder site
ls -la /home/site-user/htdocs/
cd /home/site-user/htdocs/subdomain.domain.com
# Jalankan command sebagai user site (penting untuk permission)
sudo -u site-user wp plugin list
sudo -u site-user php artisan migrate
💡 Selalu jalankan WP-CLI dan Artisan sebagai user site (sudo -u <site-user>), bukan sebagai root. Ini mencegah masalah permission pada file yang dibuat.
C.3 Ringkasan Akses SSH
| Kebutuhan | User yang Dipakai | Command |
| Akses folder site tertentu | SSH User CloudPanel | ssh sar-dev@172.25.x.x |
| Akses semua site / maintenance | User server + sudo | ssh servert@172.25.x.x → sudo su - |
| Jalankan WP-CLI / Artisan | User site via sudo | sudo -u site-user php artisan ... |
| Upload file ke site | SSH User atau FTP User | sftp / SCP / FTP client |
D. Penambahan Domain Baru
Urutan WAJIB: ① Cloudflare → ② CloudPanel → ③ NPM
⚠️ Jangan request SSL di NPM sebelum DNS Cloudflare selesai propagasi (tunggu 2–5 menit setelah set DNS).
D.1 Cloudflare — Tambah DNS Record
1
Login ke Cloudflare
dash.cloudflare.com → pilih domain
2
DNS > Records > Add Record
Tambah record untuk domain utama:
| Type | A |
| Name | @ (untuk domain utama, misal: yourdomain.com) |
| IPv4 address | x.x.x.x |
| Proxy status | Proxied (awan oranye = ON) |
| TTL | Auto |
3
Tambah record untuk www
Klik Add Record lagi dengan Name: www, value sama
D.2 CloudPanel — Buat Site Baru
# Akses CloudPanel via ZeroTier:
https://172.25.x.x:8443
1
Klik Add Site di halaman Sites
2
Pilih tipe site
WordPress untuk CMS, Generic untuk Laravel / PHP custom, Node.js untuk AdonisJS
Untuk WordPress:
| Domain Name | yourdomain.com |
| PHP Version | 8.1 |
| Database | auto-generate (catat nama DB, user, password) |
Untuk Laravel / Generic:
| Domain Name | yourdomain.com |
| PHP Version | 8.1 atau 8.2 |
3
Klik Create
CloudPanel membuat user, folder, dan database
4
Jika Laravel: ubah document root ke /public
Sites → domain → Vhost → edit root path
# Di Vhost CloudPanel, cari dan ubah:
root /home/<site-user>/htdocs/yourdomain.com/public;
D.3 NPM — Tambah Proxy Host
# Akses NPM via ZeroTier:
http://172.25.x.xX:81
1
Hosts > Proxy Hosts > Add Proxy Host
| Domain Names | yourdomain.com www.yourdomain.com |
| Scheme | http |
| Forward Hostname / IP | <IP lokal VM CloudPanel> contoh: 192.168.x.xxx |
| Forward Port | 80 |
| Block Common Exploits | ON |
| Websockets Support | ON |
| SSL Certificate | Request a new SSL Certificate |
| Force SSL | ON |
| HTTP/2 Support | ON |
| HSTS Enabled | ON |
4
Klik Save
NPM otomatis request SSL dari Let's Encrypt
D.4 Verifikasi
- https://yourdomain.com bisa dibuka — tidak ada warning SSL
- https://www.yourdomain.com redirect ke https://yourdomain.com
- Di NPM, status proxy host = hijau (online)
- Konten yang tampil benar (bukan site lain)
E. Penambahan Subdomain
Urutan WAJIB: ① Cloudflare → ② CloudPanel → ③ NPM
E.1 Cloudflare — Tambah DNS Record Subdomain
| Type | A |
| Name | app (hasilnya: app.yourdomain.com) |
| IPv4 address | x.x.x.x |
| Proxy status | Proxied |
💡 Name diisi nama subdomain saja tanpa domain induk. Cloudflare otomatis menambahkan .yourdomain.com di belakangnya.
E.2 CloudPanel — Buat Site untuk Subdomain
Proses sama persis dengan domain baru. Isi domain name dengan subdomain lengkap:
| Domain Name | app.yourdomain.com |
| PHP Version | 8.1 atau 8.2 (sesuai kebutuhan) |
| Tipe | WordPress atau Generic |
💡 Setiap subdomain dibuat sebagai site terpisah agar punya PHP version, database, dan user sendiri. Lebih mudah dikelola dan di-debug.
E.3 NPM — Tambah Proxy Host Subdomain
| Domain Names | app.yourdomain.com |
| Scheme | http |
| Forward Hostname / IP | <IP lokal VM CloudPanel> |
| Forward Port | 80 |
Di tab SSL: Request new SSL Certificate, Force SSL ON, HTTP/2 ON.
E.4 Verifikasi
- https://app.yourdomain.com bisa dibuka — tidak ada warning SSL
- Konten yang tampil benar (bukan site induk)
- Di NPM, status proxy host = hijau (online)
F. Kasus Khusus
F.1 Deploy Laravel
1
Ubah document root ke /public
Di CloudPanel → Sites → domain → Vhost
# Cari dan ubah baris root di Vhost:
root /home/<user>/htdocs/domain.com/public;
2
SSH ke VM CloudPanel (via ZeroTier) & deploy
ssh servert@172.25.x.x
sudo su -
cd /home/<site-user>/htdocs/domain.com
git clone https://github.com/username/repo.git .
composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate
nano .env # sesuaikan DB credentials dari CloudPanel
php artisan migrate --force
php artisan config:cache
php artisan route:cache
# Fix permission
chown -R <site-user>:www-data storage bootstrap/cache
chmod -R 755 storage bootstrap/cache
F.2 Install WordPress Manual via WP-CLI
ssh servert@172.25.x.x
sudo su -
cd /home/<site-user>/htdocs/domain.com
sudo -u <site-user> wp core download --locale=id_ID
sudo -u <site-user> wp config create \
--dbname=<db-name> \
--dbuser=<db-user> \
--dbpass=<db-pass> \
--dbhost=localhost
sudo -u <site-user> wp core install \
--url=https://domain.com \
--title='Nama Website' \
--admin_user=admin \
--admin_password=PasswordKuat123! \
--admin_email=email@domain.com
F.3 Wildcard Subdomain (*.domain.com)
Di Cloudflare:
| Type | A |
| Name | * |
| IPv4 address | x.x.x.x |
| Proxy status | Proxied |
Di NPM — SSL Wildcard butuh DNS Challenge:
- Buat proxy host dengan domain:
*.domain.com
- Di tab SSL, pilih Request a new SSL Certificate
- Centang Use a DNS Challenge
- Pilih Cloudflare sebagai DNS provider
- Masukkan Cloudflare API Token
- Save — NPM akan request wildcard certificate
⚠️ SSL wildcard membutuhkan Cloudflare API Token dengan permission DNS:Edit.
G. Quick Reference & Troubleshooting
G.1 Checklist Standar Setiap Penambahan Domain/Subdomain
| ✓ | Di mana | Yang dilakukan |
| ☐ | Cloudflare | Tambah A Record → Name: domain/subdomain, Value: x.x.x.x, Proxy: ON |
| ☐ | CloudPanel | Add Site → isi domain, pilih tipe dan PHP version, catat kredensial DB |
| ☐ | CloudPanel | Jika Laravel: ubah document root ke /public di Vhost |
| ☐ | CloudPanel | Deploy code (git clone / upload) dan setup .env / wp-config.php |
| ☐ | NPM | Add Proxy Host → Domain, Forward ke IP CloudPanel:80, Exploits ON, WS ON |
| ☐ | NPM | Tab SSL → Request new cert, Force SSL ON, HTTP/2 ON, Save |
| ☐ | Browser | Buka https://domain.com → HTTPS aktif, konten benar, tidak ada warning |
G.2 Referensi URL & IP
| IP Publik Kantor | x.x.x.x |
| ZeroTier Network ID | ← isi sesuai network kamu |
| ZeroTier IP VM NPM | 172.25.x.___ ← isi setelah setup |
| ZeroTier IP VM CloudPanel | 172.25.x.___ ← isi setelah setup |
| CloudPanel Admin | https://<ZeroTier-IP-CloudPanel>:8443 |
| NPM Admin Panel | http://<ZeroTier-IP-NPM>:81 |
| ZeroTier Dashboard | https://my.zerotier.com |
G.3 Troubleshooting
| Gejala | Kemungkinan Penyebab & Solusi |
| Domain tidak bisa dibuka | DNS belum propagasi. Cek di whatsmydns.net. Tunggu 2–5 menit |
| Masuk ke website yang salah | Proxy host di NPM belum dibuat atau nama domain tidak cocok persis |
| SSL error / Not Secure | SSL belum di-request di NPM, atau DNS belum propagasi saat request SSL |
| 502 Bad Gateway di NPM | VM CloudPanel tidak bisa direach. Cek IP Forward di proxy host sudah benar |
| CloudPanel 404 setelah SSL aktif | Site belum dibuat di CloudPanel, atau nama domain tidak persis sama |
| Laravel Nginx 404 | Document root belum diubah ke /public di Vhost CloudPanel |
| Permission denied saat SSH | Pastikan pakai SSH User dari CloudPanel, bukan system user langsung |
| ZeroTier tidak konek | Cek apakah device sudah di-approve di dashboard my.zerotier.com |
| NPM tidak bisa request SSL | Port 80 belum terbuka dari internet ke VM NPM. Cek port forward MikroTik |
| WordPress tidak bisa upload | Jalankan: sudo chown -R <user>:www-data /home/<user>/htdocs/domain/wp-content |
H. Deploy Node.js / AdonisJS dengan PM2
PM2 adalah process manager untuk Node.js yang menjaga aplikasi tetap berjalan meskipun SSH ditutup, dan otomatis restart jika server reboot atau aplikasi crash.
✅ SSH ditutup
App tetap running
✅ Server reboot
App otomatis start ulang
✅ App crash
PM2 otomatis restart
H.1 Persiapan Site di CloudPanel
1
Buat Site dengan tipe Node.js
CloudPanel → Sites → Add Site → pilih Node.js
| Domain Name | domain.com |
| Node.js Version | Node 22 LTS |
| App Port | 3333 (default AdonisJS — sesuaikan jika berbeda) |
💡 App Port di CloudPanel harus sama dengan PORT yang diset di file .env AdonisJS. CloudPanel otomatis generate Nginx sebagai reverse proxy ke port ini — tidak perlu edit Vhost manual.
H.2 Install PM2
⚠️ PENTING: PM2 diinstall sebagai SSH User site, BUKAN sebagai root atau servert. Node.js hanya tersedia untuk user site via NVM yang dikelola CloudPanel.
1
Login SSH sebagai SSH User siteGunakan SSH User yang dibuat di tab SSH/FTP CloudPanel
# Login sebagai user site (bukan servert/root)
ssh site-user@192.168.x.xxx
# atau via ZeroTier:
ssh site-user@172.25.x.x
cd htdocs/subdomain.domain.com
3
Install PM2 via npm — TANPA sudo
# Install PM2 — jalankan sebagai user site, TANPA sudo
npm install pm2@latest -g
# Verifikasi
pm2 --version
H.3 Deploy & Jalankan AdonisJS
1
Upload / clone project & build
cd htdocs/subdomain.domain.com
git clone https://github.com/username/repo.git .
npm install
cp .env.example .env
nano .env # isi APP_KEY, DB credentials, PORT=3333
node ace build --production
# Ganti 'nama-app' dengan nama project kamu
pm2 start npm --name nama-app -- start
# Cek status — pastikan status: online
pm2 status
pm2 save
H.4 Auto-Start saat Server Reboot
CloudPanel menggunakan cron job (bukan pm2 startup systemd) untuk auto-start setelah reboot:
1
Ambil nilai PATH saat ini
echo $PATH
# Contoh output:
# /home/site-user/.nvm/versions/node/v22.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
⚠️ Salin seluruh output echo $PATH. Nilai ini berbeda di setiap server dan wajib dipakai di langkah berikutnya.
crontab -e
# Ganti PATH= dengan output dari echo $PATH
PATH=/home/site-user/.nvm/versions/node/v22.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
@reboot pm2 resurrect > /dev/null
# Reboot dari Proxmox atau sebagai servert
sudo reboot
# Setelah reboot, SSH lagi dan cek status
ssh site-user@172.25.x.x
pm2 status
# Status harus: online
H.5 Perintah PM2 Sehari-hari
| Perintah | Fungsi |
pm2 status | Lihat semua app yang dikelola PM2 dan statusnya |
pm2 logs nama-app | Lihat log output app secara realtime |
pm2 logs nama-app --lines 100 | Lihat 100 baris log terakhir |
pm2 restart nama-app | Restart app (misal setelah update code) |
pm2 stop nama-app | Stop app sementara |
pm2 start nama-app | Start app yang sedang stop |
pm2 delete nama-app | Hapus app dari PM2 sepenuhnya |
pm2 monit | Dashboard monitoring realtime (CPU, memory, logs) |
pm2 save | Simpan daftar app — jalankan setelah setiap perubahan |
H.6 Alur Update Code (Deployment Ulang)
# SSH sebagai user site
ssh site-user@172.25.x.x
cd htdocs/subdomain.domain.com
# Pull update terbaru
git pull origin main
# Install dependency baru jika ada
npm install
# Build ulang
node ace build --production
# Restart app via PM2
pm2 restart nama-app
# Verifikasi
pm2 status
pm2 logs nama-app --lines 20
H.7 Troubleshooting PM2
| Masalah | Solusi |
npm: command not found saat install PM2 | Pastikan login sebagai SSH User site (bukan servert/root). Node.js hanya tersedia untuk user site. |
| pm2 status: errored | Lihat log: pm2 logs nama-app. Biasanya error di .env atau koneksi database. |
| App tidak auto-start setelah reboot | Cek crontab: crontab -l. Pastikan PATH dan @reboot pm2 resurrect sudah ada. |
| Port sudah dipakai (EADDRINUSE) | App masih jalan. Jalankan: pm2 delete nama-app lalu start ulang. |
| 502 Bad Gateway setelah deploy | App belum running atau crash. Cek: pm2 status dan pm2 logs. |
3 Aturan Utama
① Akses admin/SSH → WAJIB konek ZeroTier VPN dulu
② Tambah domain → urutan WAJIB: Cloudflare → CloudPanel → NPM
③ Jangan request SSL di NPM sebelum DNS Cloudflare propagasi
Posting Komentar
oke