#!/bin/bash ############################################################################### # Oltalama Test Yönetim Paneli - Otomatik Kurulum Scripti # Version: 1.0.0 # Date: 2025-11-10 ############################################################################### set -e # Exit on error # Renkli çıktılar RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Değişkenler INSTALL_DIR="/opt/oltalama" LOG_DIR="/var/log/oltalama" BACKUP_DIR="${INSTALL_DIR}/backups" USER="oltalama" # Tüm sistemler için ortak kullanıcı NODE_VERSION="20" # Fonksiyonlar print_header() { echo -e "\n${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${BLUE}║ ║${NC}" echo -e "${BLUE}║ Oltalama Test Yönetim Paneli - Kurulum Scripti ║${NC}" echo -e "${BLUE}║ Version 1.0.0 ║${NC}" echo -e "${BLUE}║ ║${NC}" echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}\n" } print_success() { echo -e "${GREEN}✓ $1${NC}" } print_error() { echo -e "${RED}✗ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠ $1${NC}" } print_info() { echo -e "${BLUE}ℹ $1${NC}" } check_root() { if [[ $EUID -ne 0 ]]; then print_error "Bu script root yetkisi ile çalıştırılmalıdır." print_info "Lütfen 'sudo ./deploy.sh' komutunu kullanın." exit 1 fi } check_os() { if [[ -f /etc/os-release ]]; then . /etc/os-release OS=$ID VERSION=$VERSION_ID print_success "İşletim sistemi tespit edildi: $PRETTY_NAME" # Paket yöneticisi tespit et if command -v apt-get &> /dev/null; then PKG_MANAGER="apt" print_info "Paket yöneticisi: APT (Debian/Ubuntu)" elif command -v dnf &> /dev/null; then PKG_MANAGER="dnf" print_info "Paket yöneticisi: DNF (RedHat/Oracle/Fedora)" elif command -v yum &> /dev/null; then PKG_MANAGER="yum" print_info "Paket yöneticisi: YUM (RedHat/CentOS)" else print_error "Desteklenen paket yöneticisi bulunamadı!" exit 1 fi else print_error "İşletim sistemi tespit edilemedi!" exit 1 fi } install_nodejs() { print_info "Node.js ${NODE_VERSION}.x kuruluyor..." if command -v node &> /dev/null; then CURRENT_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [[ $CURRENT_VERSION -ge $NODE_VERSION ]]; then print_success "Node.js $(node -v) zaten yüklü." return fi fi # NodeSource repository ekle if [[ "$PKG_MANAGER" == "apt" ]]; then curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - apt-get install -y nodejs elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash - $PKG_MANAGER install -y nodejs fi print_success "Node.js $(node -v) kuruldu." print_success "npm $(npm -v) kuruldu." } install_dependencies() { print_info "Sistem bağımlılıkları kuruluyor..." if [[ "$PKG_MANAGER" == "apt" ]]; then apt-get update apt-get install -y git curl wget build-essential sqlite3 elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then $PKG_MANAGER update -y # EPEL repository (bazı paketler için gerekli) $PKG_MANAGER install -y epel-release 2>/dev/null || true # Paketleri kur $PKG_MANAGER install -y git curl wget gcc-c++ make sqlite # Development tools $PKG_MANAGER groupinstall -y "Development Tools" 2>/dev/null || true fi print_success "Sistem bağımlılıkları kuruldu." } install_pm2() { print_info "PM2 process manager kuruluyor..." npm install -g pm2 print_success "PM2 $(pm2 -v) kuruldu." } setup_directories() { print_info "Dizinler oluşturuluyor..." mkdir -p $LOG_DIR mkdir -p $BACKUP_DIR mkdir -p "${INSTALL_DIR}/backend/database" print_success "Dizinler oluşturuldu." } create_user() { print_info "Sistem kullanıcısı kontrol ediliyor..." if id "$USER" &>/dev/null; then print_success "Kullanıcı '$USER' zaten mevcut." else print_info "Kullanıcı '$USER' oluşturuluyor..." useradd -r -s /bin/bash -d $INSTALL_DIR -m $USER print_success "Kullanıcı '$USER' oluşturuldu." fi } install_project() { print_info "Proje dosyaları kontrol ediliyor..." # Eğer script zaten proje dizininde çalıştırılıyorsa if [[ -f "$(pwd)/backend/package.json" ]]; then CURRENT_DIR=$(pwd) print_info "Mevcut dizinden kurulum yapılıyor: $CURRENT_DIR" if [[ "$CURRENT_DIR" != "$INSTALL_DIR" ]]; then print_info "Dosyalar $INSTALL_DIR dizinine kopyalanıyor..." # rsync yerine cp kullan (daha yaygın) # Önce .git ve node_modules hariç tüm dosyaları kopyala find "$CURRENT_DIR" -mindepth 1 -maxdepth 1 \ ! -name 'node_modules' \ ! -name '.git' \ ! -name 'logs' \ ! -name 'database' \ -exec cp -r {} "$INSTALL_DIR/" \; print_success "Dosyalar kopyalandı." fi else print_error "Proje dosyaları bulunamadı!" print_info "Script'i proje dizininde çalıştırın veya projeyi klonlayın." exit 1 fi print_success "Proje dosyaları hazır." } install_backend() { print_info "Backend dependencies kuruluyor..." cd "${INSTALL_DIR}/backend" npm install --production print_success "Backend dependencies kuruldu." } install_frontend() { print_info "Frontend dependencies kuruluyor..." cd "${INSTALL_DIR}/frontend" npm install print_success "Frontend dependencies kuruldu." } setup_env_files() { print_info "Çevre değişkenleri ayarlanıyor..." # Backend .env if [[ ! -f "${INSTALL_DIR}/backend/.env" ]]; then cp "${INSTALL_DIR}/backend/.env.example" "${INSTALL_DIR}/backend/.env" # Session secret oluştur SESSION_SECRET=$(node -e "console.log(require('crypto').randomBytes(64).toString('hex'))") # .env dosyasını güncelle sed -i "s|NODE_ENV=development|NODE_ENV=production|g" "${INSTALL_DIR}/backend/.env" sed -i "s|SESSION_SECRET=.*|SESSION_SECRET=${SESSION_SECRET}|g" "${INSTALL_DIR}/backend/.env" sed -i "s|DB_PATH=.*|DB_PATH=${INSTALL_DIR}/backend/database/oltalama.db|g" "${INSTALL_DIR}/backend/.env" print_success "Backend .env dosyası oluşturuldu." print_warning "Gmail ve Telegram ayarlarını panelden yapabilirsiniz." else print_info "Backend .env dosyası zaten mevcut." fi # Frontend .env if [[ ! -f "${INSTALL_DIR}/frontend/.env" ]]; then cp "${INSTALL_DIR}/frontend/.env.example" "${INSTALL_DIR}/frontend/.env" print_success "Frontend .env dosyası oluşturuldu." else print_info "Frontend .env dosyası zaten mevcut." fi } setup_admin_user() { print_info "Admin kullanıcısı oluşturuluyor..." # Check if admin already exists ADMIN_COUNT=$(sqlite3 "${INSTALL_DIR}/backend/database/oltalama.db" "SELECT COUNT(*) FROM admin_user;" 2>/dev/null || echo "0") if [[ "$ADMIN_COUNT" -gt 0 ]]; then print_info "Admin kullanıcısı zaten mevcut, atlanıyor." return fi echo "" print_warning "╔═══════════════════════════════════════════════════════════════╗" print_warning "║ Admin Kullanıcı Bilgilerini Oluşturun ║" print_warning "╚═══════════════════════════════════════════════════════════════╝" echo "" # Username while true; do read -p "Admin kullanıcı adı (en az 3 karakter): " ADMIN_USERNAME if [[ ${#ADMIN_USERNAME} -ge 3 ]]; then break else print_error "Kullanıcı adı en az 3 karakter olmalıdır!" fi done # Password with validation while true; do read -sp "Admin şifresi (en az 8 karakter, harf ve rakam içermeli): " ADMIN_PASSWORD echo "" # Password length check if [[ ${#ADMIN_PASSWORD} -lt 8 ]]; then print_error "Şifre en az 8 karakter olmalıdır!" continue fi # Check for letters and numbers if ! [[ "$ADMIN_PASSWORD" =~ [a-zA-Z] ]] || ! [[ "$ADMIN_PASSWORD" =~ [0-9] ]]; then print_error "Şifre hem harf hem de rakam içermelidir!" continue fi # Confirm password read -sp "Şifreyi tekrar girin: " ADMIN_PASSWORD_CONFIRM echo "" if [[ "$ADMIN_PASSWORD" == "$ADMIN_PASSWORD_CONFIRM" ]]; then break else print_error "Şifreler eşleşmiyor! Tekrar deneyin." fi done # Create admin user using Node.js cd "${INSTALL_DIR}/backend" cat > /tmp/create_admin.js << EOF const bcrypt = require('bcrypt'); const { sequelize } = require('./src/config/database'); const AdminUser = require('./src/models/AdminUser'); (async () => { try { await sequelize.authenticate(); const hashedPassword = await bcrypt.hash('${ADMIN_PASSWORD}', 10); await AdminUser.create({ username: '${ADMIN_USERNAME}', password_hash: hashedPassword, email: null, full_name: 'Administrator', }); console.log('✓ Admin kullanıcısı oluşturuldu'); process.exit(0); } catch (error) { console.error('✗ Hata:', error.message); process.exit(1); } })(); EOF node /tmp/create_admin.js rm -f /tmp/create_admin.js print_success "Admin kullanıcısı oluşturuldu: ${ADMIN_USERNAME}" echo "" } setup_database() { print_info "Database oluşturuluyor..." cd "${INSTALL_DIR}/backend" # Migrations node migrations/run-migrations.js print_success "Database migrations tamamlandı." # Seed sample data (companies and templates only, not admin user) ADMIN_COUNT=$(sqlite3 "${INSTALL_DIR}/backend/database/oltalama.db" "SELECT COUNT(*) FROM admin_user;" 2>/dev/null || echo "0") if [[ "$ADMIN_COUNT" -eq 0 ]]; then # Seed only non-admin data (create script in backend directory) cat > "${INSTALL_DIR}/backend/seed_data_temp.js" << 'EOF' const { sequelize } = require('./src/config/database'); const { Company, MailTemplate } = require('./src/models'); (async () => { try { await sequelize.authenticate(); // Seed companies const companies = [ { name: 'Türk Telekom', domain: 'turktelekom.com.tr', description: 'Türkiye\'nin lider telekomünikasyon şirketi' }, { name: 'İş Bankası', domain: 'isbank.com.tr', description: 'Türkiye\'nin en büyük özel sermayeli bankası' }, { name: 'PTT', domain: 'ptt.gov.tr', description: 'Posta ve Telgraf Teşkilatı' }, ]; for (const company of companies) { await Company.findOrCreate({ where: { name: company.name }, defaults: company }); } // Seed templates const templates = [ { name: 'Banka Güvenlik Uyarısı', template_type: 'bank', subject_template: '🔒 {{company_name}} - Hesap Güvenlik Uyarısı', body_html: '

