#!/bin/bash # Copyright (c) 2024-2025 Тарабанов Александр Викторович # All rights reserved. # # This software is proprietary and confidential. # Unauthorized copying, modification, or distribution is prohibited. # # For licensing inquiries: info@hb3-accelerator.com # Website: https://hb3-accelerator.com # GitHub: https://github.com/VC-HB3-Accelerator #!/bin/bash # Скрипт для полной миграции приложения между провайдерами # Использование: ./migrate-app.sh source-server target-server app-path set -e # Остановка при ошибке # Цвета для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Функции для логирования log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Проверка аргументов if [ $# -ne 3 ]; then echo "Использование: $0 " echo "Пример: $0 user@hostland-server.com user@aws-server.com /home/user/dapp" exit 1 fi SOURCE_SERVER=$1 TARGET_SERVER=$2 APP_PATH=$3 BACKUP_NAME="app-migration-$(date +%Y%m%d-%H%M%S)" log_info "Начинаем миграцию приложения" log_info "Источник: $SOURCE_SERVER:$APP_PATH" log_info "Цель: $TARGET_SERVER:$APP_PATH" log_info "Резервная копия: $BACKUP_NAME" # Функция для проверки подключения к серверу check_connection() { local server=$1 log_info "Проверяем подключение к $server..." if ! ssh -o ConnectTimeout=10 -o BatchMode=yes "$server" "echo 'Connection OK'" 2>/dev/null; then log_error "Не удалось подключиться к $server" log_error "Убедитесь, что SSH ключи настроены правильно" exit 1 fi log_success "Подключение к $server установлено" } # Функция для проверки Docker на сервере check_docker() { local server=$1 log_info "Проверяем Docker на $server..." if ! ssh "$server" "docker --version" >/dev/null 2>&1; then log_error "Docker не установлен на $server" log_error "Установите Docker: curl -fsSL https://get.docker.com | sh" exit 1 fi log_success "Docker установлен на $server" } # Функция для создания полного бэкапа create_backup() { local server=$1 local path=$2 local backup_name=$3 log_info "Создаём полный бэкап на $server..." # Останавливаем приложение log_info "Останавливаем приложение..." ssh "$server" "cd $path && docker compose down" || log_warning "Приложение уже остановлено" # Создаём бэкап базы данных log_info "Создаём бэкап PostgreSQL..." ssh "$server" "cd $path && docker compose up -d postgres" || true sleep 5 # Ждём запуска PostgreSQL # Бэкап PostgreSQL ssh "$server" "cd $path && docker compose exec -T postgres pg_dump -U dapp_user dapp_db > postgres-backup.sql" || { log_warning "Не удалось создать бэкап PostgreSQL, продолжаем без него" } # Бэкап Ollama моделей log_info "Создаём бэкап Ollama моделей..." ssh "$server" "cd $path && docker compose exec -T ollama ollama list > ollama-models.txt" || log_warning "Ollama не найден" # Создаём полный архив log_info "Создаём полный архив приложения..." ssh "$server" "cd $path && tar -czf $backup_name.tar.gz \ . \ postgres-backup.sql \ ollama-models.txt \ --exclude='node_modules' \ --exclude='.git' \ --exclude='*.log' \ --exclude='temp' \ --exclude='sessions'" log_success "Бэкап создан: $backup_name.tar.gz" } # Функция для восстановления на целевом сервере restore_backup() { local server=$1 local path=$2 local backup_name=$3 log_info "Восстанавливаем приложение на $server..." # Создаём директорию если не существует ssh "$server" "mkdir -p $path" # Копируем архив log_info "Копируем архив на целевой сервер..." scp "$SOURCE_SERVER:$APP_PATH/$backup_name.tar.gz" "$server:/tmp/" # Распаковываем log_info "Распаковываем архив..." ssh "$server" "cd $path && tar -xzf /tmp/$backup_name.tar.gz" # Восстанавливаем PostgreSQL if ssh "$server" "test -f $path/postgres-backup.sql"; then log_info "Восстанавливаем PostgreSQL..." ssh "$server" "cd $path && docker compose up -d postgres" sleep 10 # Ждём запуска PostgreSQL ssh "$server" "cd $path && docker compose exec -T postgres psql -U dapp_user -d dapp_db < postgres-backup.sql" || { log_warning "Не удалось восстановить PostgreSQL, создаём новую БД" ssh "$server" "cd $path && docker compose exec -T postgres createdb -U dapp_user dapp_db 2>/dev/null || true" } fi # Восстанавливаем Ollama модели if ssh "$server" "test -f $path/ollama-models.txt"; then log_info "Восстанавливаем Ollama модели..." ssh "$server" "cd $path && docker compose up -d ollama" sleep 10 # Ждём запуска Ollama ssh "$server" "cd $path && cat ollama-models.txt | grep -v 'NAME' | awk '{print \$1}' | xargs -I {} docker compose exec -T ollama ollama pull {}" || { log_warning "Не удалось восстановить все Ollama модели" } fi # Запускаем приложение log_info "Запускаем приложение..." ssh "$server" "cd $path && docker compose up -d" log_success "Приложение восстановлено на $server" } # Функция для проверки статуса приложения check_app_status() { local server=$1 local path=$2 log_info "Проверяем статус приложения на $server..." # Проверяем контейнеры ssh "$server" "cd $path && docker compose ps" # Проверяем логи log_info "Последние логи приложения:" ssh "$server" "cd $path && docker compose logs --tail=20" # Проверяем доступность сервисов log_info "Проверяем доступность сервисов..." # Получаем IP сервера SERVER_IP=$(ssh "$server" "curl -s ifconfig.me") # Проверяем порты for port in 80 443 8000 5173; do if ssh "$server" "netstat -tlnp | grep :$port" >/dev/null 2>&1; then log_success "Порт $port доступен" else log_warning "Порт $port недоступен" fi done } # Функция для очистки временных файлов cleanup() { local server=$1 local backup_name=$2 log_info "Очищаем временные файлы..." ssh "$server" "rm -f $APP_PATH/$backup_name.tar.gz" ssh "$server" "rm -f $APP_PATH/postgres-backup.sql" ssh "$server" "rm -f $APP_PATH/ollama-models.txt" ssh "$server" "rm -f /tmp/$backup_name.tar.gz" } # Основной процесс миграции main() { log_info "=== НАЧАЛО МИГРАЦИИ ПРИЛОЖЕНИЯ ===" # Проверяем подключения check_connection "$SOURCE_SERVER" check_connection "$TARGET_SERVER" # Проверяем Docker check_docker "$SOURCE_SERVER" check_docker "$TARGET_SERVER" # Создаём бэкап на исходном сервере create_backup "$SOURCE_SERVER" "$APP_PATH" "$BACKUP_NAME" # Восстанавливаем на целевом сервере restore_backup "$TARGET_SERVER" "$APP_PATH" "$BACKUP_NAME" # Проверяем статус check_app_status "$TARGET_SERVER" "$APP_PATH" # Очищаем временные файлы cleanup "$SOURCE_SERVER" "$BACKUP_NAME" cleanup "$TARGET_SERVER" "$BACKUP_NAME" log_success "=== МИГРАЦИЯ ЗАВЕРШЕНА УСПЕШНО ===" log_info "Приложение перенесено с $SOURCE_SERVER на $TARGET_SERVER" log_info "Не забудьте обновить DNS записи на новый IP сервера" # Показываем новый IP NEW_IP=$(ssh "$TARGET_SERVER" "curl -s ifconfig.me") log_info "Новый IP сервера: $NEW_IP" } # Обработка ошибок trap 'log_error "Миграция прервана из-за ошибки"; exit 1' ERR # Запуск основной функции main "$@"