Files
biiproject-kit-v1/DEPLOYMENT_GUIDE.md
T

12 KiB

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

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

sudo -u postgres psql
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

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

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

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

# 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:

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).

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)

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:

[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:

[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)

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

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start all

Langkah 7 — Permission File

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

# 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

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)

SENTRY_LARAVEL_DSN=https://xxxx@o0.ingest.sentry.io/xxxx
SENTRY_TRACES_SAMPLE_RATE=0.1

Buat project di 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. Testphp artisan test --parallel (Postgres 15 + Redis 7 service containers)
  2. Lintpint --test + composer audit --abandoned=ignore + permissions:audit
  3. Static Analysisphpstan 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:

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

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)

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:

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:

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.