🔒 Güvenlik Uyarısı

Sayın {{employee_name}},

{{company_name}} hesabınızda şüpheli bir aktivite tespit edildi. Hesabınızın güvenliğini sağlamak için lütfen aşağıdaki bağlantıya tıklayarak kimlik doğrulaması yapın.

Hesabımı Doğrula

Bu işlemi 24 saat içinde yapmazsanız hesabınız geçici olarak askıya alınabilir.

Tarih: {{current_date}}


Bu bir phishing testidir. Gerçek bir güvenlik tehdidi değildir.

', description: 'Banka hesap güvenliği temalı phishing test maili', active: true, }, { name: 'E-Devlet Sistem Güncellemesi', template_type: 'edevlet', subject_template: '⚠️ E-Devlet - Sistem Güncellemesi Gerekli', body_html: '

E-DEVLET KAPISI

Sayın {{employee_name}},

E-Devlet sistemimizde önemli bir güvenlik güncellemesi yapılmaktadır. Hesabınıza erişiminizi sürdürebilmek için lütfen kimlik bilgilerinizi güncelleyin.

Bilgilerimi Güncelle

⚠️ Bu işlemi 48 saat içinde tamamlamazsanız E-Devlet hesabınız askıya alınacaktır.

İşlem Tarihi: {{current_date}}

