commit 7
This commit is contained in:
184
install.sh
184
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"
|
||||
|
||||
Reference in New Issue
Block a user