chore: update gitignore and add root docs and tooling

This commit is contained in:
2026-05-21 16:05:53 +07:00
parent c72dde4484
commit 2311767e9f
12 changed files with 2582 additions and 0 deletions
+478
View File
@@ -0,0 +1,478 @@
# Deployment Guide
Panduan instalasi aplikasi di server produksi **Ubuntu 22.04+**.
---
## Spesifikasi Server
| Komponen | Minimum | Rekomendasi |
|----------|---------|-------------|
| CPU | 2 core | 4 core |
| RAM | 4 GB | 8 GB |
| Storage | 40 GB SSD | 100 GB SSD |
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
---
## Langkah 1 — Install Dependensi
```bash
sudo apt update && sudo apt upgrade -y
# PHP 8.3 + ekstensi
sudo add-apt-repository ppa:ondrej/php -y
sudo apt install -y php8.3 php8.3-fpm php8.3-pgsql php8.3-redis \
php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-gd \
php8.3-bcmath php8.3-intl php8.3-readline
# PostgreSQL, Redis, Nginx, Supervisor
sudo apt install -y postgresql postgresql-contrib redis-server nginx supervisor
sudo systemctl enable redis-server
# Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
```
---
## Langkah 2 — Setup Database
```bash
sudo -u postgres psql
```
```sql
CREATE USER biiproject WITH PASSWORD 'password_kuat_anda';
CREATE DATABASE biiproject_db OWNER biiproject;
GRANT ALL PRIVILEGES ON DATABASE biiproject_db TO biiproject;
\q
```
---
## Langkah 3 — Deploy Aplikasi
```bash
cd /var/www
sudo git clone <repo-url> html
sudo chown -R $USER:www-data html
cd html
composer install --no-dev --optimize-autoloader
npm install && npm run build
cp .env.example .env
php artisan key:generate
```
### Edit `.env`
```env
APP_NAME="biiproject"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://domain.com
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=biiproject_db
DB_USERNAME=biiproject
DB_PASSWORD=password_kuat_anda
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
BROADCAST_CONNECTION=reverb
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REVERB_APP_ID=your-app-id
REVERB_APP_KEY=your-app-key
REVERB_APP_SECRET=your-app-secret
REVERB_HOST=domain.com
REVERB_PORT=8080
REVERB_SCHEME=https
BCRYPT_ROUNDS=12
# Opsional — Error monitoring
SENTRY_LARAVEL_DSN=https://xxxx@sentry.io/xxxx
SENTRY_TRACES_SAMPLE_RATE=0.1
SENTRY_PROFILES_SAMPLE_RATE=0.1
```
### Migrasi, Seed & Optimisasi
```bash
php artisan migrate --force
php artisan db:seed --force
php artisan cache:clear # wajib setelah seeder
php artisan storage:link
php artisan optimize
php artisan l5-swagger:generate # regen API docs
```
### Post-Deploy Verification
```bash
# Quality gate — pastikan tidak ada regresi
./vendor/bin/phpstan analyse --memory-limit=1G
./vendor/bin/pint --test
composer audit --no-dev
# Health check
curl -sf https://domain.com/api/health | jq .
# expect: {"status":"healthy","timestamp":"...","checks":{...}}
```
---
## Langkah 4 — Konfigurasi Nginx
`/etc/nginx/sites-available/biiproject`:
```nginx
server {
listen 80;
server_name domain.com;
root /var/www/html/public;
index index.php;
client_max_body_size 50M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# WebSocket Reverb
location /app {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 60s;
}
location ~ /\.(?!well-known) { deny all; }
}
```
> **Catatan keamanan:** Laravel mengirim header `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, dan `Permissions-Policy` dari middleware `SecurityHeaders`. Tidak perlu duplikasi di Nginx — biarkan aplikasi yang kontrol (lebih mudah di-update via setting).
```bash
sudo ln -s /etc/nginx/sites-available/biiproject /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```
---
## Langkah 5 — SSL (Let's Encrypt)
```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d domain.com
```
Setelah HTTPS aktif, **aktifkan HSTS** dari admin panel: Global Settings → Login Security → `HSTS Enabled`. Aplikasi akan mengirim header `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`.
---
## Langkah 6 — Background Workers (Supervisor)
### Queue Worker
`/etc/supervisor/conf.d/biiproject-worker.conf`:
```ini
[program:biiproject-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
```
### Reverb (WebSocket)
`/etc/supervisor/conf.d/biiproject-reverb.conf`:
```ini
[program:biiproject-reverb]
command=php /var/www/html/artisan reverb:start --host=0.0.0.0 --port=8080
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/reverb.log
```
### Scheduler (Cron)
```bash
echo "* * * * * cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1" \
| sudo crontab -u www-data -
```
> Scheduler menjalankan `dashboard:broadcast-stats` setiap menit — membutuhkan queue worker dan Reverb **sudah berjalan** agar broadcast terkirim ke browser. Pastikan keduanya distart via Supervisor sebelum mengaktifkan cron.
### Aktifkan
```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start all
```
---
## Langkah 7 — Permission File
```bash
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html/storage /var/www/html/bootstrap/cache
```
---
## Langkah 8 — Konfigurasi Pasca-Deploy
### A. Global Settings
Login sebagai Super Admin → System Settings → Global Settings. Pastikan:
- [ ] `Password Policy`: min 12, charset mixed-case + digit + symbol, expiry & history sesuai kebijakan
- [ ] `Login Security`: max attempts 5, lockout duration, 2FA toggle, captcha jika perlu
- [ ] `IP & Access`: whitelist admin (IP kantor/VPN), auto-block on burst
- [ ] `HSTS Enabled`: ON (setelah SSL aktif)
- [ ] `Single Session`: ON jika kebijakan satu-device-per-akun
### B. Verifikasi Quality Gate
```bash
# Pastikan dependencies aman
composer audit --no-dev --abandoned=ignore
# Pastikan tidak ada regresi
php artisan test --parallel
```
---
## Layanan Eksternal (Opsional)
Sebagian besar bisa diatur via **Global Settings** di admin panel — tidak perlu edit `.env`.
### Email SMTP
```env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=postmaster@domain.com
MAIL_PASSWORD=xxxxxxxx
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@domain.com
MAIL_FROM_NAME="biiproject"
```
### Sentry (Error Monitoring)
```env
SENTRY_LARAVEL_DSN=https://xxxx@o0.ingest.sentry.io/xxxx
SENTRY_TRACES_SAMPLE_RATE=0.1
```
Buat project di [sentry.io](https://sentry.io), pilih platform **Laravel**, dan salin DSN-nya.
### Telegram Bot
1. Chat `@BotFather``/newbot` → simpan **Token**
2. Kirim pesan ke bot, buka `https://api.telegram.org/bot<TOKEN>/getUpdates` → simpan **Chat ID**
3. Masukkan via Global Settings → Notifications
> **Catatan:** `IpAccessControl` middleware mengirim alert otomatis ke Telegram saat sebuah IP di-auto-block karena burst — pastikan token + chat id valid.
### Google Drive Backup
1. Google Cloud Console → buat project → enable **Google Drive API**
2. Buat **OAuth 2.0 Client ID** (Desktop app)
3. Dapatkan **Refresh Token** via OAuth Playground
4. Masukkan Client ID, Client Secret, Refresh Token, dan nama folder via Global Settings → Backup
### Amazon S3
1. Buat IAM user dengan policy `AmazonS3FullAccess`
2. Buat S3 bucket
3. Masukkan Access Key, Secret, Bucket, Region (dan endpoint opsional) via Global Settings → Backup
### Firebase Cloud Messaging (Push Notification Mobile)
1. Buat project di Firebase Console → Project Settings → Cloud Messaging
2. Unduh `google-services.json` (Android) atau `GoogleService-Info.plist` (iOS)
3. Letakkan di direktori mobile app sesuai panduan Expo
4. Device token diregistrasikan otomatis via API `/api/v1/devices/register`
---
## CI/CD
Workflow di `.github/workflows/ci.yml`. Setiap push ke `main`/`develop`/`config`/`advanced` dan setiap PR ke `main`/`develop` menjalankan:
1. **Test**`php artisan test --parallel` (Postgres 15 + Redis 7 service containers)
2. **Lint**`pint --test` + `composer audit --abandoned=ignore` + `permissions:audit`
3. **Static Analysis**`phpstan analyse --memory-limit=1G`
Branch protection: PR tidak bisa di-merge kalau salah satu job gagal.
---
## Update Aplikasi
Cara tercepat dan teraman untuk memperbarui aplikasi adalah menggunakan skrip deployment otomatis yang sudah disediakan:
```bash
cd /var/www/html
sudo chmod +x deploy.sh
./deploy.sh
```
Skrip ini akan melakukan:
1. Masuk ke Maintenance Mode.
2. Update dependencies (Composer & NPM).
3. Build assets (Vite).
4. Run migrations.
5. Optimasi cache & pembersihan log.
6. Restart background workers (Queue & Reverb).
7. Verifikasi kesehatan sistem.
8. Keluar dari Maintenance Mode.
### Update Manual
```bash
cd /var/www/html
git pull origin main
php artisan down --secret="your-bypass-key"
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan cache:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan l5-swagger:generate
sudo supervisorctl restart biiproject-worker:*
sudo supervisorctl restart biiproject-reverb
# Verifikasi
curl -sf https://domain.com/api/health | jq -e '.checks.database.status == "ok"'
php artisan up
```
---
## Deployment via Docker (alternatif)
```bash
git clone <repo-url> Project
cd Project
cp .env.example .env
# Edit .env:
# DB_HOST=pgsql (nama service Docker, bukan 127.0.0.1)
# REDIS_HOST=redis
./vendor/bin/sail up -d
./vendor/bin/sail artisan migrate --seed --force
./vendor/bin/sail artisan cache:clear
./vendor/bin/sail artisan optimize
```
> **Penting:** Semua perintah `php artisan` di lingkungan Docker **harus** dijalankan via `./vendor/bin/sail artisan`, bukan langsung. Host `pgsql` hanya bisa di-resolve dari dalam Docker network.
---
## Troubleshooting
| Masalah | Solusi |
|---------|--------|
| 502 Bad Gateway | `sudo systemctl status php8.3-fpm` |
| Queue tidak jalan | `sudo supervisorctl status` |
| Permission denied | `sudo chown -R www-data:www-data storage bootstrap/cache` |
| Cache error setelah update | `php artisan optimize:clear && php artisan optimize` |
| Settings tidak muncul setelah seeder | `php artisan cache:clear` (settings di-cache 60 menit) |
| WebSocket gagal connect | `sudo supervisorctl status biiproject-reverb` + cek port 8080 di firewall |
| `pgsql` host tidak resolve | Pastikan `DB_HOST=127.0.0.1` (bukan `pgsql`) di server non-Docker |
| Telescope/log tidak ditemukan | Cek `storage/logs/laravel.log` & menu System Monitoring → Logs |
| Error monitoring tidak aktif | Pastikan `SENTRY_LARAVEL_DSN` sudah diset di `.env` |
| `/api/health` return 503 | Cek setiap field `checks.*.status` — yang `fail` mengindikasikan masalah. `warn` (storage >90%) tetap 200 by design. |
| OAuth callback 404 | Pastikan route order: `/auth/callback` HARUS sebelum `/auth/{provider}` di `routes/web.php`. |
| `column "google_id" does not exist` | Pastikan migrasi `2026_05_12_120000_add_social_columns_to_users_table` sudah jalan. |
| Dashboard stats tidak update real-time | Cek Reverb berjalan (`supervisorctl status biiproject-reverb`), queue worker aktif, dan `BROADCAST_CONNECTION=reverb` di `.env`. |
| Dashboard widget tidak tersimpan | Pastikan migrasi `2026_05_16_220000_create_dashboard_widget_preferences_table` sudah dijalankan. |
---
## Performance Tuning
### PHP-FPM
`/etc/php/8.3/fpm/pool.d/www.conf`:
```ini
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
```
### OPcache
`/etc/php/8.3/fpm/php.ini`:
```ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; production only
opcache.preload=/var/www/html/bootstrap/cache/preload.php
opcache.preload_user=www-data
```
### Redis Tuning
`/etc/redis/redis.conf`:
```
maxmemory 1gb
maxmemory-policy allkeys-lru
```
### PostgreSQL
Tambah index recommendation: sudah ada (lihat migrasi `2026_05_14_100000_add_performance_indexes`). Untuk dataset besar (>10M rows pada `activity_log`), pertimbangkan `pg_partman` untuk partisi bulanan.