From cd93ddc640807d86594e517f2ba49c783cac0745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D0=B4=D0=BE=D0=B2?= Date: Wed, 10 Jun 2026 17:17:29 +0300 Subject: [PATCH] commit 7 --- install.sh | 184 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 73 deletions(-) diff --git a/install.sh b/install.sh index e28ba73..a93adfb 100644 --- a/install.sh +++ b/install.sh @@ -6,6 +6,7 @@ GIT_HOST="git.lendry.ru" BRANCH="main" INSTALL_DIR="${INSTALL_DIR:-$HOME/sso-mvk}" SKIP_PREREQS="${SKIP_PREREQS:-false}" +PROGRESS_FILE="$INSTALL_DIR/.install-progress" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' info() { echo -e "${GREEN}✔${NC} $1"; } @@ -13,6 +14,10 @@ warn() { echo -e "${YELLOW}⚠${NC} $1"; } error() { echo -e "${RED}✘${NC} $1"; exit 1; } step() { echo -e "\n${CYAN}━━━ $1 ━━━${NC}"; } +# ─── Mark progress ────────────────────────────────────────────── +mark_done() { echo "$1" >> "$PROGRESS_FILE"; } +is_done() { grep -qx "$1" "$PROGRESS_FILE" 2>/dev/null; } + echo -e "${CYAN}" echo " ╔══════════════════════════════════════════════╗" echo " ║ SSO Service — Auto Installer ║" @@ -47,11 +52,7 @@ install_docker() { info "Docker already installed ($($SUDO docker --version 2>/dev/null || docker --version))" else warn "Docker not found — installing..." - if command -v apt-get &>/dev/null; then - curl -fsSL https://get.docker.com | $SUDO sh - elif command -v yum &>/dev/null; then - curl -fsSL https://get.docker.com | $SUDO sh - elif command -v dnf &>/dev/null; then + if command -v apt-get &>/dev/null || command -v yum &>/dev/null || command -v dnf &>/dev/null; then curl -fsSL https://get.docker.com | $SUDO sh else error "Unsupported package manager. Install Docker manually: https://docs.docker.com/engine/install/" @@ -60,14 +61,25 @@ install_docker() { info "Docker installed." fi - # Ensure Docker daemon is running + # Ждём запуска Docker daemon (до 30 секунд) if ! $SUDO docker info &>/dev/null; then - warn "Starting Docker daemon..." + warn "Docker daemon not running — starting..." $SUDO systemctl enable --now docker 2>/dev/null || $SUDO dockerd &>/dev/null & - sleep 3 + for i in $(seq 1 15); do + sleep 2 + if $SUDO docker info &>/dev/null; then + info "Docker daemon started" + break + fi + if [ "$i" -eq 15 ]; then + error "Docker daemon did not start. Check: $SUDO systemctl status docker" + fi + done + else + info "Docker daemon is running" fi - info "Docker daemon is running" + # Docker Compose plugin if ! $SUDO docker compose version &>/dev/null; then warn "Docker Compose not found — installing plugin..." $SUDO mkdir -p /usr/local/lib/docker/cli-plugins @@ -82,38 +94,34 @@ install_node() { step "2/8 Installing Node.js" if command -v node &>/dev/null; then NODE_MAJOR=$(node -v | sed 's/v//' | cut -d. -f1) - if [ "$NODE_MAJOR" -lt 22 ]; then - warn "Node.js $(node -v) is too old — upgrading to v22..." - else + if [ "$NODE_MAJOR" -ge 22 ]; then info "Node.js $(node -v) detected" return 0 fi + warn "Node.js $(node -v) is too old — upgrading to v22..." fi - if ! command -v node &>/dev/null || [ "$NODE_MAJOR" -lt 22 ]; then - warn "Installing Node.js 22 LTS..." - if command -v apt-get &>/dev/null; then - curl -fsSL https://deb.nodesource.com/setup_22.x | $SUDO bash - - $SUDO apt-get install -y nodejs - elif command -v dnf &>/dev/null; then - curl -fsSL https://rpm.nodesource.com/setup_22.x | $SUDO bash - - $SUDO dnf install -y nodejs - elif command -v yum &>/dev/null; then - curl -fsSL https://rpm.nodesource.com/setup_22.x | $SUDO bash - - $SUDO yum install -y nodejs - else - warn "Package manager not recognised — trying nvm..." - curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - nvm install 22 - nvm alias default 22 - fi + warn "Installing Node.js 22 LTS..." + if command -v apt-get &>/dev/null; then + curl -fsSL https://deb.nodesource.com/setup_22.x | $SUDO bash - + $SUDO apt-get install -y nodejs + elif command -v dnf &>/dev/null; then + curl -fsSL https://rpm.nodesource.com/setup_22.x | $SUDO bash - + $SUDO dnf install -y nodejs + elif command -v yum &>/dev/null; then + curl -fsSL https://rpm.nodesource.com/setup_22.x | $SUDO bash - + $SUDO yum install -y nodejs + else + warn "Package manager not recognised — trying nvm..." + curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install 22 + nvm alias default 22 fi info "Node.js $(node -v) ready" } -# ─── 3. Install prerequisites if needed ────────────────────────── if [ "$SKIP_PREREQS" != "true" ]; then install_docker install_node @@ -121,61 +129,85 @@ else step "1-2/8 Skipping prerequisites (SKIP_PREREQS=true)" fi -# ─── 4. Download project ───────────────────────────────────────── +# ─── 3. Download project ───────────────────────────────────────── step "3/8 Downloading SSO Service" -if [ -d "$INSTALL_DIR/.git" ]; then +if ! is_done "download"; then + if [ -d "$INSTALL_DIR/.git" ]; then + cd "$INSTALL_DIR" + git pull --ff-only 2>/dev/null && info "Updated existing installation" || warn "Could not git pull, continuing" + else + mkdir -p "$INSTALL_DIR" + if command -v git &>/dev/null; then + git clone --depth 1 "https://$GIT_HOST/$REPO.git" "$INSTALL_DIR" 2>&1 + else + warn "git not found, downloading archive..." + curl -fsSL "https://$GIT_HOST/$REPO/archive/$BRANCH.tar.gz" | tar xz --strip=1 -C "$INSTALL_DIR" + fi + info "Downloaded to $INSTALL_DIR" + fi cd "$INSTALL_DIR" - git pull --ff-only 2>/dev/null && info "Updated existing installation" || warn "Could not git pull, continuing" + mark_done "download" else - mkdir -p "$INSTALL_DIR" - if command -v git &>/dev/null; then - git clone --depth 1 "https://$GIT_HOST/$REPO.git" "$INSTALL_DIR" 2>&1 - else - warn "git not found, downloading archive..." - curl -fsSL "https://$GIT_HOST/$REPO/archive/$BRANCH.tar.gz" | tar xz --strip=1 -C "$INSTALL_DIR" - fi - info "Downloaded to $INSTALL_DIR" + cd "$INSTALL_DIR" + info "Already downloaded" fi -cd "$INSTALL_DIR" -# ─── 5. .env ───────────────────────────────────────────────────── +# ─── 4. .env ───────────────────────────────────────────────────── step "4/8 Configuring environment" -if [ ! -f .env ]; then - cp .env.example .env - # Генерация случайных JWT-секретов (32 байта hex = 64 символа) - JWT_ACCESS=$(openssl rand -hex 32 2>/dev/null || node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))") - JWT_REFRESH=$(openssl rand -hex 32 2>/dev/null || node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))") - if [ "$(uname -s)" = "Darwin" ]; then - sed -i '' "s/change-me-access-secret-at-least-32-chars/$JWT_ACCESS/" .env - sed -i '' "s/change-me-refresh-secret-at-least-32-chars/$JWT_REFRESH/" .env +if ! is_done "env"; then + if [ ! -f .env ]; then + cp .env.example .env + JWT_ACCESS=$(openssl rand -hex 32 2>/dev/null || node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))") + JWT_REFRESH=$(openssl rand -hex 32 2>/dev/null || node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))") + if [ "$(uname -s)" = "Darwin" ]; then + sed -i '' "s/change-me-access-secret-at-least-32-chars/$JWT_ACCESS/" .env + sed -i '' "s/change-me-refresh-secret-at-least-32-chars/$JWT_REFRESH/" .env + else + sed -i "s/change-me-access-secret-at-least-32-chars/$JWT_ACCESS/" .env + sed -i "s/change-me-refresh-secret-at-least-32-chars/$JWT_REFRESH/" .env + fi + info "Created .env with random JWT secrets" else - sed -i "s/change-me-access-secret-at-least-32-chars/$JWT_ACCESS/" .env - sed -i "s/change-me-refresh-secret-at-least-32-chars/$JWT_REFRESH/" .env + info ".env already exists, keeping it" fi - info "Created .env with random JWT secrets" + mark_done "env" else - info ".env already exists, keeping it" + info "Environment already configured" fi set -a; source .env; set +a -# ─── 6. Docker infrastructure ──────────────────────────────────── +# ─── 5. Docker infrastructure ──────────────────────────────────── step "5/8 Starting infrastructure (PostgreSQL, Redis, RabbitMQ)" -if ! $SUDO docker compose up -d; then - $SUDO docker compose logs 2>/dev/null | tail -20 - error "Docker containers failed to start. Check '${INSTALL_DIR}/docker-compose.yml' and run '${SUDO}docker compose logs' manually." + +# Проверка занятости портов +for port in 5432 6379 5672 15672; do + if ss -tlnp "sport = :$port" 2>/dev/null | grep -q .; then + warn "Port $port is already in use — service may conflict with existing postgres/redis/rabbitmq" + fi +done + +# Остановить предыдущие контейнеры (если есть), потом запустить заново +$SUDO docker compose down --remove-orphans 2>/dev/null || true + +if ! $SUDO docker compose up -d --force-recreate --remove-orphans; then + warn "Docker Compose output:" + $SUDO docker compose logs --tail=30 2>/dev/null || true + error "Containers failed to start. Check ports and run: ${SUDO}docker compose logs" fi -info "Waiting for PostgreSQL..." +info "Waiting for PostgreSQL (up to 60s)..." +DB_READY=false for i in $(seq 1 30); do if $SUDO docker compose exec -T postgres pg_isready -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" &>/dev/null; then + DB_READY=true info "PostgreSQL is ready" break fi if [ "$i" -eq 30 ]; then - warn "PostgreSQL did not become ready — showing last logs:" + warn "PostgreSQL logs (last 20 lines):" $SUDO docker compose logs --tail=20 postgres 2>/dev/null || true - error "PostgreSQL did not start in time. Fix the issue and re-run the script." + error "PostgreSQL did not start. Check ${INSTALL_DIR}/.env for DB credentials and port 5432 availability." fi sleep 2 done @@ -187,35 +219,41 @@ for i in $(seq 1 15); do break fi if [ "$i" -eq 15 ]; then - warn "Redis may not be ready yet, continuing..." + warn "Redis did not respond — continuing anyway..." fi sleep 2 done -# ─── 7. Dependencies & Prisma ──────────────────────────────────── +# ─── 6. Dependencies & Prisma ──────────────────────────────────── step "6/8 Installing dependencies" npm ci --no-audit --no-fund || error "'npm ci' failed. Check network / ${INSTALL_DIR}/package-lock.json" info "npm dependencies installed" -npx prisma generate || error "'prisma generate' failed. Check Prisma schema." +npx prisma generate || error "'prisma generate' failed." info "Prisma client generated" export DATABASE_URL -npx prisma db push --skip-generate || error "'prisma db push' failed. Is PostgreSQL running? Check connection details in ${INSTALL_DIR}/.env" +npx prisma db push --skip-generate || error "'prisma db push' failed. Is PostgreSQL accessible? Check ${INSTALL_DIR}/.env DATABASE_URL" info "Database schema applied" -# ─── 8. Seed ───────────────────────────────────────────────────── +# ─── 7. Seed ───────────────────────────────────────────────────── step "7/8 Seeding database" -npx ts-node -P tsconfig.json prisma/seed.ts || error "Seed failed. Check database connection." +npx ts-node -P tsconfig.json prisma/seed.ts || error "Seed failed." info "Seed data created" -# ─── 9. Build & Start ──────────────────────────────────────────── +# ─── 8. Build & Start ──────────────────────────────────────────── step "8/8 Building and starting SSO Service" -npm run build || error "'npm run build' failed. Check for TypeScript errors above." +npm run build || error "'npm run build' failed. Check TypeScript errors above." info "Application built" +# Остановить предыдущий процесс, если был +if [ -f "$INSTALL_DIR/.sso.pid" ]; then + kill "$(cat "$INSTALL_DIR/.sso.pid")" 2>/dev/null || true + rm -f "$INSTALL_DIR/.sso.pid" +fi +pm2 delete sso-service 2>/dev/null || true + if command -v pm2 &>/dev/null; then - pm2 delete sso-service 2>/dev/null || true pm2 start npm --name "sso-service" -- run start:prod pm2 save 2>/dev/null || true info "Started with PM2"