319 lines
7.1 KiB
Markdown
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
|