# Panduan Deploy Rabbit Presensia ke VPS / Hosting

Panduan menyiapkan server produksi dari nol: upload kode, migrasi database kosongan (dengan user & password default), menjalankan aplikasi, sampai HTTPS publik.

---

## 1. Persyaratan Server

| Kebutuhan | Minimal | Rekomendasi |
|---|---|---|
| OS | Ubuntu 20.04+ / Debian 11+ | Ubuntu 22.04 LTS |
| RAM | 1 GB | 2 GB |
| Disk | 10 GB | 20 GB |
| Node.js | **20.19+ atau 22.12+** (syarat Vite 7) | 22 LTS |
| MySQL | 8.0+ / MariaDB 10.5+ | MySQL 8.0 |
| Domain (opsional tapi disarankan) | - | `absen.contoh.com` |

Aplikasi terdiri dari **1 server Node.js (Express + API)** yang sekaligus menyajikan **frontend React** (hasil build di `client/dist`). Cukup 1 proses Node + MySQL + (opsional) Nginx untuk HTTPS.

---

## 2. Struktur Project

```
rabbit-presensia/
├── client/                 # Frontend React (Vite)
│   ├── public/sw.js        # Service Worker PWA
│   └── dist/               # Hasil build (dibuat di server)
├── server/                 # Backend Node.js (Express)
│   ├── database/init-kosongan.sql  # MIGRASI KOSONGAN (instalasi pertama, hanya admin)
│   ├── database/init.sql           # (opsional) database berisi data contoh
│   ├── routes/             # API
│   ├── uploads/            # Folder foto absen (dibuat otomatis)
│   └── certs/              # Cert lokal (hanya utk pengembangan, lihat bab 8)
├── package.json            # NPM workspace root
└── server/package.json
```

---

## 3. Upload File ke Server

### Opsi A - Git (disarankan)

```bash
git clone <url-repo-anda> /opt/rabbit-presensia
cd /opt/rabbit-presensia
```

### Opsi B - rsync (tanpa git)

```bash
rsync -avz --exclude 'node_modules' \
           --exclude 'client/dist' \
           --exclude 'server/uploads' \
           --exclude 'server/certs' \
           --exclude 'server/server.log' \
           --exclude '.git' \
           ./ user@IP-SERVER:/opt/rabbit-presensia/
```

Atau pakai **FileZilla** (SFTP) dengan pola exclude yang sama.

> **Jangan ikut terupload:** `node_modules`, `client/dist`, `server/uploads`, `server/certs`, `server.log`. Folder `server/uploads` wajib bisa ditulis oleh proses Node (dibuat otomatis saat start).

---

## 4. Migrasi Database Kosongan (Setup Pertama)

### 4.1 Buat user MySQL khusus (tidak wajib memakai root)

```bash
sudo mysql -u root -p
```

```sql
CREATE USER 'rabbit'@'localhost' IDENTIFIED BY 'GANTI-PASSWORD-KUAT';
GRANT ALL PRIVILEGES ON rabbit_presensia.* TO 'rabbit'@'localhost';
FLUSH PRIVILEGES;
```

### 4.2 Import file migrasi (database kosongan)

> Gunakan **`server/database/init-kosongan.sql`** untuk instalasi pertama:
> membuat database `rabbit_presensia`, **semua tabel**, dan **hanya akun admin
> default** (tanpa karyawan demo / shift / pengaturan). Aman dijalankan ulang
> (idempotent).
>
> (Jika ingin database berisi data contoh — shift, pengaturan, 4 akun demo —
> gunakan `server/database/init.sql` sebagai gantinya.)

```bash
mysql -u rabbit -p < /opt/rabbit-presensia/server/database/init-kosongan.sql
```

Atau lewat **phpMyAdmin / Adminer**: buka tab Import, pilih `init-kosongan.sql`.

### 4.3 Akun default (instalasi pertama)

| Role | Email | Password |
|---|---|---|
| Admin | `admin@rabbit.com` | `admin123` |

> **WAJIB ganti password default** setelah login pertama (menu **Profil Saya -> Ubah Password**).
> Setelah masuk, buat shift, lokasi kantor/proyek, dan akun karyawan lewat menu aplikasi.

> Catatan: aplikasi juga bisa membuat database + tabel + seed otomatis saat pertama kali start (`server/db.js`). Jadi minimal Anda cukup menyediakan user MySQL + nama database; file `init-kosongan.sql` mempercepat dan memastikan semuanya siap (hanya akun admin) sebelum aplikasi berjalan.

---

## 5. Install Dependensi & Build Frontend

> `package-lock.json` tersedia, jadi gunakan `npm ci` agar versi terpasang
> persis seperti di repo. Dengan npm workspace, satu perintah sudah menginstal
> backend (`server`) + frontend (`client`).

```bash
cd /opt/rabbit-presensia
npm ci
npm run build -w client     # build frontend -> client/dist
```

Verifikasi Node memenuhi syarat Vite 7:
```bash
node -v   # wajib 20.19+ atau 22.12+
```

---

## 6. Konfigurasi Environment

Variabel yang dibaca server (default dalam kurung):

