# Panduan Deploy SIPORA

## Ringkasan

Memasang SIPORA di server baru hanya perlu tiga langkah: **upload file, atur `.env`, buka
installer di browser**. Dokumen ini menjelaskan langkah-langkahnya untuk hosting bersama
(shared hosting/cPanel) maupun VPS, plus alternatif lewat CLI bagi yang punya akses SSH.

## Persyaratan Server

Jalankan `php tools/check-requirements.php` (lewat SSH) untuk memeriksa otomatis, atau
periksa manual lewat panel hosting:

- PHP 8.2 atau lebih baru.
- Ekstensi PHP: `curl`, `fileinfo`, `gd`, `mbstring`, `openssl`, `pdo_mysql`, `xml`, `zip`, `zlib`.
- MySQL 8.0+ atau MariaDB 10.6+.
- Modul `mod_rewrite` Apache aktif (dipakai `public/.htaccess` untuk routing).
- Database dan user MySQL/MariaDB sudah dibuat lewat panel hosting, dengan user tersebut
  diberi akses penuh HANYA ke database tersebut.

## Langkah 1: Siapkan Paket

Di komputer developer (bukan di server), jalankan:

```
php tools/build-release.php
```

Ini membuat `storage/releases/sipora-release-<tanggal>.zip` berisi seluruh kode aplikasi
plus `vendor/` yang sudah dioptimalkan untuk produksi (tanpa dependensi development seperti
PHPUnit). Ekstrak zip ini menjadi folder kerja sebelum upload.

Tanpa akses untuk menjalankan `build-release.php`, boleh juga upload langsung dari checkout
git ditambah `composer install --no-dev --optimize-autoloader` di server bila composer
tersedia di sana.

## Langkah 2: Upload — Pilih Struktur Sesuai Hosting

SIPORA tidak mengasumsikan lokasi foldernya di server (semua path dihitung relatif dari
lokasi file itu sendiri), jadi kedua skenario berikut sama-sama berfungsi tanpa mengubah kode.

### Skenario A — Bisa mengatur document root (VPS, atau hosting yang izinkan ubah docroot)

Upload seluruh isi paket apa adanya, lalu arahkan document root web server ke folder `public/`.
Folder `app/`, `database/`, `storage/`, `tools/`, `vendor/` tetap berada di luar area yang
bisa diakses langsung lewat HTTP — ini yang paling aman.

**Kasus umum yang termasuk Skenario A: subdomain di cPanel.** Saat membuat subdomain
(mis. `sipora.namadomain.com`) lewat menu Subdomains cPanel, kolom "Document Root" biasanya
berupa isian bebas, bukan cuma dropdown ke dalam `public_html/`. Kalau begitu, upload SATU
folder saja apa adanya (mis. `sipora/` berisi persis seluruh isi paket rilis — `app/`,
`public/`, `storage/`, dst sebagai anak langsung folder itu, boleh diletakkan di mana saja
yang nyaman lewat File Manager, tidak harus sejajar `public_html/`), lalu arahkan Document
Root subdomain tersebut ke `sipora/public` (bukan ke `sipora` saja). Hasilnya satu folder
untuk seluruh aplikasi, tapi tetap hanya isi `public/` yang bisa diakses lewat web — sama
amannya dengan upload ke server sendiri, cukup satu lokasi upload.

Bila kolom Document Root subdomain ternyata dibatasi harus di dalam `public_html/` (tidak
bisa path bebas), upload folder tunggal itu sebagai `public_html/sipora/` lalu arahkan
Document Root ke `public_html/sipora/public` — prinsipnya sama, cuma lokasinya bersarang
satu tingkat lebih dalam.

### Skenario B — Hosting bersama umum (cPanel, document root tetap `public_html/`)

1. Upload **ISI folder `public/`** (bukan foldernya) langsung ke `public_html/`.
2. Upload folder `app/`, `database/`, `storage/`, `tools/`, `vendor/`, serta file
   `composer.json`, `composer.lock`, `.env.example` sebagai **saudara (sibling)** dari
   `public_html/` — yaitu di folder home akun hosting, sejajar dengan `public_html/`,
   BUKAN di dalamnya.

   Struktur akhir di server (contoh):
   ```
   /home/namauser/
   ├── app/
   ├── database/
   ├── storage/
   ├── tools/
   ├── vendor/
   ├── composer.json
   ├── composer.lock
   ├── .env                  <- dibuat di langkah berikutnya
   └── public_html/          <- isi folder public/ SIPORA ada di sini
       ├── index.php
       ├── install.php
       ├── .htaccess
       └── assets/
   ```

   Ini berfungsi karena `public/index.php` (dan `install.php`) menghitung folder lain lewat
   `dirname(__DIR__)` dari lokasinya sendiri — begitu `index.php` ada di `public_html/`,
   `dirname(__DIR__)` otomatis mengarah ke folder home yang berisi `app/`, `storage/`, dst.

3. `public/.htaccess` sudah menolak akses langsung ke file `.env`, `.ini`, `.log`, `.sql`
   dan dotfile lain lewat HTTP — tapi pada Skenario B, folder-folder sensitif itu sama sekali
   tidak berada di dalam `public_html/`, jadi tidak bisa diakses lewat web sama sekali
   (lebih aman daripada mengandalkan `.htaccess` saja).

