# Panduan Instalasi MySQL dan Hosting

Paket ini menggunakan Next.js 16, Node.js 22, MySQL 8, `mysql2`, dan Drizzle ORM. Hosting harus mendukung aplikasi Node.js yang berjalan terus-menerus. Paket ini tidak dapat dijalankan sebagai hosting HTML/PHP statis saja.

## 1. Persyaratan hosting

- Node.js minimal 22.13.
- MySQL minimal 8.0.13; MySQL 8.4 LTS juga didukung.
- Akses membuat database dan user MySQL.
- Dukungan environment variable.
- Perintah build `npm ci && npm run build`.
- Perintah start `npm start` dan port dari hosting/proxy.
- Folder `storage/` harus dapat ditulis oleh proses Node.js dan ikut dibackup.
- HTTPS aktif pada domain production.

Shared hosting yang hanya menyediakan PHP tidak cocok. Gunakan cPanel dengan **Setup Node.js App**, VPS dengan PM2/systemd, Plesk Node.js, atau platform Node.js yang menyediakan MySQL eksternal.

## 2. Instalasi lokal di Windows dan VS Code

1. Pasang Node.js 22 LTS dan MySQL 8 atau Laragon yang menggunakan MySQL 8.
2. Ekstrak ZIP, lalu buka folder proyek melalui **File → Open Folder** di VS Code.
3. Buka Terminal VS Code.
4. Buat database lewat MySQL CLI atau phpMyAdmin:

```sql
CREATE DATABASE padjajaran_elektrik
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;
```

5. Salin file environment:

```powershell
Copy-Item .env.example .env.local
```

6. Isi `.env.local`. Contoh lokal:

```dotenv
DATABASE_URL=mysql://root@127.0.0.1:3306/padjajaran_elektrik
DATABASE_CONNECTION_LIMIT=10
SESSION_SECRET=GANTI_DENGAN_NILAI_ACAK_MINIMAL_64_KARAKTER
PASSWORD_PEPPER=GANTI_DENGAN_NILAI_ACAK_LAIN_MINIMAL_64_KARAKTER
BACKUP_ENCRYPTION_KEY=GANTI_DENGAN_NILAI_ACAK_KHUSUS_BACKUP
SETUP_TOKEN=GANTI_DENGAN_TOKEN_SETUP_SEKALI_PAKAI
OWNER_RECOVERY_TOKEN=GANTI_DENGAN_TOKEN_PEMULIHAN_PEMILIK
SUPER_ADMIN_EMAIL=email-pemilik@domain.com
SITE_BASE_URL=http://localhost:3000
APP_ENV=development
DISABLE_ANALYTICS=true
```

Jika password MySQL berisi karakter seperti `@`, `:`, `/`, `#`, atau `%`, URL-encode password tersebut sebelum dimasukkan ke `DATABASE_URL`.

7. Instal dan siapkan database:

```powershell
npm ci
npm run db:setup
npm run db:check
```

8. Jalankan website:

```powershell
npm run dev
```

9. Buka `http://localhost:3000/cms/setup`. Masukkan `SETUP_TOKEN` dari `.env.local`, kemudian buat Super Admin dan aktifkan MFA.

## 3. Alternatif impor melalui phpMyAdmin

Jika hosting tidak menyediakan terminal:

1. Buat database kosong dan pilih collation `utf8mb4_unicode_ci`.
2. Buka phpMyAdmin → pilih database → **Import**.
3. Pilih `database/mysql/install.sql`.
4. Pastikan impor selesai tanpa error dan terdapat 36 tabel aplikasi ditambah tabel `pe_migrations` bila migration CLI pernah dipakai.
5. Jangan menjalankan `npm run db:setup` pada database yang sudah diisi dengan `install.sql`.

File `install.sql` tidak membuat akun admin dan tidak berisi password.

## 4. Upload ke cPanel Node.js

