Aplikasi 2 halaman:
- Form publik — permintaan layanan → SQLite. Anti-bot honeypot + rate limit. Layanan tampil dari DB (hanya yang aktif). Semua field wajib diisi. Panel kanan menampilkan peta jalur kabel (Singapura–Jakarta–Surabaya) dan detail produk terpilih; sebelum memilih layanan tampil placeholder "Pilih Produk untuk Melihat Detailnya".
- Admin dashboard — login, tabel + paginasi, filter tanggal/layanan/status, ubah status (BARU→DIPROSES→SELESAI/DITOLAK), hapus, detail per baris, export Excel (server-side), audit trail.
- Kelola layanan —
/admin/services: tambah/edit/hapus layanan (nama, subtitle, deskripsi, urutan, aktif/nonaktif, best seller, kapasitas terkunci) dengan 2 gambar: preview (kartu layanan) + full (panel kanan). Upload jpg/png/webp/gif, maks 5MB, tersimpan dipublic/images/services/. - Pengaturan halaman & brand —
/admin/settings: nama brand, keterangan, dan logo (opsional; berlaku di semua permukaan — header publik, halaman login, sidebar admin, judul tab; kosong = ikon default), serta judul, deskripsi, poin, gambar, dan toggle "Panel Tentang Aktif" (matikan panel "Tentang" halaman publik tanpa menghapus isinya).
Next.js (App Router) · TypeScript · Tailwind + shadcn UI · Prisma + SQLite (WAL) · Auth.js (credentials) · xlsx
- Node.js 20+ (cek
node -v), npm 10+ - Git
Buat LXC/VM Ubuntu 22.04/24.04, RAM 1GB+, disk 10GB. Pastikan dapat IP privat (mis. 10.202.10.15). Untuk akses publik, buat DNAT di Proxmox/firewall:
IP_PUBLIK:80 → 10.202.10.15:80
IP_PUBLIK:443 → 10.202.10.15:80 (jika pakai TLS)
Atau pakai Nginx reverse-proxy di depan. Tidak perlu config NEXTAUTH_URL — trustHost:true sudah aktif otomatis ikut Host publik.
apt update && apt install -y nodejs npm git
# jika Node <20, install via NodeSource:
# curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt install -y nodejs
git clone <repo-url> equotation
cd equotation
npm install
# postinstall otomatis: prisma generateJika
npm installdiblokir script Prisma:npm install --foreground-scriptsatau manualnpx prisma generate.
npm run setupsetup = node scripts/setup-env.mjs + prisma migrate deploy + prisma db seed:
- Buat
.envjika belum ada (generateNEXTAUTH_SECRET+AUTH_SECRETrandom 32 byte). Jika.envsudah ada tapi secret-nya masih placeholder/dev-secret..., akan di-random +AUTH_SECRETditambahkan otomatis. - Buat semua tabel SQLite
prisma/prod.db. - Seed admin
admin / admin123+ 9 layanan + setting brand (idempoten — tidak timpa editan admin saat re-run).
Cek .env yang terbuat:
DATABASE_URL="file:./prod.db"
NEXTAUTH_SECRET="<random base64 32>"
AUTH_SECRET="<random base64 32>" # Auth.js v5; sinkron dengan NEXTAUTH_SECRET
AUTH_TRUST_HOST=true
SEED_ADMIN_PASSWORD="admin123"
Production: ganti
SEED_ADMIN_PASSWORDdi.envsebelum seed ulang, atau langsung reset via CLI (lihat bawah).
npm run dev
# → http://localhost:3000 atau http://10.202.10.15:3000
# hot-reload, tidak di-minify, bisa login admin/admin123Jika next dev diblokir saat diakses dari IP LAN lain:
# di .env
ALLOWED_DEV_ORIGINS="10.202.10.15,IP_PUBLIK_ANDA"
npm run devALLOWED_DEV_ORIGINS hanya berpengaruh di dev, tidak di production.
npm run build
npm start
# → NODE_ENV=production otomatis (Next 16)
# listen 0.0.0.0:80
# atau eksplisit:
NODE_ENV=production npm run build && NODE_ENV=production npm startAkses: http://IP_VM (lokal, port 80) atau http://IP_PUBLIK (via DNAT). Tidak perlu set NEXTAUTH_URL — AUTH_TRUST_HOST=true bikin Auth.js ikut Host publik, tidak akan MissingCSRF.
Port 80 butuh hak istimewa. Pilih salah satu: jalankan dengan
sudo npm start, atau systemd denganAmbientCapabilities=CAP_NET_BIND_SERVICE, atausetcap 'cap_net_bind_service=+ep' $(readlink -f $(which node)).
Update code setelah git pull:
git pull
npm install
npm run build
npm start # atau pm2 restart / systemctl restart equotationJalankan sebagai service (opsional, agar hidup setelah reboot):
# dengan pm2
npm i -g pm2
pm2 start npm --name equotation -- start
pm2 save && pm2 startup
# atau systemd: buat /etc/systemd/system/equotation.service
# ExecStart=/usr/bin/npm start WorkingDirectory=/opt/equotation
# AmbientCapabilities=CAP_NET_BIND_SERVICE (biar bisa bind port 80 tanpa root)Jalankan
npm run devataunpm run buildsekali sebelum typecheck/CI (typeLayoutPropsdi-generate ke.next/types).
npm run dev (NODE_ENV=development) |
npm run build && npm start (NODE_ENV=production) |
|
|---|---|---|
| Performa | Lambat, source map, hot-reload | Minify + cache, 10/10 static pages |
Login admin/admin123 |
Bisa | Bisa — tidak ada blokiran khusus; untuk deployment publik disarankan ganti password |
SEED_ADMIN_PASSWORD |
Default admin123 boleh |
Seed production wajib set variabel ini (seed menolak default tanpa env) |
ALLOWED_DEV_ORIGINS |
Aktif — untuk akses LAN/IP lain | Tidak berpengaruh |
AUTH_TRUST_HOST |
true |
true — sama (ikut Host NAT) |
| Prisma | prisma migrate dev (buat migration baru) |
prisma migrate deploy (apply saja, dipakai setup) |
Cara ganti: cukup ganti command. Tidak ada file lain yang perlu diedit untuk NAT.
Ganti password admin (disarankan di production publik):
npm run admin:reset-password -- admin PasswordBaru123Reset menghapus sesi aktif user tersebut (wajib login ulang).
- DNAT murni (
IP_PUBLIK → 10.x:80): tanpa Nginx, cukupAUTH_TRUST_HOST=true— sudah handle. - Nginx di depan
next start: wajib forward header agar tidakMissingCSRF/ cookie__Secure-mismatch:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme; # https bila publik TLS
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.202.10.15:80;- Jika publik pakai
httpstapi apphttpdi balik Nginx,X-Forwarded-Proto: httpswajib — kalau tidak, Auth.js set cookie non-Secure tapi browser minta Secure → login loop.
- Username:
admin - Password:
admin123(atau nilaiSEED_ADMIN_PASSWORDdi.env) - Halaman:
/login→/admin/dashboard - Rate limit login: 5 percobaan / 15 menit / IP (in-memory — reset saat server restart)
- Lupa password di server:
npm run admin:reset-password -- admin PasswordBaru123 - Ganti password/username dari dashboard:
/admin/account(butuh password lama; ganti password akan logout sesi lain otomatis, daftar sesi tampil di bawah form) - Deployment publik: ganti password default
admin123setelah setup.
Semua layanan dikelola dari dashboard /admin/services (nama, subtitle, deskripsi, urutan, status aktif) dengan dua gambar per layanan: gambar preview (tampil di kartu layanan sisi kiri) dan gambar full (tampil di panel kanan, tanpa crop). Jika gambar full belum diisi, panel kanan memakai gambar preview.
Seed (npm run db:seed) hanya mengisi 9 layanan + setting brand (idempoten — tidak timpa editan admin).
| Command | Fungsi |
|---|---|
npm run dev |
Dev server |
npm run build |
Build production |
npm start |
Start production, port 80 (NODE_ENV=production) |
npm run setup |
VM baru: .env + migrate + seed (sekali, idempoten) |
npm run lint |
ESLint |
npm run db:migrate |
Prisma migrate dev (buat migration baru) |
npm run db:push |
Push schema Prisma langsung ke DB (tanpa migration file) |
npm run db:seed |
Seed admin + layanan (idempoten) |
npm run admin:reset-password -- <user> <pass> |
Reset password via terminal (tanpa password lama) |
npm run setup sudah buat .env otomatis. Isinya:
DATABASE_URL="file:./prod.db"
NEXTAUTH_SECRET="<random 32 byte>"
AUTH_SECRET="<random 32 byte>" # wajib ada untuk Auth.js v5; sinkron NEXTAUTH_SECRET
AUTH_TRUST_HOST=true
SEED_ADMIN_PASSWORD="admin123"
# Opsional dev: ALLOWED_DEV_ORIGINS="10.202.10.15"
- Secret placeholder (
<openssl rand -base64 32>): bila ketahuan di.env, jalankannode scripts/setup-env.mjs— akan diganti random +AUTH_SECRETditambahkan. - Production publik: ganti
SEED_ADMIN_PASSWORD, jalankannpm run db:seed(ataunpm run admin:reset-password -- admin <pass-baru>). Seed tidak menimpa password user yang sudah ada.