Ver Fonte

Добавлен deploy-remote.sh для удалённого деплоя на тестовый сервер

- Автоклонирование/обновление репозитория
- Автогенерация секретов (DB_PASSWORD, REDIS_PASSWORD, JWT_SECRET, JWT_REFRESH_SECRET, S3_SECRET_KEY)
- Проверка обязательных переменных (YANDEX_MAPS_API_KEY и т.д.)
- Docker secrets для Swarm mode
- Health checks через Caddy + HTTPS (Synology)
- Вывод итоговых URL
neyrogovnarik há 1 mês atrás
pai
commit
f801e1edb5
1 ficheiros alterados com 218 adições e 0 exclusões
  1. 218 0
      deploy/deploy-remote.sh

+ 218 - 0
deploy/deploy-remote.sh

@@ -0,0 +1,218 @@
+#!/usr/bin/env bash
+# ===========================================
+# PhotoPlaces — Удалённый деплой на тестовый сервер
+# ===========================================
+# Запуск на сервере 192.168.88.128:
+#   curl -fsSL https://raw.githubusercontent.com/foxtime/photoplaces/main/deploy/deploy-remote.sh | bash
+# Или склонировав репо и запустив:
+#   cd /home/foxtime/photoplaces && bash deploy/deploy-remote.sh
+# ===========================================
+
+set -euo pipefail
+
+# Цвета для вывода
+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} $*"; }
+log_ok() { echo -e "${GREEN}[OK]${NC} $*"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
+log_err() { echo -e "${RED}[ERR]${NC} $*"; }
+
+# Конфигурация
+REPO_URL="http://192.168.88.96:10880/foxtime/photoplaces.git"
+PROJECT_DIR="/home/foxtime/photoplaces"
+BRANCH="main"
+ENV_FILE="$PROJECT_DIR/deploy/env.prod"
+
+log_info "=== PhotoPlaces Remote Deploy ==="
+log_info "Сервер: $(hostname) ($(hostname -I | awk '{print $1}'))"
+log_info "Пользователь: $(whoami)"
+log_info "Директория: $PROJECT_DIR"
+
+# 1. Проверка зависимостей
+check_deps() {
+    log_info "Проверка зависимостей..."
+    local missing=()
+    for cmd in docker git curl openssl; do
+        if ! command -v "$cmd" >/dev/null 2>&1; then
+            missing+=("$cmd")
+        fi
+    done
+    if ! docker compose version >/dev/null 2>&1; then
+        missing+=("docker compose")
+    fi
+
+    if [ ${#missing[@]} -gt 0 ]; then
+        log_err "Отсутствуют: ${missing[*]}"
+        log_info "Установите: sudo apt update && sudo apt install -y docker.io docker-compose-plugin git curl openssl"
+        exit 1
+    fi
+    log_ok "Все зависимости установлены"
+}
+
+# 2. Клонирование/обновление репозитория
+setup_repo() {
+    log_info "Настройка репозитория..."
+    if [ -d "$PROJECT_DIR/.git" ]; then
+        log_info "Репозиторий существует, обновляю..."
+        cd "$PROJECT_DIR"
+        git fetch origin
+        git reset --hard "origin/$BRANCH"
+        git clean -fd
+    else
+        log_info "Клонирую репозиторий..."
+        git clone --branch "$BRANCH" "$REPO_URL" "$PROJECT_DIR"
+        cd "$PROJECT_DIR"
+    fi
+    log_ok "Репозиторий готов: $(git rev-parse --short HEAD)"
+}
+
+# 3. Настройка env.prod
+setup_env() {
+    log_info "Настройка переменных окружения..."
+    cd "$PROJECT_DIR"
+
+    if [ ! -f "$ENV_FILE" ]; then
+        cp deploy/env.prod.example "$ENV_FILE"
+        log_info "Создан $ENV_FILE из шаблона"
+    fi
+
+    # Автогенерация секретов если пустые или CHANGE_ME
+    generate_secret() {
+        local var="$1"
+        local current="${!var:-}"
+        if [[ -z "$current" || "$current" == *"CHANGE_ME"* ]]; then
+            local secret
+            secret=$(openssl rand -hex 32)
+            if [[ "$OSTYPE" == "darwin"* ]]; then
+                sed -i '' "s/^${var}=.*/${var}=${secret}/" "$ENV_FILE"
+            else
+                sed -i "s/^${var}=.*/${var}=${secret}/" "$ENV_FILE"
+            fi
+            export "$var=$secret"
+            log_ok "$var сгенерирован автоматически"
+        fi
+    }
+
+    # Загружаем текущие значения
+    set -a
+    source "$ENV_FILE"
+    set +a
+
+    generate_secret "DB_PASSWORD"
+    generate_secret "REDIS_PASSWORD"
+    generate_secret "JWT_SECRET"
+    generate_secret "JWT_REFRESH_SECRET"
+    generate_secret "S3_SECRET_KEY"
+
+    # Проверка обязательных переменных
+    local required=("DB_PASSWORD" "REDIS_PASSWORD" "JWT_SECRET" "JWT_REFRESH_SECRET" "S3_SECRET_KEY" "YANDEX_MAPS_API_KEY")
+    local missing=()
+    for var in "${required[@]}"; do
+        if [ -z "${!var:-}" ]; then
+            missing+=("$var")
+        fi
+    done
+
+    if [ ${#missing[@]} -gt 0 ]; then
+        log_warn "Требуют ручного заполнения в $ENV_FILE:"
+        for var in "${missing[@]}"; do
+            echo "  - $var"
+        done
+        log_info "Откройте $ENV_FILE и заполните недостающие значения, затем запустите скрипт снова"
+        exit 1
+    fi
+
+    log_ok "Все секреты настроены"
+}
+
+# 4. Создание Docker secrets (если Swarm)
+create_docker_secrets() {
+    if docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
+        log_info "Swarm mode: создание Docker secrets..."
+        printf "%s" "$DB_PASSWORD" | docker secret create db_password - 2>/dev/null || docker secret rm db_password && printf "%s" "$DB_PASSWORD" | docker secret create db_password -
+        printf "%s" "$REDIS_PASSWORD" | docker secret create redis_password - 2>/dev/null || docker secret rm redis_password && printf "%s" "$REDIS_PASSWORD" | docker secret create redis_password -
+        printf "%s" "$JWT_SECRET" | docker secret create jwt_secret - 2>/dev/null || docker secret rm jwt_secret && printf "%s" "$JWT_SECRET" | docker secret create jwt_secret -
+        printf "%s" "$JWT_REFRESH_SECRET" | docker secret create jwt_refresh_secret - 2>/dev/null || docker secret rm jwt_refresh_secret && printf "%s" "$JWT_REFRESH_SECRET" | docker secret create jwt_refresh_secret -
+        printf "%s" "$S3_SECRET_KEY" | docker secret create s3_secret_key - 2>/dev/null || docker secret rm s3_secret_key && printf "%s" "$S3_SECRET_KEY" | docker secret create s3_secret_key -
+        log_ok "Docker secrets созданы"
+    fi
+}
+
+# 5. Деплой через docker compose
+deploy() {
+    log_info "Запуск docker compose..."
+    cd "$PROJECT_DIR"
+    docker compose -f deploy/docker-compose.prod.yml up -d --build --remove-orphans
+    log_ok "Контейнеры запущены"
+}
+
+# 6. Health checks
+health_check() {
+    log_info "Ожидание готовности сервисов (до 120 сек)..."
+    local max_attempts=60
+    local attempt=0
+
+    while [ $attempt -lt $max_attempts ]; do
+        attempt=$((attempt + 1))
+
+        # Проверка Caddy (порт 2019 metrics)
+        if docker compose -f deploy/docker-compose.prod.yml exec -T caddy wget -q --spider http://localhost:2019/metrics 2>/dev/null; then
+            # Проверка backend через Caddy (HTTP, SSL на Synology)
+            if curl -sf "http://localhost/api/v1/health" >/dev/null 2>&1; then
+                log_ok "Backend здоров"
+                break
+            fi
+        fi
+
+        if [ $attempt -eq $max_attempts ]; then
+            log_err "Таймаут ожидания здоровья"
+            docker compose -f deploy/docker-compose.prod.yml logs --tail=50 caddy backend
+            exit 1
+        fi
+        sleep 2
+    done
+
+    # Финальная проверка через HTTPS (Synology)
+    log_info "Проверка через HTTPS (Synology)..."
+    if curl -sf "https://photoplaces.ru/api/v1/health" >/dev/null 2>&1; then
+        log_ok "HTTPS health check пройден"
+    else
+        log_warn "HTTPS check не прошёл (проверьте настройки Synology Reverse Proxy)"
+    fi
+}
+
+# 7. Вывод результатов
+show_result() {
+    echo
+    log_ok "=== ДЕПЛОЙ УСПЕШНО ЗАВЕРШЁН ==="
+    echo
+    echo "  Фронтенд:     https://photoplaces.ru"
+    echo "  API:          https://api.photoplaces.ru/api/v1"
+    echo "  S3 API:       https://api.photoplaces.ru/s3"
+    echo "  MinIO Console: https://api.photoplaces.ru/minio-console/"
+    echo
+    echo "  Логи:         cd $PROJECT_DIR && docker compose -f deploy/docker-compose.prod.yml logs -f"
+    echo "  Статус:       cd $PROJECT_DIR && docker compose -f deploy/docker-compose.prod.yml ps"
+    echo "  Остановка:    cd $PROJECT_DIR && docker compose -f deploy/docker-compose.prod.yml down"
+    echo
+}
+
+# ===========================================
+# MAIN
+# ===========================================
+main() {
+    check_deps
+    setup_repo
+    setup_env
+    create_docker_secrets
+    deploy
+    health_check
+    show_result
+}
+
+main "$@"