fix: remove "type" field from package.json + improve setup.sh
- Remove "type": "commonjs" from package.json — fixes Turbopack ESM/CommonJS conflict causing white screen in dev mode - setup.sh: auto-generate passwords (PostgreSQL, MinIO, auth secret) - setup.sh: auto-install Docker/Node.js if missing (apt/nvm/brew) - setup.sh: backup existing .env before overwrite - setup.sh: create MinIO bucket via curl if mc not installed - setup.sh: add timeout errors for service readiness checks - setup.sh: include pgbouncer in local dev docker compose up Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,6 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"type": "commonjs",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@livekit/components-react": "^2.9.20",
|
"@livekit/components-react": "^2.9.20",
|
||||||
"@livekit/components-styles": "^1.2.0",
|
"@livekit/components-styles": "^1.2.0",
|
||||||
|
|||||||
214
setup.sh
214
setup.sh
@@ -64,6 +64,12 @@ generate_secret() {
|
|||||||
openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64 | tr -d '=/+' | head -c 32
|
openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64 | tr -d '=/+' | head -c 32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_password() {
|
||||||
|
# 20 символов: буквы + цифры (безопасно для URL и CLI)
|
||||||
|
openssl rand -base64 24 2>/dev/null | tr -d '=/+' | head -c 20 || \
|
||||||
|
head -c 24 /dev/urandom | base64 | tr -d '=/+' | head -c 20
|
||||||
|
}
|
||||||
|
|
||||||
check_command() {
|
check_command() {
|
||||||
if command -v "$1" &>/dev/null; then
|
if command -v "$1" &>/dev/null; then
|
||||||
log_ok "$1 найден: $(command -v "$1")"
|
log_ok "$1 найден: $(command -v "$1")"
|
||||||
@@ -74,21 +80,87 @@ check_command() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_if_missing() {
|
||||||
|
local cmd="$1" install_hint="$2"
|
||||||
|
if command -v "$cmd" &>/dev/null; then
|
||||||
|
log_ok "$cmd найден: $(command -v "$cmd")"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_warn "$cmd не найден"
|
||||||
|
|
||||||
|
# Попытка автоустановки через системные менеджеры
|
||||||
|
if [[ "$cmd" == "node" || "$cmd" == "npm" || "$cmd" == "npx" ]]; then
|
||||||
|
if command -v nvm &>/dev/null; then
|
||||||
|
echo -e " Установка Node.js через nvm..."
|
||||||
|
nvm install --lts 2>&1 | tail -3
|
||||||
|
if command -v "$cmd" &>/dev/null; then
|
||||||
|
log_ok "$cmd установлен через nvm"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Автоустановка через apt/yum/brew если доступно
|
||||||
|
case "$cmd" in
|
||||||
|
docker)
|
||||||
|
if command -v apt-get &>/dev/null; then
|
||||||
|
if ask_yn "Установить Docker автоматически (apt)?" "y"; then
|
||||||
|
echo -e " Установка Docker..."
|
||||||
|
curl -fsSL https://get.docker.com | sh 2>&1 | tail -5
|
||||||
|
sudo usermod -aG docker "$USER" 2>/dev/null || true
|
||||||
|
if command -v docker &>/dev/null; then
|
||||||
|
log_ok "Docker установлен"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
node|npm|npx)
|
||||||
|
if command -v apt-get &>/dev/null; then
|
||||||
|
if ask_yn "Установить Node.js 22 автоматически (apt)?" "y"; then
|
||||||
|
echo -e " Установка Node.js..."
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - 2>&1 | tail -3
|
||||||
|
sudo apt-get install -y nodejs 2>&1 | tail -3
|
||||||
|
if command -v "$cmd" &>/dev/null; then
|
||||||
|
log_ok "$cmd установлен"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif command -v brew &>/dev/null; then
|
||||||
|
if ask_yn "Установить Node.js через Homebrew?" "y"; then
|
||||||
|
brew install node 2>&1 | tail -3
|
||||||
|
if command -v "$cmd" &>/dev/null; then
|
||||||
|
log_ok "$cmd установлен"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
log_err "$cmd не удалось установить автоматически"
|
||||||
|
echo -e " ${YELLOW}Установи вручную:${NC} $install_hint"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Main
|
# Main
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
print_banner
|
print_banner
|
||||||
|
|
||||||
# --- Step 1: Check dependencies ---
|
# --- Step 1: Check & install dependencies ---
|
||||||
log_step "Шаг 1/6 — Проверка зависимостей"
|
log_step "Шаг 1/6 — Проверка и установка зависимостей"
|
||||||
|
|
||||||
MISSING=0
|
MISSING=0
|
||||||
check_command docker || MISSING=1
|
install_if_missing docker "https://docs.docker.com/get-docker/" || MISSING=1
|
||||||
check_command "docker compose" 2>/dev/null || check_command docker-compose || MISSING=1
|
check_command "docker compose" 2>/dev/null || check_command docker-compose 2>/dev/null || {
|
||||||
check_command node || MISSING=1
|
log_err "docker compose не найден (нужен Docker Compose V2)"
|
||||||
check_command npm || MISSING=1
|
MISSING=1
|
||||||
check_command npx || MISSING=1
|
}
|
||||||
|
install_if_missing node "https://nodejs.org/" || MISSING=1
|
||||||
|
install_if_missing npm "https://nodejs.org/" || MISSING=1
|
||||||
|
|
||||||
if [[ "$MISSING" -eq 1 ]]; then
|
if [[ "$MISSING" -eq 1 ]]; then
|
||||||
log_err "Установи недостающие зависимости и запусти скрипт снова."
|
log_err "Установи недостающие зависимости и запусти скрипт снова."
|
||||||
@@ -137,39 +209,66 @@ fi
|
|||||||
# --- Step 3: Configure environment ---
|
# --- Step 3: Configure environment ---
|
||||||
log_step "Шаг 3/6 — Настройка окружения"
|
log_step "Шаг 3/6 — Настройка окружения"
|
||||||
|
|
||||||
echo ""
|
# Автогенерация паролей
|
||||||
echo -e " ${BOLD}PostgreSQL${NC}"
|
PG_PASSWORD=$(generate_password)
|
||||||
ask "Пароль PostgreSQL" "postgres" PG_PASSWORD
|
MINIO_USER="minio-$(head -c 4 /dev/urandom | xxd -p)"
|
||||||
|
MINIO_PASS=$(generate_password)
|
||||||
|
AUTH_SECRET=$(generate_secret)
|
||||||
|
DEV_ACCESS_KEY=$(generate_password | head -c 16)
|
||||||
|
S3_BUCKET="liveserver"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${BOLD}MinIO (S3 Storage)${NC}"
|
echo -e " ${GREEN}${BOLD}Пароли сгенерированы автоматически:${NC}"
|
||||||
ask "MinIO root user" "minioadmin" MINIO_USER
|
echo -e " ${CYAN}PostgreSQL:${NC} ${PG_PASSWORD}"
|
||||||
ask_secret "MinIO root password" "minioadmin" MINIO_PASS
|
echo -e " ${CYAN}MinIO user:${NC} ${MINIO_USER}"
|
||||||
ask "Название S3 bucket" "liveserver" S3_BUCKET
|
echo -e " ${CYAN}MinIO password:${NC} ${MINIO_PASS}"
|
||||||
|
echo -e " ${CYAN}Auth secret:${NC} ${AUTH_SECRET:0:16}..."
|
||||||
|
if [[ "$MODE" == "1" ]]; then
|
||||||
|
echo -e " ${CYAN}DEV_ACCESS_KEY:${NC} ${DEV_ACCESS_KEY}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo -e " ${YELLOW}Все пароли сохранены в .env — можешь изменить позже${NC}"
|
||||||
|
|
||||||
|
if ask_yn "Хочешь задать свои пароли вместо сгенерированных?" "n"; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}PostgreSQL${NC}"
|
||||||
|
ask "Пароль PostgreSQL" "$PG_PASSWORD" PG_PASSWORD
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}MinIO (S3 Storage)${NC}"
|
||||||
|
ask "MinIO root user" "$MINIO_USER" MINIO_USER
|
||||||
|
ask_secret "MinIO root password" "$MINIO_PASS" MINIO_PASS
|
||||||
|
ask "Название S3 bucket" "$S3_BUCKET" S3_BUCKET
|
||||||
|
|
||||||
|
if [[ "$MODE" == "1" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Защита локалки${NC}"
|
||||||
|
ask "Ключ доступа (DEV_ACCESS_KEY)" "$DEV_ACCESS_KEY" DEV_ACCESS_KEY
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${BOLD}LiveKit${NC}"
|
echo -e " ${BOLD}LiveKit${NC} (Enter чтобы пропустить, настроишь позже)"
|
||||||
ask "LiveKit URL (wss://...)" "" LK_URL
|
ask "LiveKit URL (wss://...)" "" LK_URL
|
||||||
ask "LiveKit API Key" "" LK_KEY
|
LK_KEY=""
|
||||||
ask_secret "LiveKit API Secret" "" LK_SECRET
|
LK_SECRET=""
|
||||||
ask_secret "LiveKit Webhook Secret (Enter чтобы пропустить)" "" LK_WEBHOOK
|
LK_WEBHOOK=""
|
||||||
|
if [[ -n "$LK_URL" ]]; then
|
||||||
|
ask "LiveKit API Key" "" LK_KEY
|
||||||
|
ask_secret "LiveKit API Secret" "" LK_SECRET
|
||||||
|
ask_secret "LiveKit Webhook Secret (Enter = пропустить)" "" LK_WEBHOOK
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${BOLD}AI Agent (Enter чтобы пропустить, настроишь позже)${NC}"
|
echo -e " ${BOLD}AI Agent${NC} (Enter чтобы пропустить, настроишь позже)"
|
||||||
ask_secret "Deepgram API Key" "" DG_KEY
|
ask_secret "Deepgram API Key" "" DG_KEY
|
||||||
ask_secret "OpenAI API Key" "" OAI_KEY
|
ask_secret "OpenAI API Key" "" OAI_KEY
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e " ${BOLD}Аутентификация${NC}"
|
|
||||||
AUTH_SECRET=$(generate_secret)
|
|
||||||
log_ok "Сгенерирован BETTER_AUTH_SECRET"
|
|
||||||
|
|
||||||
if [[ "$MODE" == "1" ]]; then
|
if [[ "$MODE" == "1" ]]; then
|
||||||
DEV_KEY=$(generate_secret | head -c 16)
|
ALLOWED_IPS=""
|
||||||
echo ""
|
if ask_yn "Ограничить доступ по IP? (кроме localhost)" "n"; then
|
||||||
echo -e " ${BOLD}Защита локалки${NC}"
|
ask "Разрешённые IP (через запятую)" "" ALLOWED_IPS
|
||||||
ask "Ключ доступа (DEV_ACCESS_KEY)" "$DEV_KEY" DEV_ACCESS_KEY
|
fi
|
||||||
ask "Разрешённые IP (через запятую, Enter = все)" "" ALLOWED_IPS
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Step 4: Generate .env ---
|
# --- Step 4: Generate .env ---
|
||||||
@@ -183,8 +282,15 @@ else
|
|||||||
S3_ENDPOINT="http://localhost:9000"
|
S3_ENDPOINT="http://localhost:9000"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Бэкап существующего .env
|
||||||
|
if [[ -f .env ]]; then
|
||||||
|
cp .env ".env.backup.$(date +%Y%m%d_%H%M%S)"
|
||||||
|
log_ok "Бэкап старого .env создан"
|
||||||
|
fi
|
||||||
|
|
||||||
cat > .env << ENVEOF
|
cat > .env << ENVEOF
|
||||||
# === Generated by setup.sh at $(date) ===
|
# === Generated by setup.sh at $(date) ===
|
||||||
|
# Все пароли сгенерированы автоматически — можешь заменить на свои.
|
||||||
|
|
||||||
# Domain & SSL
|
# Domain & SSL
|
||||||
DOMAIN=${DOMAIN}
|
DOMAIN=${DOMAIN}
|
||||||
@@ -195,8 +301,8 @@ DATABASE_URL=postgresql://postgres:${PG_PASSWORD}@localhost:5432/liveserver
|
|||||||
POSTGRES_PASSWORD=${PG_PASSWORD}
|
POSTGRES_PASSWORD=${PG_PASSWORD}
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
# For Docker containers: redis://redis:6379
|
# Для Docker контейнеров: redis://redis:6379
|
||||||
# For local npm run dev: redis://localhost:6379
|
# Для локального npm run dev: redis://localhost:6379
|
||||||
REDIS_URL=redis://localhost:6379
|
REDIS_URL=redis://localhost:6379
|
||||||
|
|
||||||
# LiveKit
|
# LiveKit
|
||||||
@@ -232,13 +338,17 @@ log_ok ".env создан"
|
|||||||
# --- Step 5: Install & setup ---
|
# --- Step 5: Install & setup ---
|
||||||
log_step "Шаг 5/6 — Установка и настройка"
|
log_step "Шаг 5/6 — Установка и настройка"
|
||||||
|
|
||||||
# npm install
|
# npm install — автоматически если нет node_modules или package-lock изменился
|
||||||
if [[ ! -d "node_modules" ]]; then
|
if [[ ! -d "node_modules" ]]; then
|
||||||
echo -e " Установка npm зависимостей..."
|
echo -e " Установка npm зависимостей..."
|
||||||
npm install --silent 2>&1 | tail -3
|
npm install 2>&1 | tail -5
|
||||||
log_ok "npm install"
|
log_ok "npm install завершён"
|
||||||
|
elif [[ "package.json" -nt "node_modules/.package-lock.json" ]] 2>/dev/null; then
|
||||||
|
echo -e " package.json обновлён, переустановка зависимостей..."
|
||||||
|
npm install 2>&1 | tail -5
|
||||||
|
log_ok "npm install завершён (обновление)"
|
||||||
else
|
else
|
||||||
log_ok "node_modules уже существует"
|
log_ok "node_modules актуален"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Prisma generate
|
# Prisma generate
|
||||||
@@ -251,7 +361,7 @@ echo -e " Запуск Docker контейнеров..."
|
|||||||
if [[ "$MODE" == "2" ]]; then
|
if [[ "$MODE" == "2" ]]; then
|
||||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build 2>&1 | tail -5
|
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build 2>&1 | tail -5
|
||||||
else
|
else
|
||||||
docker compose up -d postgres minio redis 2>&1 | tail -5
|
docker compose up -d postgres minio redis pgbouncer 2>&1 | tail -5
|
||||||
fi
|
fi
|
||||||
log_ok "Docker контейнеры запущены"
|
log_ok "Docker контейнеры запущены"
|
||||||
|
|
||||||
@@ -261,6 +371,10 @@ for i in $(seq 1 30); do
|
|||||||
if docker compose exec -T postgres pg_isready -U postgres &>/dev/null; then
|
if docker compose exec -T postgres pg_isready -U postgres &>/dev/null; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
if [[ "$i" -eq 30 ]]; then
|
||||||
|
log_err "PostgreSQL не запустился за 30 секунд"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
log_ok "PostgreSQL готов"
|
log_ok "PostgreSQL готов"
|
||||||
@@ -271,6 +385,10 @@ for i in $(seq 1 15); do
|
|||||||
if docker compose exec -T redis redis-cli ping 2>/dev/null | grep -q PONG; then
|
if docker compose exec -T redis redis-cli ping 2>/dev/null | grep -q PONG; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
if [[ "$i" -eq 15 ]]; then
|
||||||
|
log_err "Redis не запустился за 15 секунд"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
log_ok "Redis готов"
|
log_ok "Redis готов"
|
||||||
@@ -281,6 +399,9 @@ for i in $(seq 1 15); do
|
|||||||
if docker compose exec -T pgbouncer pg_isready -h 127.0.0.1 -p 6432 &>/dev/null; then
|
if docker compose exec -T pgbouncer pg_isready -h 127.0.0.1 -p 6432 &>/dev/null; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
if [[ "$i" -eq 15 ]]; then
|
||||||
|
log_warn "PgBouncer не отвечает — продолжаем без него"
|
||||||
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
log_ok "PgBouncer готов"
|
log_ok "PgBouncer готов"
|
||||||
@@ -290,7 +411,7 @@ echo -e " Применение миграций..."
|
|||||||
npx prisma db push --skip-generate 2>&1 | tail -3
|
npx prisma db push --skip-generate 2>&1 | tail -3
|
||||||
log_ok "Схема БД синхронизирована"
|
log_ok "Схема БД синхронизирована"
|
||||||
|
|
||||||
# Create MinIO bucket
|
# Create MinIO bucket (через docker exec если mc не установлен)
|
||||||
echo -e " Создание S3 bucket..."
|
echo -e " Создание S3 bucket..."
|
||||||
sleep 2
|
sleep 2
|
||||||
if command -v mc &>/dev/null; then
|
if command -v mc &>/dev/null; then
|
||||||
@@ -298,7 +419,15 @@ if command -v mc &>/dev/null; then
|
|||||||
mc mb "local/${S3_BUCKET}" 2>/dev/null || true
|
mc mb "local/${S3_BUCKET}" 2>/dev/null || true
|
||||||
log_ok "Bucket '${S3_BUCKET}' создан"
|
log_ok "Bucket '${S3_BUCKET}' создан"
|
||||||
else
|
else
|
||||||
log_warn "MinIO Client (mc) не найден — создай bucket '${S3_BUCKET}' вручную через http://localhost:9001"
|
# Создание через curl (MinIO S3 API)
|
||||||
|
if curl -sf -o /dev/null -X PUT "http://localhost:9000/${S3_BUCKET}" \
|
||||||
|
-u "${MINIO_USER}:${MINIO_PASS}" 2>/dev/null; then
|
||||||
|
log_ok "Bucket '${S3_BUCKET}' создан через API"
|
||||||
|
else
|
||||||
|
log_warn "Не удалось создать bucket автоматически"
|
||||||
|
echo -e " Создай вручную: ${CYAN}http://localhost:9001${NC} → Buckets → Create"
|
||||||
|
echo -e " Логин: ${CYAN}${MINIO_USER}${NC} / пароль в .env"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Step 6: Done ---
|
# --- Step 6: Done ---
|
||||||
@@ -326,6 +455,15 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Сгенерированные пароли (сохранены в .env):${NC}"
|
||||||
|
echo -e " ${CYAN}PostgreSQL:${NC} ${PG_PASSWORD}"
|
||||||
|
echo -e " ${CYAN}MinIO:${NC} ${MINIO_USER} / ${MINIO_PASS}"
|
||||||
|
if [[ "$MODE" == "1" && -n "${DEV_ACCESS_KEY:-}" ]]; then
|
||||||
|
echo -e " ${CYAN}DEV_ACCESS_KEY:${NC} ${DEV_ACCESS_KEY}"
|
||||||
|
fi
|
||||||
|
echo -e " ${YELLOW}Изменить пароли: отредактируй .env и перезапусти docker compose${NC}"
|
||||||
|
|
||||||
if [[ -z "$LK_URL" ]]; then
|
if [[ -z "$LK_URL" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
log_warn "LiveKit не настроен — видеозвонки не будут работать."
|
log_warn "LiveKit не настроен — видеозвонки не будут работать."
|
||||||
|
|||||||
Reference in New Issue
Block a user