#!/usr/bin/env bash # ╔══════════════════════════════════════════════════════════════╗ # ║ KomposIn — Non-Docker Setup untuk Azure VM ║ # ║ Instalasi: Python backend + Next.js frontend + Nginx ║ # ║ Jalankan: bash setup-nondocker.sh ║ # ╚══════════════════════════════════════════════════════════════╝ set -euo pipefail RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' BLUE='\033[0;34m'; BOLD='\033[1m'; NC='\033[0m' log() { echo -e "${BLUE}[$(date +'%H:%M:%S')]${NC} $*"; } ok() { echo -e " ${GREEN}✔${NC} $*"; } warn() { echo -e " ${YELLOW}⚠${NC} $*"; } err() { echo -e " ${RED}✘ $*${NC}"; exit 1; } echo -e "\n${BOLD}${BLUE}╔════════════════════════════════════════╗${NC}" echo -e "${BOLD}${BLUE}║ 🗑️ KomposIn Setup ║${NC}" echo -e "${BOLD}${BLUE}╚════════════════════════════════════════╝${NC}\n" # ── 0. Cek privilege ──────────────────────────────────────── [ "$EUID" -eq 0 ] || err "Script ini harus dijalankan dengan sudo" # ── 1. System update ──────────────────────────────────────── log "Update sistem..." apt-get update && apt-get upgrade -y # ── 2. Install dependencies ───────────────────────────────── log "Menginstall system libraries..." apt-get install -y \ python3.11 python3.11-venv python3-pip \ nodejs npm \ nginx \ git git-lfs \ curl wget \ build-essential libssl-dev ok "System packages terinstall" # ── 3. Setup user & direktori ─────────────────────────────── log "Setup user dan direktori..." getent passwd komposin >/dev/null 2>&1 || { useradd -m -s /bin/bash -d /home/komposin komposin ok "User komposin dibuat" } mkdir -p /opt/komposin /var/log/komposin chown -R komposin:komposin /opt/komposin /var/log/komposin chmod 0755 /opt/komposin /var/log/komposin # ── 4. Clone dan setup backend ────────────────────────────── log "Setup FastAPI backend..." cd /opt/komposin # Jika folder sudah ada, pull terbaru; jika belum, clone if [ -d "fpAI-komposin" ]; then cd fpAI-komposin git pull hf main 2>/dev/null || warn "git pull gagal" else git clone https://huggingface.co/KomposIn-Team/fpAI-komposin fpAI-komposin cd fpAI-komposin fi git lfs pull # Buat virtual environment Python cd /opt/komposin/fpAI-komposin/be [ -d "venv" ] && rm -rf venv python3.11 -m venv venv source venv/bin/activate # Install Python dependencies (CPU-only torch) pip install --upgrade pip pip install --extra-index-url https://download.pytorch.org/whl/cpu torch torchvision pip install -r requirements.txt ok "FastAPI backend ready" # ── 5. Setup frontend ─────────────────────────────────────── log "Setup Next.js frontend..." cd /opt/komposin/fpAI-komposin/fe # Cek dan set next.config.ts jika belum ada output: standalone if ! grep -q "output.*standalone" next.config.ts 2>/dev/null; then warn "next.config.ts belum punya output: 'standalone'" warn "Tambahkan baris ini ke next.config.ts:" warn " output: 'standalone'," fi npm install npm run build ok "Next.js frontend build selesai" # ── 6. Setup Nginx ────────────────────────────────────────── log "Setup Nginx..." cat > /etc/nginx/sites-available/komposin <<'EOF' upstream backend { server 127.0.0.1:8000; keepalive 16; } upstream frontend { server 127.0.0.1:3000; keepalive 32; } server { listen 80 default_server; server_name _; client_max_body_size 20M; # Rate limiting limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=web:10m rate=30r/s; # API proxy location /api/ { limit_req zone=api burst=30 nodelay; rewrite ^/api/(.*) /$1 break; proxy_pass http://backend; proxy_http_version 1.1; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 180s; proxy_connect_timeout 10s; proxy_send_timeout 60s; } # Frontend proxy location / { limit_req zone=web burst=50 nodelay; proxy_pass http://frontend; proxy_http_version 1.1; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 60s; } } EOF # Enable site dan disable default ln -sf /etc/nginx/sites-available/komposin /etc/nginx/sites-enabled/ rm -f /etc/nginx/sites-enabled/default # Test & restart nginx -t || err "Nginx config error" systemctl enable nginx systemctl restart nginx ok "Nginx configured dan running" # ── 7. Buat systemd units ────────────────────────────────── log "Setup systemd services..." # Backend unit cat > /etc/systemd/system/komposin-backend.service < /etc/systemd/system/komposin-frontend.service </dev/null 2>&1 && BACKEND_OK=true || true curl -f http://127.0.0.1:3000 >/dev/null 2>&1 && FRONTEND_OK=true || true [ "$BACKEND_OK" = true ] && ok "Backend responding" || warn "Backend tidak respond" [ "$FRONTEND_OK" = true ] && ok "Frontend responding" || warn "Frontend tidak respond" # ── Final status ─────────────────────────────────────────── PUBLIC_IP=$(curl -s --max-time 5 ifconfig.me 2>/dev/null || \ curl -s --max-time 5 api.ipify.org 2>/dev/null || \ hostname -I | awk '{print $1}') echo "" echo -e "\n${GREEN}${BOLD}════════════════════════════════════════════${NC}" echo -e "${GREEN}${BOLD} ✅ KomposIn Non-Docker siap!${NC}" echo -e "${GREEN}${BOLD}════════════════════════════════════════════${NC}\n" echo -e " 🌐 Aplikasi : ${GREEN}http://${PUBLIC_IP}${NC}" echo -e " 📡 API Docs : ${GREEN}http://${PUBLIC_IP}/api/docs${NC}" echo -e " 📁 Project dir : ${GREEN}/opt/komposin/fpAI-komposin${NC}" echo -e " 🔍 Backend log : journalctl -u komposin-backend.service -f" echo -e " 🔍 Frontend log: journalctl -u komposin-frontend.service -f" echo -e " 🔄 Restart : systemctl restart komposin-{backend,frontend}.service" echo -e " 🛑 Stop : systemctl stop komposin-{backend,frontend}.service\n" echo -e "${YELLOW}Pastikan port 80 sudah dibuka di Azure NSG (Network Security Group)!${NC}" echo -e "${YELLOW}Buka: portal.azure.com → VM → Networking → Add inbound rule → Port 80${NC}\n"