Files
links/setup.sh
Andrey K. Choi 20014d3a81
Some checks failed
continuous-integration/drone/push Build is failing
environment emprovements
2025-11-04 21:18:15 +09:00

494 lines
15 KiB
Bash
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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