494 lines
15 KiB
Bash
494 lines
15 KiB
Bash
#!/bin/bash
|
||
|
||
# CatLink Setup Script
|
||
# ====================
|
||
# Автоматическая настройка среды разработки
|
||
|
||
set -e # Остановить при ошибке
|
||
|
||
# Цвета для вывода
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Функции для цветного вывода
|
||
print_header() {
|
||
echo -e "${BLUE}========================================${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}========================================${NC}"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
# Проверка зависимостей
|
||
check_dependencies() {
|
||
print_header "Проверка зависимостей"
|
||
|
||
# Проверка Docker
|
||
if ! command -v docker &> /dev/null; then
|
||
print_error "Docker не установлен"
|
||
print_info "Установите Docker: https://docs.docker.com/get-docker/"
|
||
exit 1
|
||
fi
|
||
print_success "Docker найден: $(docker --version)"
|
||
|
||
# Проверка Docker Compose
|
||
if ! command -v docker-compose &> /dev/null; then
|
||
print_error "Docker Compose не установлен"
|
||
print_info "Установите Docker Compose: https://docs.docker.com/compose/install/"
|
||
exit 1
|
||
fi
|
||
print_success "Docker Compose найден: $(docker-compose --version)"
|
||
|
||
# Проверка Git
|
||
if ! command -v git &> /dev/null; then
|
||
print_warning "Git не установлен (рекомендуется для обновлений)"
|
||
else
|
||
print_success "Git найден: $(git --version)"
|
||
fi
|
||
|
||
# Проверка Make
|
||
if ! command -v make &> /dev/null; then
|
||
print_warning "Make не установлен (рекомендуется для удобства)"
|
||
print_info "Установите: sudo apt-get install make"
|
||
else
|
||
print_success "Make найден: $(make --version | head -1)"
|
||
fi
|
||
}
|
||
|
||
# Создание .env файла
|
||
create_env_file() {
|
||
print_header "Создание конфигурации (.env)"
|
||
|
||
if [ -f .env ]; then
|
||
print_info ".env файл уже существует"
|
||
read -p "Пересоздать с помощью интерактивного генератора? (y/N): " recreate
|
||
if [[ $recreate =~ ^[Yy]$ ]]; then
|
||
print_info "Запуск интерактивного генератора .env..."
|
||
./scripts/generate_env.sh
|
||
return
|
||
else
|
||
print_info "Пропуск создания .env"
|
||
return
|
||
fi
|
||
fi
|
||
|
||
print_info "Запуск интерактивного генератора .env..."
|
||
|
||
# Проверяем наличие скрипта генерации
|
||
if [ -f "scripts/generate_env.sh" ]; then
|
||
chmod +x scripts/generate_env.sh
|
||
./scripts/generate_env.sh
|
||
else
|
||
print_warning "Скрипт генерации не найден, создаем базовый .env"
|
||
|
||
# Генерация SECRET_KEY
|
||
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(50))" 2>/dev/null || openssl rand -base64 32)
|
||
|
||
# Запрос основных данных
|
||
echo ""
|
||
read -p "Имя базы данных [links_db]: " DB_NAME
|
||
DB_NAME=${DB_NAME:-links_db}
|
||
|
||
read -p "Пользователь БД [links_user]: " DB_USER
|
||
DB_USER=${DB_USER:-links_user}
|
||
|
||
read -p "Пароль БД (пустой для генерации): " DB_PASSWORD
|
||
if [ -z "$DB_PASSWORD" ]; then
|
||
DB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
print_info "Сгенерирован пароль БД: $DB_PASSWORD"
|
||
fi
|
||
|
||
# Копируем из примера и заполняем основные поля
|
||
cp .env.example .env
|
||
sed -i "s|^DJANGO_SECRET_KEY=.*|DJANGO_SECRET_KEY=$SECRET_KEY|" .env
|
||
sed -i "s|^DATABASE_NAME=.*|DATABASE_NAME=$DB_NAME|" .env
|
||
sed -i "s|^DATABASE_USER=.*|DATABASE_USER=$DB_USER|" .env
|
||
sed -i "s|^DATABASE_PASSWORD=.*|DATABASE_PASSWORD=$DB_PASSWORD|" .env
|
||
sed -i "s|^POSTGRES_DB=.*|POSTGRES_DB=$DB_NAME|" .env
|
||
sed -i "s|^POSTGRES_USER=.*|POSTGRES_USER=$DB_USER|" .env
|
||
sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$DB_PASSWORD|" .env
|
||
sed -i "s|^NEXT_PUBLIC_API_URL=.*|NEXT_PUBLIC_API_URL=http://localhost:8000|" .env
|
||
fi
|
||
|
||
print_success ".env файл создан"
|
||
}
|
||
|
||
# Создание продакшен конфигурации
|
||
create_production_config() {
|
||
print_header "Создание продакшен конфигурации"
|
||
|
||
if [ ! -f docker-compose.prod.yml ]; then
|
||
cat > docker-compose.prod.yml << 'EOF'
|
||
version: '3.8'
|
||
|
||
services:
|
||
web:
|
||
environment:
|
||
- DEBUG=False
|
||
- DJANGO_SETTINGS_MODULE=backend.settings
|
||
volumes:
|
||
- ./storage:/app/storage
|
||
- ./logs:/app/logs
|
||
restart: unless-stopped
|
||
|
||
frontend:
|
||
environment:
|
||
- NODE_ENV=production
|
||
- NEXT_TELEMETRY_DISABLED=1
|
||
restart: unless-stopped
|
||
|
||
db:
|
||
restart: unless-stopped
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./backups:/backups
|
||
|
||
nginx:
|
||
image: nginx:alpine
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
volumes:
|
||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||
- ./ssl:/etc/nginx/ssl:ro
|
||
- ./storage:/var/www/storage:ro
|
||
- /etc/letsencrypt:/etc/letsencrypt:ro
|
||
depends_on:
|
||
- web
|
||
- frontend
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
postgres_data:
|
||
EOF
|
||
print_success "docker-compose.prod.yml создан"
|
||
else
|
||
print_info "docker-compose.prod.yml уже существует"
|
||
fi
|
||
}
|
||
|
||
# Создание nginx конфигурации
|
||
create_nginx_config() {
|
||
print_header "Создание конфигурации Nginx"
|
||
|
||
if [ ! -f nginx.conf ]; then
|
||
cat > nginx.conf << 'EOF'
|
||
events {
|
||
worker_connections 1024;
|
||
}
|
||
|
||
http {
|
||
upstream backend {
|
||
server web:8000;
|
||
}
|
||
|
||
upstream frontend {
|
||
server frontend:3000;
|
||
}
|
||
|
||
# Redirect HTTP to HTTPS
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
|
||
# HTTPS Server
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name _;
|
||
|
||
# SSL Configuration
|
||
ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
|
||
# Frontend
|
||
location / {
|
||
proxy_pass http://frontend;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
|
||
# Backend API
|
||
location /api/ {
|
||
proxy_pass http://backend;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
|
||
# Admin
|
||
location /admin/ {
|
||
proxy_pass http://backend;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
|
||
# Static files
|
||
location /storage/ {
|
||
alias /var/www/storage/;
|
||
expires 30d;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
|
||
# Security headers
|
||
add_header X-Frame-Options DENY;
|
||
add_header X-Content-Type-Options nosniff;
|
||
add_header X-XSS-Protection "1; mode=block";
|
||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||
}
|
||
}
|
||
EOF
|
||
print_success "nginx.conf создан"
|
||
else
|
||
print_info "nginx.conf уже существует"
|
||
fi
|
||
}
|
||
|
||
# Создание директорий
|
||
create_directories() {
|
||
print_header "Создание необходимых директорий"
|
||
|
||
directories=(
|
||
"storage"
|
||
"storage/avatars"
|
||
"storage/images"
|
||
"storage/images/links"
|
||
"storage/images/link_groups"
|
||
"storage/customization"
|
||
"backups"
|
||
"logs"
|
||
"ssl"
|
||
)
|
||
|
||
for dir in "${directories[@]}"; do
|
||
if [ ! -d "$dir" ]; then
|
||
mkdir -p "$dir"
|
||
print_success "Создана директория: $dir"
|
||
else
|
||
print_info "Директория уже существует: $dir"
|
||
fi
|
||
done
|
||
|
||
# Установка прав доступа
|
||
chmod 755 storage
|
||
chmod -R 755 storage/
|
||
print_success "Права доступа установлены"
|
||
}
|
||
|
||
# Сборка и запуск контейнеров
|
||
build_and_start() {
|
||
print_header "Сборка и запуск контейнеров"
|
||
|
||
print_info "Остановка существующих контейнеров..."
|
||
docker-compose down 2>/dev/null || true
|
||
|
||
print_info "Сборка контейнеров..."
|
||
docker-compose build --no-cache
|
||
|
||
print_info "Запуск контейнеров..."
|
||
docker-compose up -d
|
||
|
||
print_info "Ожидание запуска сервисов..."
|
||
sleep 10
|
||
|
||
print_success "Контейнеры запущены"
|
||
}
|
||
|
||
# Инициализация базы данных
|
||
initialize_database() {
|
||
print_header "Инициализация базы данных"
|
||
|
||
print_info "Ожидание готовности базы данных..."
|
||
sleep 5
|
||
|
||
print_info "Выполнение миграций..."
|
||
docker-compose exec -T web python manage.py migrate
|
||
|
||
print_info "Сбор статических файлов..."
|
||
docker-compose exec -T web python manage.py collectstatic --noinput
|
||
|
||
print_success "База данных инициализирована"
|
||
}
|
||
|
||
# Создание суперпользователя
|
||
create_superuser() {
|
||
print_header "Создание суперпользователя"
|
||
|
||
echo ""
|
||
read -p "Создать суперпользователя? (Y/n): " create_user
|
||
if [[ ! $create_user =~ ^[Nn]$ ]]; then
|
||
print_info "Создание суперпользователя..."
|
||
docker-compose exec web python manage.py createsuperuser
|
||
print_success "Суперпользователь создан"
|
||
else
|
||
print_info "Пропуск создания суперпользователя"
|
||
print_info "Вы можете создать его позже командой: make superuser"
|
||
fi
|
||
}
|
||
|
||
# Проверка здоровья системы
|
||
health_check() {
|
||
print_header "Проверка здоровья системы"
|
||
|
||
print_info "Проверка frontend..."
|
||
if curl -s http://localhost:3000 > /dev/null; then
|
||
print_success "Frontend доступен: http://localhost:3000"
|
||
else
|
||
print_error "Frontend недоступен"
|
||
fi
|
||
|
||
print_info "Проверка backend..."
|
||
if curl -s http://localhost:8000 > /dev/null; then
|
||
print_success "Backend доступен: http://localhost:8000"
|
||
else
|
||
print_error "Backend недоступен"
|
||
fi
|
||
|
||
print_info "Проверка базы данных..."
|
||
if docker-compose exec -T db pg_isready -U links_user > /dev/null 2>&1; then
|
||
print_success "База данных готова"
|
||
else
|
||
print_error "База данных недоступна"
|
||
fi
|
||
}
|
||
|
||
# Создание документации
|
||
create_documentation() {
|
||
print_header "Создание документации"
|
||
|
||
if [ ! -f DEPLOYMENT.md ]; then
|
||
cat > DEPLOYMENT.md << 'EOF'
|
||
# CatLink Deployment Guide
|
||
|
||
## Быстрый старт
|
||
|
||
```bash
|
||
# Первый запуск
|
||
make install
|
||
|
||
# Режим разработки
|
||
make dev
|
||
|
||
# Продакшен
|
||
make deploy
|
||
```
|
||
|
||
## Полезные команды
|
||
|
||
```bash
|
||
# Статус сервисов
|
||
make status
|
||
|
||
# Логи
|
||
make logs
|
||
|
||
# Перезапуск
|
||
make restart
|
||
|
||
# Создание суперпользователя
|
||
make superuser
|
||
|
||
# Бэкап базы данных
|
||
make backup
|
||
|
||
# SSL настройка
|
||
make ssl
|
||
```
|
||
|
||
## Структура проекта
|
||
|
||
- `frontend/` - Next.js приложение
|
||
- `backend/` - Django API
|
||
- `storage/` - Загруженные файлы
|
||
- `backups/` - Бэкапы базы данных
|
||
- `logs/` - Логи приложения
|
||
|
||
## Продакшен
|
||
|
||
1. Настройте домен в `.env`
|
||
2. Запустите `make ssl` для настройки HTTPS
|
||
3. Используйте `make deploy` для развертывания
|
||
|
||
EOF
|
||
print_success "DEPLOYMENT.md создан"
|
||
else
|
||
print_info "DEPLOYMENT.md уже существует"
|
||
fi
|
||
}
|
||
|
||
# Финальный вывод
|
||
print_final_info() {
|
||
print_header "Установка завершена!"
|
||
|
||
echo ""
|
||
echo -e "${GREEN}🎉 CatLink успешно установлен!${NC}"
|
||
echo ""
|
||
echo -e "${BLUE}📱 Frontend:${NC} http://localhost:3000"
|
||
echo -e "${BLUE}🔧 Backend API:${NC} http://localhost:8000/api/"
|
||
echo -e "${BLUE}📊 Admin панель:${NC} http://localhost:8000/admin/"
|
||
echo ""
|
||
echo -e "${YELLOW}📚 Полезные команды:${NC}"
|
||
echo " make help - Все доступные команды"
|
||
echo " make status - Статус сервисов"
|
||
echo " make logs - Просмотр логов"
|
||
echo " make restart - Перезапуск"
|
||
echo " make superuser - Создать суперпользователя"
|
||
echo " make backup - Создать бэкап"
|
||
echo ""
|
||
echo -e "${BLUE}📖 Документация:${NC} DEPLOYMENT.md"
|
||
echo ""
|
||
}
|
||
|
||
# Основная функция
|
||
main() {
|
||
print_header "CatLink Setup Script v2.0"
|
||
|
||
# Проверка, что мы в правильной директории
|
||
if [ ! -f "docker-compose.yml" ]; then
|
||
print_error "docker-compose.yml не найден. Убедитесь, что вы в корневой директории проекта."
|
||
exit 1
|
||
fi
|
||
|
||
check_dependencies
|
||
create_env_file
|
||
create_production_config
|
||
create_nginx_config
|
||
create_directories
|
||
build_and_start
|
||
initialize_database
|
||
create_superuser
|
||
health_check
|
||
create_documentation
|
||
print_final_info
|
||
}
|
||
|
||
# Обработка ошибок
|
||
trap 'print_error "Произошла ошибка. Установка прервана."' ERR
|
||
|
||
# Запуск основной функции
|
||
main "$@" |