Bu bir phishing farkındalık testidir.

© {{current_year}} E-Devlet Kapısı

', description: 'E-Devlet sistem güncellemesi temalı phishing test maili', active: true, }, ]; for (const template of templates) { await MailTemplate.findOrCreate({ where: { template_type: template.template_type }, defaults: template }); } console.log('✓ Örnek veriler oluşturuldu'); process.exit(0); } catch (error) { console.error('✗ Hata:', error.message); process.exit(1); } })(); EOF cd "${INSTALL_DIR}/backend" node seed_data_temp.js rm -f seed_data_temp.js print_success "Örnek veriler oluşturuldu (şirketler ve mail şablonları)." else print_info "Database zaten veri içeriyor, seed atlanıyor." fi } build_frontend() { print_info "Frontend build ediliyor..." cd "${INSTALL_DIR}/frontend" npm run build print_success "Frontend build tamamlandı." } setup_pm2() { print_info "PM2 konfigürasyonu yapılıyor..." # ecosystem.config.js oluştur cat > "${INSTALL_DIR}/ecosystem.config.js" << 'EOF' module.exports = { apps: [ { name: 'oltalama-backend', cwd: '/opt/oltalama/backend', script: 'src/app.js', instances: 1, exec_mode: 'cluster', watch: false, max_memory_restart: '500M', env: { NODE_ENV: 'production', PORT: 3000, }, error_file: '/var/log/oltalama/backend-error.log', out_file: '/var/log/oltalama/backend-out.log', log_date_format: 'YYYY-MM-DD HH:mm:ss Z', }, { name: 'oltalama-frontend', cwd: '/opt/oltalama/frontend', script: 'npm', args: 'run preview', instances: 1, exec_mode: 'fork', watch: false, max_memory_restart: '300M', env: { NODE_ENV: 'production', PORT: 4173, }, error_file: '/var/log/oltalama/frontend-error.log', out_file: '/var/log/oltalama/frontend-out.log', log_date_format: 'YYYY-MM-DD HH:mm:ss Z', }, ], }; EOF print_success "PM2 konfigürasyon dosyası oluşturuldu." } start_services() { print_info "Servisler başlatılıyor..." cd "${INSTALL_DIR}" # PM2 ile başlat pm2 start ecosystem.config.js # Startup script oluştur pm2 startup systemd -u root --hp /root pm2 save print_success "Servisler başlatıldı." # Durum göster sleep 2 pm2 status } setup_permissions() { print_info "Dosya izinleri ayarlanıyor..." # Dizin sahipliği chown -R ${USER}:${USER} ${INSTALL_DIR} chown -R ${USER}:${USER} ${LOG_DIR} # .env dosyaları chmod 600 "${INSTALL_DIR}/backend/.env" chmod 600 "${INSTALL_DIR}/frontend/.env" # Database chmod 600 "${INSTALL_DIR}/backend/database/oltalama.db" print_success "Dosya izinleri ayarlandı." } setup_firewall() { print_info "Firewall ayarlanıyor..." if command -v ufw &> /dev/null; then # Ubuntu/Debian - UFW print_info "UFW kullanılıyor..." # SSH izin ver ufw allow 22/tcp comment 'SSH' # HTTP/HTTPS izin ver ufw allow 80/tcp comment 'HTTP' ufw allow 443/tcp comment 'HTTPS' # Backend ve Frontend portlarını engelle (sadece localhost'tan erişilebilir) ufw deny 3000/tcp comment 'Oltalama Backend (use reverse proxy)' ufw deny 4173/tcp comment 'Oltalama Frontend (use reverse proxy)' # UFW'yi aktifleştir (sadece henüz aktif değilse) if ! ufw status | grep -q "Status: active"; then print_warning "UFW firewall aktifleştiriliyor..." print_warning "SSH bağlantınız kopmayacak (port 22 açık)." read -p "Devam etmek için ENTER'a basın..." echo "y" | ufw enable fi print_success "Firewall ayarlandı (UFW)." elif command -v firewall-cmd &> /dev/null; then # RedHat/Oracle/CentOS - firewalld print_info "firewalld kullanılıyor..." # firewalld'yi başlat ve aktifleştir systemctl start firewalld 2>/dev/null || true systemctl enable firewalld 2>/dev/null || true # HTTP/HTTPS izin ver firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --permanent --add-service=ssh # Backend ve Frontend portları sadece localhost'tan erişilebilir # (reverse proxy kullanılacağı için dışarıdan erişim kapalı) # Yeniden yükle firewall-cmd --reload print_success "Firewall ayarlandı (firewalld)." else print_warning "Firewall bulunamadı, firewall ayarları atlanıyor." print_warning "Güvenlik için manuel olarak firewall yapılandırmanız önerilir." fi } setup_backup_cron() { print_info "Otomatik yedekleme ayarlanıyor..." # Backup script oluştur cat > "${INSTALL_DIR}/backup.sh" << 'EOF' #!/bin/bash BACKUP_DIR="/opt/oltalama/backups" DB_PATH="/opt/oltalama/backend/database/oltalama.db" DATE=$(date +%Y%m%d-%H%M%S) mkdir -p $BACKUP_DIR cp $DB_PATH "$BACKUP_DIR/oltalama-$DATE.db" find $BACKUP_DIR -name "oltalama-*.db" -mtime +30 -delete echo "Backup completed: oltalama-$DATE.db" EOF chmod +x "${INSTALL_DIR}/backup.sh" # Crontab ekle CRON_JOB="0 3 * * * ${INSTALL_DIR}/backup.sh >> ${LOG_DIR}/backup.log 2>&1" (crontab -l 2>/dev/null | grep -v "backup.sh"; echo "$CRON_JOB") | crontab - print_success "Otomatik yedekleme ayarlandı (her gün saat 03:00)." } print_completion() { echo -e "\n${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}║ 🎉 Kurulum Tamamlandı! 🎉 ║${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}\n" print_info "Servis Bilgileri:" echo -e " Backend: ${BLUE}http://localhost:3000${NC}" echo -e " Frontend: ${BLUE}http://localhost:4173${NC}" print_info "\nAdmin Hesabı:" echo -e " ${GREEN}✓${NC} Kurulum sırasında oluşturuldu" echo -e " ${GREEN}✓${NC} Güvenli şifre kullanıldı" print_info "\nYapılması Gerekenler:" echo " 1. Nginx Proxy Manager'da reverse proxy ayarları yapın" echo " 2. Frontend için: yourdomain.com → localhost:4173" echo " 3. Backend API için path: /api → localhost:3000" echo " 4. SSL sertifikası ekleyin" echo " 5. Panele giriş yapın ve Gmail/Telegram ayarlarını yapın" print_info "\nYararlı Komutlar:" echo " Servis durumu: pm2 status" echo " Logları izle: pm2 logs" echo " Servis yeniden başlat: pm2 restart all" echo " Servis durdur: pm2 stop all" print_info "\nDokümantasyon:" echo " Detaylı kurulum kılavuzu: ${INSTALL_DIR}/DEPLOYMENT.md" echo " Kullanım kılavuzu: ${INSTALL_DIR}/KULLANIM.md" echo " Hızlı başlangıç: ${INSTALL_DIR}/QUICKSTART.md" print_success "\nKurulum başarıyla tamamlandı!" } # Ana kurulum fonksiyonu main() { print_header check_root check_os print_info "Kurulum başlıyor...\n" install_dependencies install_nodejs install_pm2 create_user setup_directories install_project install_backend install_frontend setup_env_files setup_database setup_admin_user build_frontend setup_pm2 setup_permissions start_services setup_firewall setup_backup_cron print_completion } # Script'i çalıştır main "$@"