| Variabel | Default | Keterangan |
|---|---|---|
| `DB_HOST` | `127.0.0.1` | Host MySQL |
| `DB_PORT` | `3307` | **di VPS biasanya MySQL di `3306` - WAJIB di-set** |
| `DB_USER` | `root` | User MySQL (sebaiknya user khusus bab 4.1) |
| `DB_PASSWORD` | `qwer1234` | Password MySQL |
| `DB_NAME` | `rabbit_presensia` | Nama database |
| `PORT` | `5000` | Port aplikasi (HTTP/HTTPS Node) |
| `HTTP_PORT` | `5001` | Port HTTP tambahan (di produksi tidak wajib) |
| `JWT_SECRET` | rahasia dev | **WAJIB di-set** di produksi untuk keamanan sesi login |

Contoh nilai:

```
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=rabbit
DB_PASSWORD=password-kuat-anda
DB_NAME=rabbit_presensia
PORT=5000
HTTP_PORT=5001
JWT_SECRET=ganti-dengan-string-acak-panjang
```

> `JWT_SECRET` cukup buat sekali (contoh: `openssl rand -hex 32`), simpan di
> tempat aman, dan jangan diubah setelah dipakai karena akan membuat semua
> sesi login tidak valid.

---

## 7. Menjalankan Server

### Opsi A - PM2 (disarankan)

Buat `ecosystem.config.cjs` di root project:

```js
module.exports = {
  apps: [{
    name: 'rabbit-presensia',
    cwd: '/opt/rabbit-presensia',
    script: 'server/index.js',
    interpreter: 'node',
    env: {
      DB_HOST: '127.0.0.1',
      DB_PORT: '3306',
      DB_USER: 'rabbit',
      DB_PASSWORD: 'password-kuat-anda',
      DB_NAME: 'rabbit_presensia',
      PORT: '5000',
      HTTP_PORT: '5001',
      JWT_SECRET: 'ganti-dengan-string-acak-panjang'
    },
    out_file: '/var/log/rabbit-presensia.log',
    error_file: '/var/log/rabbit-presensia-error.log',
    time: true
  }]
}
```

```bash
npm install -g pm2
cd /opt/rabbit-presensia
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup   # ikuti perintah yang muncul agar auto-start saat reboot
```

### Opsi B - systemd

Buat `/etc/systemd/system/rabbit-presensia.service`:

```ini
[Unit]
Description=Rabbit Presensia
After=network.target mysql.service

[Service]
Type=simple
WorkingDirectory=/opt/rabbit-presensia
ExecStart=/usr/bin/node /opt/rabbit-presensia/server/index.js
Environment=DB_HOST=127.0.0.1
Environment=DB_PORT=3306
Environment=DB_USER=rabbit
Environment=DB_PASSWORD=password-kuat-anda
Environment=DB_NAME=rabbit_presensia
Environment=PORT=5000
Environment=HTTP_PORT=5001
Environment=JWT_SECRET=ganti-dengan-string-acak-panjang
Restart=always
User=www-data

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now rabbit-presensia
```

### Verifikasi

```bash
curl http://127.0.0.1:5000/api/health
# => {"ok":true,"app":"Rabbit Presensia dev by Agni Dev"}
```

---

## 8. HTTPS Publik (Nginx + Let's Encrypt)

> **Penting:** fitur kamera, geolokasi, dan PWA hanya berfungsi di **secure context (HTTPS)** - kecuali `localhost`. Untuk akses dari HP karyawan, WAJIB pakai HTTPS.

Node bisa langsung HTTPS **jika** `server/certs/` berisi `key.pem` + `cert.pem`. Di produksi lebih baik **tidak** mengirim cert lokal tersebut dan membiarkan **Nginx yang menangani SSL** (Node tetap HTTP internal di `127.0.0.1:5000`). Hapus folder `server/certs` bila tidak digunakan.

### 8.1 Pasang Nginx

```bash
sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx
```

### 8.2 Buat konfigurasi site

Buat `/etc/nginx/sites-available/rabbit-presensia`:

```nginx
server {
    server_name absen.contoh.com;

    client_max_body_size 20M;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
```

```bash
sudo ln -s /etc/nginx/sites-available/rabbit-presensia /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```

### 8.3 Terbitkan sertifikat Let's Encrypt

```bash
sudo certbot --nginx -d absen.contoh.com
```

Arahkan DNS domain ke IP server **sebelum** menjalankan perintah ini.

### 8.4 Firewall (ufw)

```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
```

Port 5000/5001 sebaiknya **jangan dibuka** ke publik; akses cukup lewat Nginx (80/443).

---

## 9. Akses Pertama Kali

1. Buka `https://absen.contoh.com`
2. Login: `admin@rabbit.com` / `admin123`
3. Segera ganti password lewat **Profil Saya -> Ubah Password**
4. Atur data perusahaan & lokasi kantor di **Pengaturan** (lat/lng/radius kantor, tarif lembur & potongan telat, SOP)
5. Minta karyawan mendaftarkan perangkat lewat halaman `/presensi` di HP, lalu validasi di menu **Validasi** / **Manajemen Pengguna**

---

## 10. Checklist Keamanan

- [ ] Ganti semua password default akun demo
- [ ] Gunakan user MySQL khusus (bukan root) dengan password kuat
- [ ] Atur `late_penalty_per_minute`, `overtime_rate_hour`, dan lokasi kantor di menu Pengaturan sesuai kebijakan perusahaan
- [ ] Backup database rutin: `mysqldump -u rabbit -p rabbit_presensia > backup-$(date +%F).sql`
- [ ] Update & upgrade OS secara berkala
- [ ] Nonaktifkan akses port 5000/5001 dari internet bila memakai Nginx