#!/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 "$@"