Files
speech2text/DEPLOYMENT.md
2026-06-02 17:35:45 +08:00

319 lines
7.1 KiB
Markdown

# DEPLOYMENT.md — Speech2Text MBIP
## Keperluan Server
| Komponen | Minimum | Disyorkan |
|---|---|---|
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| CPU | 4 core | 8 core |
| RAM | 8 GB | 16 GB |
| Storage | 100 GB | 500 GB+ (untuk audio files) |
| Docker | 24.x | Latest stable |
| Docker Compose | 2.x | Latest stable |
**Nota:** RAM tambahan diperlukan jika menggunakan Whisper model yang lebih besar (medium/large).
---
## Struktur Direktori Server
```
/svr/speech2text/
├── .env # environment variables (JANGAN commit ke git)
├── .env.example # template (commit ke git)
├── docker-compose.yml # development / staging
├── docker-compose.prod.yml # production override
├── Dockerfile # Laravel app image
├── docker/
│ ├── nginx/
│ │ └── default.conf
│ ├── php/
│ │ └── php.ini
│ ├── supervisor/
│ │ └── supervisord.conf
│ └── transcription-worker/
│ └── Dockerfile
├── app/ # Laravel source code
│ ├── storage/
│ │ └── app/
│ │ └── private/ # fail audio (tidak accessible web)
│ └── ...
└── mysql-data/ # MySQL data volume (auto-created)
```
---
## Langkah Deployment Pertama Kali
### 1. Persediaan Server
```bash
# Update server
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# Verify
docker --version
docker compose version
```
### 2. Clone Repository
```bash
sudo mkdir -p /svr/speech2text
sudo chown $USER:$USER /svr/speech2text
cd /svr/speech2text
git clone <repo-url> .
```
### 3. Konfigurasi Environment
```bash
cp .env.example .env
nano .env # atau gunakan editor pilihan anda
```
Nilai wajib diisi dalam `.env`:
```
APP_KEY= # akan dijanakan kemudian
DB_PASSWORD=<password-kuat>
ADMIN_DEFAULT_NAME=<nama-admin>
ADMIN_DEFAULT_EMAIL=<email-admin>
ADMIN_DEFAULT_PASSWORD=<password-admin-kuat>
```
### 4. Build dan Jalankan Container
```bash
cd /svr/speech2text
docker compose up -d --build
```
### 5. Setup Laravel
```bash
# Jana APP_KEY
docker compose exec app php artisan key:generate
# Jalankan migration dan seeder
docker compose exec app php artisan migrate --seed
# Set permission storage
docker compose exec app chmod -R 775 storage bootstrap/cache
docker compose exec app chown -R www-data:www-data storage bootstrap/cache
```
### 6. Verify Services
```bash
# Semak semua container berjalan
docker compose ps
# Semak logs
docker compose logs -f app
docker compose logs -f queue-worker
docker compose logs -f transcription-worker
# Semak queue worker
docker compose exec app php artisan queue:monitor
```
---
## Deployment Update (Selepas Push Kod Baru)
```bash
cd /svr/speech2text
# Pull kod terbaru
git pull origin main
# Rebuild container jika ada perubahan Dockerfile
docker compose up -d --build app
# Atau restart tanpa rebuild jika hanya kod PHP berubah
docker compose restart app queue-worker scheduler
# Jalankan migration baru (jika ada)
docker compose exec app php artisan migrate --force
# Clear cache
docker compose exec app php artisan config:cache
docker compose exec app php artisan route:cache
docker compose exec app php artisan view:cache
# Restart queue worker untuk ambil kod baru
docker compose restart queue-worker
```
---
## Production Override (`docker-compose.prod.yml`)
```bash
# Jalankan dengan production config
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
```
---
## Konfigurasi Nginx (Luar Docker — jika ada reverse proxy)
Jika server ada Nginx luar Docker sebagai reverse proxy:
```nginx
server {
listen 443 ssl;
server_name speech2text.mbip.my;
ssl_certificate /etc/ssl/certs/mbip.crt;
ssl_certificate_key /etc/ssl/private/mbip.key;
location / {
proxy_pass http://127.0.0.1:8080; # port Docker nginx
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_read_timeout 300s;
client_max_body_size 210M; # PRIVATE_AUDIO_MAX_MB + buffer
}
}
server {
listen 80;
server_name speech2text.mbip.my;
return 301 https://$host$request_uri;
}
```
---
## Backup
### Database Backup
```bash
# Backup manual
docker compose exec mysql mysqldump \
-u root -p$DB_PASSWORD \
speech2text > backup_$(date +%Y%m%d_%H%M%S).sql
# Compress
gzip backup_*.sql
```
### Storage Backup
```bash
# Backup fail audio (private storage)
tar -czf audio_backup_$(date +%Y%m%d).tar.gz \
/svr/speech2text/app/storage/app/private/
```
### Automated Backup (crontab)
```bash
# Edit crontab
crontab -e
# Tambah:
0 2 * * * cd /svr/speech2text && docker compose exec -T mysql \
mysqldump -u root -p$DB_PASSWORD speech2text | \
gzip > /backup/db/speech2text_$(date +\%Y\%m\%d).sql.gz
```
---
## Monitoring
```bash
# Semak status container
docker compose ps
# Lihat penggunaan resource
docker stats
# Lihat logs real-time
docker compose logs -f
# Logs spesifik service
docker compose logs -f queue-worker
docker compose logs -f transcription-worker
# Semak queue jobs pending
docker compose exec app php artisan queue:monitor
# Semak failed jobs
docker compose exec app php artisan queue:failed
```
---
## Troubleshooting
### Container tidak start
```bash
docker compose logs <service-name>
docker compose config # semak syntax docker-compose.yml
```
### Transcription gagal
```bash
# Semak transcription worker
docker compose logs transcription-worker
# Test transcription worker secara manual
docker compose exec app curl http://transcription-worker:8000/health
# Retry failed jobs
docker compose exec app php artisan queue:retry all
```
### Storage permission error
```bash
docker compose exec app chmod -R 775 storage bootstrap/cache
docker compose exec app chown -R www-data:www-data storage
```
### Database migration error
```bash
# Semak status migration
docker compose exec app php artisan migrate:status
# Rollback jika perlu
docker compose exec app php artisan migrate:rollback
```
---
## Checklist Pre-Production
- [ ] `APP_ENV=production`
- [ ] `APP_DEBUG=false`
- [ ] `APP_KEY` telah dijanakan dan disimpan dengan selamat
- [ ] Database password kuat (minimum 16 karakter, alphanumeric + simbol)
- [ ] HTTPS/TLS dikonfig
- [ ] Firewall: hanya port 80/443 terbuka dari internet
- [ ] Port 3306 (MySQL), 6379 (Redis), 8000 (transcription-worker) TIDAK terbuka dari internet
- [ ] `.env` dalam `.gitignore`
- [ ] `storage/app/private/` tidak accessible dari web
- [ ] Backup berjalan secara automatik
- [ ] Log rotation dikonfig
- [ ] Admin default password ditukar selepas login pertama
- [ ] Rate limiting aktif
- [ ] Queue worker berjalan
- [ ] Scheduler berjalan
- [ ] Test upload audio berjaya
- [ ] Test transcription berjaya
- [ ] Test authorization (admin tidak dapat akses kandungan) lulus