1. Buat database dan user MySQL di **MySQL Databases**. Berikan seluruh privilege hanya pada database aplikasi.
2. Import `database/mysql/install.sql` melalui phpMyAdmin, atau jalankan `npm run db:setup` melalui terminal cPanel.
3. Upload dan ekstrak source ke folder aplikasi. Jangan upload `.env.local` dari komputer lokal.
4. Di **Setup Node.js App** pilih Node.js 22, mode `Production`, dan root folder proyek.
5. Tambahkan environment variable dari `.env.example` dengan nilai production. Contoh koneksi:

```dotenv
DATABASE_URL=mysql://NAMA_USER:PASSWORD_URL_ENCODED@127.0.0.1:3306/NAMA_DATABASE
SITE_BASE_URL=https://domain-anda.com
APP_ENV=production
DISABLE_ANALYTICS=false
```

6. Jalankan `npm ci`, lalu `npm run build`.
7. Gunakan `npm start` sebagai startup command. Jika panel meminta startup file dan tidak mendukung command, gunakan VPS/PM2 atau fitur Node.js yang mendukung script `start` dari `package.json`.
8. Pastikan proses Node.js dapat membuat dan menulis folder `storage/`.
9. Buka `/cms/setup` saat website masih dibatasi, buat Super Admin, lalu ganti `SETUP_TOKEN` setelah setup selesai.

## 5. Deploy di VPS dengan PM2

```bash
npm ci
npm run db:setup
npm run build
npm install -g pm2
pm2 start npm --name padjajaran-elektrik -- start
pm2 save
```

Pasang Nginx/Apache reverse proxy ke port aplikasi, aktifkan HTTPS, dan jangan mengekspos port MySQL ke internet. Jika database ada di server lain, batasi akses berdasarkan IP dan gunakan koneksi TLS.

## 6. Menjalankan pembaruan source

1. Backup database dan folder `storage/`.
2. Upload source versi baru tanpa menimpa `.env.local` dan `storage/`.
3. Jalankan `npm ci`.
4. Jalankan `npm run db:migrate`.
5. Jalankan `npm run build`.
6. Restart proses Node.js.
7. Jalankan `npm run db:check` dan uji login, artikel, harga, lead, upload foto, serta halaman publik.

Jangan menjalankan `npm run db:seed` berulang kali untuk mengembalikan konten lama. Seed dibuat idempotent, tetapi tetap hanya ditujukan sebagai data awal.

## 7. Penyimpanan gambar dan backup

- Metadata gambar disimpan di tabel `media` MySQL.
- File gambar disimpan dalam folder `storage/cms-uploads/` atau `storage/lead-uploads/`.
- Backup CMS terenkripsi disimpan dalam folder `storage/backups/`.
- Backup production harus mencakup **database MySQL dan seluruh folder `storage/`**.
- Jangan menyimpan file upload di folder `public/` karena file lead bersifat privat.
- Terapkan permission minimum agar hanya user proses aplikasi yang dapat menulis.

## 8. Pemeriksaan setelah upload

```bash
npm run db:check
npm run lint
npm test
```

Kemudian periksa secara manual:

- `/` dan halaman layanan terbuka.
- `/cms/login` dapat digunakan dengan MFA.
- artikel dapat dibuat, disimpan, diberi gambar, dan diterbitkan.
- harga dan kalkulator menampilkan data MySQL.
- formulir lead tersimpan dan foto dapat dibuka dari CMS.
- ekspor CSV lead dan audit log berfungsi.
- logo/favicon tersimpan dan tampil.
- folder `storage/` dapat ditulis dan dibackup.

## 9. Catatan migrasi dari website lama

Paket ini menyiapkan schema dan data awal MySQL untuk instalasi baru. Data yang sudah tersimpan pada database D1 website lama tidak otomatis ikut dipindahkan. Jika data lama perlu dipertahankan, ekspor dahulu dari CMS/D1 lalu lakukan transformasi dan impor khusus ke MySQL sebelum domain diarahkan ke instalasi baru.
