556 lines
28 KiB
TypeScript
556 lines
28 KiB
TypeScript
import { Head, Link } from '@inertiajs/react';
|
||
import {
|
||
AlertTriangle,
|
||
ArrowRight,
|
||
Cloud,
|
||
Database,
|
||
Download,
|
||
KeyRound,
|
||
Network,
|
||
Server,
|
||
ShieldCheck,
|
||
Terminal,
|
||
Users,
|
||
} from 'lucide-react';
|
||
import PublicThemeToggle from '@/components/public-theme-toggle';
|
||
|
||
const Code = ({ children }: { children: string }) => (
|
||
<pre className="mt-3 overflow-x-auto rounded-xl border border-white/10 bg-black/40 p-4 text-xs leading-6 text-sky-100">
|
||
<code>{children}</code>
|
||
</pre>
|
||
);
|
||
|
||
const Step = ({
|
||
number,
|
||
children,
|
||
}: {
|
||
number: number;
|
||
children: React.ReactNode;
|
||
}) => (
|
||
<li className="flex gap-3 text-sm leading-6 text-slate-300">
|
||
<span className="flex size-7 shrink-0 items-center justify-center rounded-full bg-sky-500/15 text-xs font-semibold text-sky-300">
|
||
{number}
|
||
</span>
|
||
<div>{children}</div>
|
||
</li>
|
||
);
|
||
|
||
const vendorRows = [
|
||
[
|
||
'MikroTik RouterOS 6/7',
|
||
'RouterOS API',
|
||
'8728 / 8729',
|
||
'Port API wajib diisi. TLS mengikuti pengaturan tenant.',
|
||
],
|
||
[
|
||
'OLT ZTE C300/C320',
|
||
'SSH',
|
||
'22',
|
||
'Mendukung login, enable, dan privilege perangkat. Telnet tidak dimatikan oleh RADIQ.',
|
||
],
|
||
[
|
||
'OLT HSGQ',
|
||
'SSH + Telnet',
|
||
'22 + 23',
|
||
'Port dapat dibuat custom. Perintah tertentu dijalankan melalui Telnet.',
|
||
],
|
||
[
|
||
'OLT Hisfocus/Hioso',
|
||
'Telnet + WebGUI HTTP',
|
||
'23 + 80',
|
||
'Port custom didukung, misalnya Telnet 8183 dan WebGUI 8182.',
|
||
],
|
||
];
|
||
|
||
export default function DeploymentDocumentation() {
|
||
return (
|
||
<>
|
||
<Head title="Dokumentasi RADIQ NDM" />
|
||
<main className="public-page min-h-screen bg-background text-foreground transition-colors">
|
||
<div className="mx-auto max-w-6xl px-5 py-8 md:px-8">
|
||
<header className="mb-12 flex flex-wrap items-center justify-between gap-4">
|
||
<Link href="/" className="flex items-center gap-3">
|
||
<img
|
||
src="/images/radiq-ndm-logo.png"
|
||
className="size-12 object-contain"
|
||
alt="RADIQ NDM"
|
||
/>
|
||
<div>
|
||
<p className="font-semibold">RADIQ NDM</p>
|
||
<p className="text-xs text-sky-300">
|
||
Dokumentasi aplikasi
|
||
</p>
|
||
</div>
|
||
</Link>
|
||
<nav className="flex items-center gap-2">
|
||
<PublicThemeToggle />
|
||
<Link href="/login" className="px-4 py-2 text-sm">
|
||
Login
|
||
</Link>
|
||
<Link
|
||
href="/register"
|
||
className="rounded-lg bg-sky-500 px-4 py-2 text-sm font-semibold text-slate-950"
|
||
>
|
||
Daftar Tenant
|
||
</Link>
|
||
</nav>
|
||
</header>
|
||
|
||
<section className="grid gap-8 lg:grid-cols-[1fr_280px]">
|
||
<div>
|
||
<p className="text-sm font-semibold text-sky-400">
|
||
PANDUAN RESMI APLIKASI
|
||
</p>
|
||
<h1 className="mt-3 max-w-3xl text-4xl font-bold tracking-tight md:text-5xl">
|
||
Menjalankan RADIQ NDM di Cloud atau server milik
|
||
tenant.
|
||
</h1>
|
||
<p className="mt-5 max-w-3xl leading-7 text-slate-300">
|
||
RADIQ NDM memusatkan pengelolaan akun akses
|
||
perangkat jaringan. Tenant Admin dapat membuat,
|
||
mengubah, menonaktifkan, dan menghapus Users
|
||
Perangkat pada banyak perangkat tanpa membuka
|
||
perangkat satu per satu.
|
||
</p>
|
||
</div>
|
||
<aside className="rounded-2xl border border-white/10 bg-white/5 p-5 text-sm">
|
||
<p className="font-semibold">Isi dokumentasi</p>
|
||
<div className="mt-3 grid gap-2 text-slate-400">
|
||
{[
|
||
'Pilih deployment',
|
||
'Persyaratan server',
|
||
'Instalasi Windows/Linux',
|
||
'Worker wajib',
|
||
'Konfigurasi perangkat',
|
||
'Keamanan dan backup',
|
||
'Migrasi Cloud ke Local',
|
||
].map((item) => (
|
||
<span key={item}>• {item}</span>
|
||
))}
|
||
</div>
|
||
</aside>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
1. Pilih lokasi deployment
|
||
</h2>
|
||
<div className="mt-5 grid gap-5 md:grid-cols-2">
|
||
<article className="rounded-2xl border border-sky-400/25 bg-sky-400/5 p-6">
|
||
<Cloud className="size-7 text-sky-400" />
|
||
<h3 className="mt-4 text-xl font-semibold">
|
||
Cloud RADIQ
|
||
</h3>
|
||
<p className="mt-2 text-sm leading-6 text-slate-300">
|
||
Tenant langsung menggunakan server yang
|
||
dikelola RADIQ. Cocok jika tidak ingin
|
||
memelihara PHP, PostgreSQL, web server,
|
||
worker, backup aplikasi, dan pembaruan
|
||
sistem sendiri.
|
||
</p>
|
||
<p className="mt-4 text-xs text-slate-400">
|
||
Saat registrasi pilih{' '}
|
||
<strong className="text-slate-200">
|
||
Cloud RADIQ
|
||
</strong>
|
||
. Instalasi dibuat dengan status aktif.
|
||
</p>
|
||
</article>
|
||
<article className="rounded-2xl border border-white/10 bg-white/5 p-6">
|
||
<Server className="size-7 text-sky-400" />
|
||
<h3 className="mt-4 text-xl font-semibold">
|
||
Self-hosted / Local
|
||
</h3>
|
||
<p className="mt-2 text-sm leading-6 text-slate-300">
|
||
Aplikasi dan database berjalan di VPS,
|
||
server, komputer, atau laptop tenant. Tenant
|
||
tetap tercatat dan lisensinya tetap dikelola
|
||
Master Admin RADIQ.
|
||
</p>
|
||
<p className="mt-4 text-xs text-slate-400">
|
||
Saat registrasi pilih{' '}
|
||
<strong className="text-slate-200">
|
||
Install Local
|
||
</strong>
|
||
. Instalasi berstatus pending sampai
|
||
pemasangan dan lisensi selesai.
|
||
</p>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
2. Persyaratan self-hosted
|
||
</h2>
|
||
<div className="mt-5 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||
{[
|
||
[
|
||
Terminal,
|
||
'PHP 8.3',
|
||
'Ekstensi Laravel, PDO PostgreSQL, OpenSSL, cURL, Mbstring, XML, dan ZIP.',
|
||
],
|
||
[
|
||
Database,
|
||
'PostgreSQL',
|
||
'Database dan user khusus RADIQ NDM dengan akses ke database tersebut.',
|
||
],
|
||
[
|
||
Server,
|
||
'Web & build tools',
|
||
'Nginx/Apache/IIS, Composer, Node.js dan NPM.',
|
||
],
|
||
[
|
||
Network,
|
||
'Akses jaringan',
|
||
'Server harus dapat menjangkau IP dan port management perangkat.',
|
||
],
|
||
].map(([Icon, title, text]) => {
|
||
const ItemIcon = Icon as typeof Server;
|
||
|
||
return (
|
||
<article
|
||
key={title as string}
|
||
className="rounded-xl border border-white/10 p-5"
|
||
>
|
||
<ItemIcon className="size-5 text-sky-400" />
|
||
<h3 className="mt-3 font-semibold">
|
||
{title as string}
|
||
</h3>
|
||
<p className="mt-2 text-xs leading-5 text-slate-400">
|
||
{text as string}
|
||
</p>
|
||
</article>
|
||
);
|
||
})}
|
||
</div>
|
||
<div className="mt-5 rounded-xl border border-amber-400/20 bg-amber-400/5 p-4 text-sm leading-6 text-amber-100">
|
||
<AlertTriangle className="mr-2 inline size-4" />
|
||
Document root web server wajib menunjuk ke folder{' '}
|
||
<code>public</code>, bukan ke root project.
|
||
</div>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<div className="flex flex-wrap items-center justify-between gap-4">
|
||
<h2 className="text-2xl font-semibold">
|
||
3. Instalasi self-hosted
|
||
</h2>
|
||
<a
|
||
href="/downloads/self-hosted"
|
||
className="inline-flex items-center gap-2 rounded-lg border border-sky-400/30 px-4 py-2 text-sm font-semibold text-sky-300 hover:bg-sky-400/10"
|
||
>
|
||
<Download className="size-4" /> Unduh paket
|
||
</a>
|
||
</div>
|
||
<div className="mt-5 rounded-2xl border border-white/10 p-6">
|
||
<h3 className="font-semibold">
|
||
Konfigurasi minimum file .env
|
||
</h3>
|
||
<Code>{`APP_NAME="RADIQ NDM"
|
||
APP_ENV=production
|
||
APP_DEBUG=false
|
||
APP_URL=https://ndm.domain-tenant.id
|
||
DEPLOYMENT_MODE=self_hosted
|
||
|
||
DB_CONNECTION=pgsql
|
||
DB_HOST=127.0.0.1
|
||
DB_PORT=5432
|
||
DB_DATABASE=radiq_ndm
|
||
DB_USERNAME=radiq_ndm
|
||
DB_PASSWORD=PASSWORD_DATABASE
|
||
|
||
QUEUE_CONNECTION=database
|
||
CACHE_STORE=database
|
||
SESSION_DRIVER=database
|
||
RADIQ_LICENSE_SERVER_URL=https://alamat-control-plane-radiq
|
||
RADIQ_LICENSE_PUBLIC_KEY=PUBLIC_KEY_DARI_RADIQ`}</Code>
|
||
<p className="mt-3 text-xs leading-5 text-slate-400">
|
||
URL server lisensi dan public key diberikan
|
||
Master Admin RADIQ. Private signing key tidak
|
||
boleh berada pada server tenant.
|
||
</p>
|
||
</div>
|
||
<div className="mt-5 grid gap-5 lg:grid-cols-2">
|
||
<article className="rounded-2xl border border-white/10 p-6">
|
||
<h3 className="text-lg font-semibold">
|
||
Windows
|
||
</h3>
|
||
<ol className="mt-5 space-y-4">
|
||
<Step number={1}>
|
||
Ekstrak paket dan buka PowerShell pada
|
||
folder aplikasi.
|
||
</Step>
|
||
<Step number={2}>
|
||
Jalankan installer dengan PHP 8.3:
|
||
<Code>{`powershell -ExecutionPolicy Bypass -File scripts/install-self-hosted.ps1 -Php C:\\php83\\php.exe`}</Code>
|
||
</Step>
|
||
<Step number={3}>
|
||
Installer membuat <code>.env</code>,
|
||
lalu berhenti agar koneksi database
|
||
dapat diisi. Ketik <code>LANJUT</code>{' '}
|
||
setelah selesai.
|
||
</Step>
|
||
<Step number={4}>
|
||
Isi identitas ISP dan Tenant Admin.
|
||
Password minimal 12 karakter dengan
|
||
huruf besar/kecil, angka, dan simbol.
|
||
</Step>
|
||
</ol>
|
||
</article>
|
||
<article className="rounded-2xl border border-white/10 p-6">
|
||
<h3 className="text-lg font-semibold">Linux</h3>
|
||
<ol className="mt-5 space-y-4">
|
||
<Step number={1}>
|
||
Ekstrak paket dan berikan akses folder
|
||
serta <code>storage</code> kepada user
|
||
service.
|
||
</Step>
|
||
<Step number={2}>
|
||
Jalankan installer:
|
||
<Code>{`PHP_BIN=/usr/bin/php8.3 bash scripts/install-self-hosted.sh`}</Code>
|
||
</Step>
|
||
<Step number={3}>
|
||
Lengkapi <code>.env</code>, lalu ketik{' '}
|
||
<code>LANJUT</code>. Installer
|
||
menjalankan Composer, migration, seeder,
|
||
pembuatan tenant, build frontend, dan
|
||
optimasi.
|
||
</Step>
|
||
<Step number={4}>
|
||
Konfigurasikan Nginx/Apache dengan HTTPS
|
||
dan document root ke folder{' '}
|
||
<code>public</code>.
|
||
</Step>
|
||
</ol>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
4. Proses background yang wajib hidup
|
||
</h2>
|
||
<p className="mt-3 text-sm leading-6 text-slate-300">
|
||
CRUD Users Perangkat dikirim ke queue. Jika
|
||
perangkat offline, assignment menjadi pending dan
|
||
scheduler akan mencoba kembali. Jalankan kedua
|
||
proses sebagai Windows Service, Task Scheduler,
|
||
systemd, atau Supervisor.
|
||
</p>
|
||
<Code>{`# Worker sinkronisasi perangkat
|
||
php artisan queue:work --queue=default --tries=1 --timeout=60
|
||
|
||
# Scheduler pekerjaan pending dan tugas berkala
|
||
php artisan schedule:work`}</Code>
|
||
<p className="mt-3 text-xs text-slate-400">
|
||
Pada Windows, ganti <code>php</code> dengan{' '}
|
||
<code>C:\php83\php.exe</code>. Setelah deployment
|
||
jalankan <code>php artisan optimize:clear</code> dan{' '}
|
||
<code>php artisan queue:restart</code>.
|
||
</p>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
5. Konfigurasi koneksi perangkat
|
||
</h2>
|
||
<div className="mt-5 overflow-x-auto rounded-2xl border border-white/10">
|
||
<table className="w-full min-w-[760px] text-left text-sm">
|
||
<thead className="bg-white/5 text-slate-200">
|
||
<tr>
|
||
{[
|
||
'Vendor',
|
||
'Protokol',
|
||
'Port default',
|
||
'Catatan',
|
||
].map((title) => (
|
||
<th
|
||
key={title}
|
||
className="px-4 py-3 font-semibold"
|
||
>
|
||
{title}
|
||
</th>
|
||
))}
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{vendorRows.map((row) => (
|
||
<tr
|
||
key={row[0]}
|
||
className="border-t border-white/10"
|
||
>
|
||
{row.map((cell) => (
|
||
<td
|
||
key={cell}
|
||
className="px-4 py-3 align-top leading-6 text-slate-400"
|
||
>
|
||
{cell}
|
||
</td>
|
||
))}
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div className="mt-5 rounded-xl border border-white/10 p-5 text-sm leading-6 text-slate-300">
|
||
<strong>Aturan port:</strong> form perangkat berubah
|
||
mengikuti vendor. Isi hanya port protokol yang
|
||
tersedia. Port kosong berarti protokol tersebut
|
||
tidak digunakan. Firewall server RADIQ harus dapat
|
||
mencapai management network.
|
||
</div>
|
||
</section>
|
||
|
||
<section className="mt-14 grid gap-5 lg:grid-cols-2">
|
||
<article className="rounded-2xl border border-white/10 p-6">
|
||
<Users className="size-6 text-sky-400" />
|
||
<h2 className="mt-4 text-xl font-semibold">
|
||
6. Cara kerja Users Perangkat
|
||
</h2>
|
||
<ol className="mt-5 space-y-3">
|
||
<Step number={1}>
|
||
Tenant Admin mengatur Base User dan Base
|
||
Password.
|
||
</Step>
|
||
<Step number={2}>
|
||
Tambahkan perangkat dengan credential awal,
|
||
lalu Cek & Aktifkan.
|
||
</Step>
|
||
<Step number={3}>
|
||
Buat Users Perangkat, pilih perangkat tujuan
|
||
dan group akses.
|
||
</Step>
|
||
<Step number={4}>
|
||
Perangkat online langsung disinkronkan;
|
||
perangkat offline berstatus pending.
|
||
</Step>
|
||
</ol>
|
||
<p className="mt-4 text-xs leading-5 text-slate-400">
|
||
Role aplikasi tetap: Master Admin, Tenant Admin,
|
||
dan Tenant User. Tenant Admin hanya mengelola
|
||
Tenant User miliknya.
|
||
</p>
|
||
</article>
|
||
<article className="rounded-2xl border border-white/10 p-6">
|
||
<KeyRound className="size-6 text-sky-400" />
|
||
<h2 className="mt-4 text-xl font-semibold">
|
||
7. Credential dan encryption key
|
||
</h2>
|
||
<div className="mt-4 space-y-3 text-sm leading-6 text-slate-300">
|
||
<p>
|
||
Password perangkat dienkripsi dengan tenant
|
||
encryption key. Tenant key dibungkus kembali
|
||
oleh application key server.
|
||
</p>
|
||
<p>
|
||
Tenant Admin dapat membuat key otomatis atau
|
||
manual. Rotasi key mengenkripsi ulang
|
||
credential yang tersimpan.
|
||
</p>
|
||
<p>
|
||
Melihat Base Password wajib memasukkan
|
||
password login Tenant Admin dan dibatasi
|
||
rate limit.
|
||
</p>
|
||
</div>
|
||
<div className="mt-4 rounded-lg bg-red-400/5 p-3 text-xs leading-5 text-red-100">
|
||
Kehilangan APP_KEY atau encryption key tanpa
|
||
backup yang benar dapat membuat credential tidak
|
||
dapat dipulihkan.
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
8. Backup dan pemeliharaan
|
||
</h2>
|
||
<div className="mt-5 grid gap-4 md:grid-cols-3">
|
||
{[
|
||
[
|
||
'Database PostgreSQL',
|
||
'Backup seluruh database termasuk tenant, assignment, queue, dan credential terenkripsi.',
|
||
],
|
||
[
|
||
'File rahasia',
|
||
'Backup .env dan APP_KEY secara terenkripsi, terpisah dari database dan dengan akses terbatas.',
|
||
],
|
||
[
|
||
'Uji pemulihan',
|
||
'Lakukan restore drill pada server terisolasi. Backup yang belum diuji belum dapat dianggap aman.',
|
||
],
|
||
].map(([title, text]) => (
|
||
<article
|
||
key={title}
|
||
className="rounded-xl border border-white/10 p-5"
|
||
>
|
||
<ShieldCheck className="size-5 text-emerald-400" />
|
||
<h3 className="mt-3 font-semibold">
|
||
{title}
|
||
</h3>
|
||
<p className="mt-2 text-xs leading-5 text-slate-400">
|
||
{text}
|
||
</p>
|
||
</article>
|
||
))}
|
||
</div>
|
||
<Code>{`# Contoh backup PostgreSQL
|
||
pg_dump -Fc -U radiq_ndm -d radiq_ndm -f radiq_ndm.backup
|
||
|
||
# Maintenance setelah update aplikasi
|
||
php artisan migrate --force
|
||
php artisan optimize
|
||
php artisan queue:restart`}</Code>
|
||
</section>
|
||
|
||
<section className="mt-14">
|
||
<h2 className="text-2xl font-semibold">
|
||
9. Migrasi Cloud ke Local
|
||
</h2>
|
||
<div className="mt-4 rounded-xl border border-amber-400/20 bg-amber-400/5 p-4 text-sm leading-6 text-amber-100">
|
||
<AlertTriangle className="mr-2 inline size-4" />
|
||
Versi saat ini belum menyediakan ekspor–impor tenant
|
||
otomatis. Migrasi harus dijadwalkan bersama Master
|
||
Admin agar credential terenkripsi dan encryption key
|
||
dipindahkan dengan aman.
|
||
</div>
|
||
<ol className="mt-5 space-y-4">
|
||
{[
|
||
'Tenant Admin mengajukan migrasi dan jadwal maintenance.',
|
||
'Master Admin menyiapkan instalasi self-hosted dan lisensi tenant.',
|
||
'Pasang RADIQ NDM local dengan APP_KEY baru, tetapi jangan aktifkan worker perangkat.',
|
||
'Pindahkan data tenant dan re-enkripsi secret melalui prosedur migrasi; jangan mengekspor password sebagai plaintext.',
|
||
'Verifikasi user, perangkat, Users Perangkat, assignment, port vendor, dan status lisensi.',
|
||
'Hentikan worker Cloud sebelum menyalakan worker Local agar perintah tidak berjalan dua kali.',
|
||
'Uji satu perangkat per vendor, kemudian selesaikan cutover.',
|
||
].map((item, index) => (
|
||
<Step key={item} number={index + 1}>
|
||
{item}
|
||
</Step>
|
||
))}
|
||
</ol>
|
||
</section>
|
||
|
||
<section className="mt-14 rounded-2xl bg-sky-500 p-7 text-slate-950">
|
||
<h2 className="text-2xl font-bold">
|
||
Mulai dengan deployment yang sesuai
|
||
</h2>
|
||
<p className="mt-2 max-w-2xl">
|
||
Cloud cocok untuk penggunaan cepat. Self-hosted
|
||
cocok ketika management perangkat hanya dapat
|
||
diakses dari jaringan internal tenant.
|
||
</p>
|
||
<Link
|
||
href="/register"
|
||
className="mt-5 inline-flex items-center gap-2 rounded-lg bg-slate-950 px-5 py-3 font-semibold text-white"
|
||
>
|
||
Daftar Tenant <ArrowRight className="size-4" />
|
||
</Link>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
</>
|
||
);
|
||
}
|