# 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 . ``` ### 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= ADMIN_DEFAULT_NAME= ADMIN_DEFAULT_EMAIL= ADMIN_DEFAULT_PASSWORD= ``` ### 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 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