## Langkah 3: Konfigurasi `.env`

1. Salin `.env.example` menjadi `.env` (di folder yang sama dengan `app/`, `database/`, dst
   — pada Skenario B berarti di folder home, BUKAN di dalam `public_html/`).
2. Isi `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` sesuai database
   yang sudah dibuat di panel hosting.
3. Set `APP_ENV=production` dan `APP_DEBUG=false` — **wajib**, supaya error tidak pernah
   menampilkan detail teknis/SQL ke pengunjung.
4. Set `APP_URL` ke alamat sesungguhnya (mis. `https://sekolah.contoh.sch.id`).
5. Buat `APP_KEY` baru — jangan pernah pakai nilai contoh:
   ```
   php -r "echo 'base64:' . base64_encode(random_bytes(32)) . PHP_EOL;"
   ```
   Bila tidak punya akses SSH, jalankan perintah ini di komputer lokal (PHP mana pun) dan
   salin hasilnya ke `.env` di server lewat File Manager.
6. Bila SIPORA dipasang di sub-folder (mis. `https://domain.com/sipora`), isi `APP_BASE_PATH`
   dengan path tersebut (mis. `/sipora`). Kosongkan bila di root domain.

## Langkah 4: Jalankan Installer

Buka `https://domain-anda.com/install.php` di browser. Installer ini akan, dalam satu
alur halaman yang sama:

1. Memeriksa persyaratan server (PHP, ekstensi, folder `storage/` bisa ditulis).
2. Menguji koneksi database memakai isian `.env`.
3. Menjalankan seluruh migrasi skema database (tombol "Jalankan Migrasi" — pada database
   kosong ini menjalankan puluhan migrasi dan bisa perlu diklik beberapa kali bila hosting
   membatasi waktu eksekusi PHP per-permintaan; installer berhenti dengan aman dan bisa
   dilanjutkan, tidak akan merusak data).
4. Menampilkan form untuk membuat akun **Super Admin** pertama (username, email, password).

Begitu akun Super Admin dibuat, installer **mengunci dirinya sendiri secara otomatis**
(menulis penanda `storage/.installed`) — mengakses `install.php` setelahnya hanya akan
menampilkan pesan "sudah terpasang", tidak bisa dipakai ulang oleh siapa pun.

**Segera setelah pemasangan selesai, hapus file `install.php` dari server** (lewat File
Manager hosting atau SFTP) sebagai lapisan keamanan tambahan — jangan hanya mengandalkan
penguncian otomatis di atas.

### Alternatif lewat CLI (bila punya akses SSH)

```
php tools/check-requirements.php
php tools/migrate.php up
php tools/create-admin.php --username=admin --email=admin@sekolah.sch.id --password=...
```

`create-admin.php` tidak menulis penanda `storage/.installed` — bila memakai jalur ini,
buat sendiri file kosong tersebut (`touch storage/.installed`) supaya `install.php` ikut
terkunci bila filenya masih ada di server.

## Checklist Pasca-Deploy

- [ ] File `install.php` sudah dihapus dari server.
- [ ] `.env` berisi `APP_ENV=production` dan `APP_DEBUG=false`.
- [ ] HTTPS aktif (sertifikat SSL dari panel hosting) — SIPORA menandai cookie sesi sebagai
      `secure` otomatis saat `APP_ENV=production`, jadi login tidak akan berfungsi lewat
      HTTP biasa di production.
- [ ] Login sebagai Super Admin berhasil, lalu segera aktifkan MFA (Menu profil > Keamanan)
      untuk akun tersebut.
- [ ] Cron backup harian sudah diatur — lihat [RUNBOOK_BACKUP.md](RUNBOOK_BACKUP.md).
- [ ] `/health` (atau `/superadmin/health` setelah login) menunjukkan seluruh pemeriksaan
      berstatus `ok`.
- [ ] Bila ada data siswa/sekolah lama yang perlu dipindahkan — lihat
      [RUNBOOK_LEGACY_MIGRATION.md](RUNBOOK_LEGACY_MIGRATION.md).
- [ ] Sebelum dipakai serentak oleh banyak siswa (mis. sesi asesmen massal), lihat
      [RUNBOOK_LOAD_TESTING.md](RUNBOOK_LOAD_TESTING.md) dan
      [PILOT_READINESS_CHECKLIST.md](PILOT_READINESS_CHECKLIST.md).

## Memperbarui Aplikasi yang Sudah Berjalan

1. Buat backup: `php tools/backup.php` (lihat [RUNBOOK_BACKUP.md](RUNBOOK_BACKUP.md)).
2. Upload file kode yang berubah (jangan timpa `.env` dan folder `storage/`).
3. Jalankan migrasi bila ada yang baru: `php tools/migrate.php up`.
4. Periksa `/superadmin/health`.

`install.php` tidak dipakai untuk update — hanya untuk pemasangan pertama kali, dan pada
instalasi yang sudah berjalan file ini seharusnya sudah dihapus dari langkah di atas.
