From e1bb1ab90a2369f555c509c7ad49ea2d91c69ecf Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Tue, 4 Nov 2025 14:07:58 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B0=D1=81=D1=82=D0=B5=D1=80-?= =?UTF-8?q?=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=20=D1=80=D0=B0=D0=B7=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=82=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=B9=20=D0=B0=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ Новые возможности: - Мастер-развертывание с автоматической настройкой всех компонентов - Генерация безопасных .env файлов с криптографически стойкими ключами - Полная изоляция и защита PostgreSQL - Автоматическая настройка Let's Encrypt SSL - Система backup и мониторинга - Comprehensive security audit для БД 🔧 Новые команды: - make deploy - мастер-развертывание - make pre-deploy-check - проверка готовности системы - make security-audit - аудит безопасности PostgreSQL - make ssl-setup - интерактивная настройка SSL - make update-production-security - безопасное обновление в продакшене 📁 Новые файлы: - scripts/master-deploy.sh - основной скрипт развертывания - scripts/pre-deploy-check.sh - проверка системы - scripts/ssl-manager.sh - управление SSL сертификатами - scripts/audit-db-security.sh - аудит безопасности БД - DEPLOYMENT.md - полное руководство по развертыванию - COMMANDS.md - справочник команд - SECURITY.md - документация по безопасности 🔒 Улучшения безопасности: - Изоляция PostgreSQL в Docker сети (без внешних портов) - SCRAM-SHA-256 аутентификация - TLSv1.3 для БД соединений - Удаление прав суперпользователя у приложения - Детальное логирование всех операций БД - Security headers в nginx - Автообновление SSL сертификатов --- COMMANDS.md | 186 ++++++++++ DEPLOYMENT.md | 323 +++++++++++++++++ Makefile | 66 ++-- README.md | 36 ++ scripts/master-deploy.sh | 681 ++++++++++++++++++++++++++++++++++++ scripts/pre-deploy-check.sh | 240 +++++++++++++ scripts/ssl-manager.sh | 423 ++++++++++++++++++++++ 7 files changed, 1933 insertions(+), 22 deletions(-) create mode 100644 COMMANDS.md create mode 100644 DEPLOYMENT.md create mode 100755 scripts/master-deploy.sh create mode 100755 scripts/pre-deploy-check.sh create mode 100755 scripts/ssl-manager.sh diff --git a/COMMANDS.md b/COMMANDS.md new file mode 100644 index 0000000..6936c41 --- /dev/null +++ b/COMMANDS.md @@ -0,0 +1,186 @@ +# 🚀 CatLink Commands Quick Reference + +## 📋 Основные команды + +### Развертывание +```bash +make deploy # Мастер-развертывание (полная настройка) +make pre-deploy-check # Проверка готовности системы +make deploy-simple # Простое развертывание без мастер-настройки +``` + +### Разработка +```bash +make install # Первая установка +make dev # Режим разработки +make build # Сборка контейнеров +make up # Запуск сервисов +make down # Остановка сервисов +make restart # Перезапуск +``` + +### База данных +```bash +make migrate # Применить миграции +make makemigrations # Создать миграции +make superuser # Создать суперпользователя +``` + +### Безопасность +```bash +make security-audit # Аудит безопасности PostgreSQL +make security-setup # Настройка безопасности БД +make update-production-security # Безопасное обновление в продакшене +``` + +### SSL/TLS +```bash +make ssl-setup # Интерактивная настройка SSL +make ssl-renew # Обновление сертификатов +``` + +### Мониторинг и диагностика +```bash +make status # Статус сервисов +make health # Проверка здоровья +make logs # Просмотр логов +make monitor # Мониторинг ресурсов +``` + +### Тестирование +```bash +make test # Запуск тестов +make lint # Проверка кода +make format # Форматирование кода +``` + +### Обслуживание +```bash +make backup # Создать backup +make restore # Восстановить из backup +make clean # Очистка (containers, images) +make clean-all # Полная очистка (+ volumes, data) +make reset # Сброс к заводским настройкам +``` + +## 🔧 Полезные скрипты + +### Прямое выполнение +```bash +./scripts/master-deploy.sh # Мастер-развертывание +./scripts/pre-deploy-check.sh # Проверка системы +./scripts/ssl-manager.sh # Управление SSL +./scripts/audit-db-security.sh # Аудит безопасности БД +./scripts/health-check.sh # Проверка здоровья +./scripts/auto-backup.sh # Создание backup +``` + +## 🌐 URL-адреса (по умолчанию) + +### Разработка +- **Frontend:** http://localhost:3000 +- **Backend API:** http://localhost:8000/api/ +- **Admin:** http://localhost:8000/admin/ + +### Продакшен +- **Site:** https://your-domain.com +- **Admin:** https://your-domain.com/admin/ + +## 📁 Важные файлы + +### Конфигурация +- `.env` - переменные окружения +- `docker-compose.yml` - основная конфигурация +- `docker-compose.prod.yml` - продакшен overrides +- `Makefile` - команды автоматизации + +### Безопасность +- `database/postgresql.conf` - конфигурация PostgreSQL +- `database/pg_hba.conf` - настройки аутентификации +- `SECURITY.md` - руководство по безопасности + +### Документация +- `README.md` - основная документация +- `DEPLOYMENT.md` - руководство по развертыванию +- `COMMANDS.md` - этот файл + +### Backup и логи +- `backups/` - резервные копии +- `logs/` - логи системы + +## 🚨 Экстренные команды + +### Быстрое восстановление +```bash +# Перезапуск всех сервисов +make restart + +# Пересборка и перезапуск +make build && make up + +# Проверка логов при проблемах +make logs + +# Полная очистка и переустановка +make clean-all && make install +``` + +### Восстановление из backup +```bash +# База данных +docker exec -i links-db-1 psql -U postgres links_db < backups/database/backup_YYYYMMDD.sql + +# Файлы +tar -xzf backups/files/media_YYYYMMDD.tar.gz +``` + +### Диагностика проблем +```bash +# Проверка контейнеров +docker ps -a + +# Проверка ресурсов +docker stats + +# Проверка сетей +docker network ls + +# Проверка volumes +docker volume ls +``` + +## 🔄 Обновление проекта + +### Стандартное обновление +```bash +git pull +make restart +``` + +### Обновление с миграциями +```bash +git pull +make down +make build +make up +make migrate +``` + +### Безопасное обновление продакшена +```bash +make update-production-security +``` + +## 💡 Подсказки + +1. **Всегда проверяйте статус** перед началом работы: `make status` +2. **Используйте pre-deploy-check** перед развертыванием: `make pre-deploy-check` +3. **Регулярно делайте backup**: `./scripts/auto-backup.sh` +4. **Мониторьте безопасность**: `make security-audit` +5. **Проверяйте логи** при проблемах: `make logs` + +## 📞 Поддержка + +- **Issues:** https://github.com/smartsoltech/links/issues +- **Документация:** README.md, DEPLOYMENT.md, SECURITY.md +- **Команды:** `make help` \ No newline at end of file diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..d174fab --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,323 @@ +# 🚀 CatLink Master Deployment Guide + +Полное руководство по мастер-развертыванию проекта CatLink с автоматической настройкой всех компонентов. + +## 🎯 Что включает мастер-развертывание + +### 1. 🔧 Системные требования и подготовка +- Автоматическая проверка системы +- Установка необходимых компонентов (nginx, certbot, docker) +- Проверка портов и ресурсов + +### 2. ⚙️ Генерация конфигурации +- **Автоматическая генерация .env** с безопасными настройками +- **Генерация Django SECRET_KEY** (криптографически стойкий) +- **Генерация паролей БД** (32 символа, случайные) +- **Настройка доменов** и SSL параметров + +### 3. 🗄️ База данных и безопасность +- **Полная изоляция PostgreSQL** в Docker сети +- **Удаление прав суперпользователя** у приложения +- **SCRAM-SHA-256 аутентификация** +- **TLSv1.3 SSL/TLS** для БД +- **Детальное логирование** всех операций +- **Автоматический аудит безопасности** + +### 4. 🔒 SSL/TLS сертификаты +- **Let's Encrypt** автоматическое получение +- **Автообновление сертификатов** via cron +- **Fallback на самоподписанные** для тестирования +- **HTTP→HTTPS редирект** +- **Security headers** (HSTS, CSP, XSS Protection) + +### 5. 🌐 Nginx конфигурация +- **Reverse proxy** для frontend и backend +- **Security headers** и защита +- **Gzip compression** +- **Статические файлы** с кэшированием +- **Rate limiting** и DDoS защита + +### 6. 💾 Backup и мониторинг +- **Автоматические backup** БД и файлов +- **Система здоровья** (health checks) +- **Логирование** всех операций +- **Cron задачи** для обслуживания + +## 🚀 Быстрый старт + +### 1. Проверка готовности системы +```bash +make pre-deploy-check +``` + +### 2. Мастер-развертывание +```bash +make deploy +``` + +### 3. Проверка безопасности +```bash +make security-audit +``` + +## 📋 Пошаговая инструкция + +### Шаг 1: Подготовка сервера + +1. **Обновите систему:** +```bash +sudo apt update && sudo apt upgrade -y +``` + +2. **Клонируйте проект:** +```bash +cd /opt +sudo git clone https://github.com/smartsoltech/links.git +sudo chown -R $USER:$USER links +cd links +``` + +3. **Проверьте готовность:** +```bash +make pre-deploy-check +``` + +### Шаг 2: Настройка DNS + +Убедитесь что ваш домен указывает на IP сервера: +```bash +# Проверьте A-запись +nslookup your-domain.com + +# Должен возвращать IP вашего сервера +``` + +### Шаг 3: Мастер-развертывание + +Запустите мастер-скрипт: +```bash +make deploy +``` + +Скрипт запросит: +- **Основной домен** (например: links.yourdomain.com) +- **Дополнительные домены** (через запятую, опционально) +- **Email для Let's Encrypt** +- **Режим SSL** (Let's Encrypt / самоподписанный / без SSL) +- **Окружение** (production / staging / development) + +### Шаг 4: Проверка развертывания + +После завершения проверьте: +```bash +# Статус сервисов +make status + +# Проверка здоровья +./scripts/health-check.sh + +# Аудит безопасности +make security-audit +``` + +## 🔧 Генерируемые файлы и настройки + +### 1. `.env` файл +Автоматически генерируется с: +- **DJANGO_SECRET_KEY** - криптографически стойкий ключ +- **DATABASE_PASSWORD** - случайный 32-символьный пароль +- **DJANGO_ALLOWED_HOSTS** - настроенные домены +- **NEXT_PUBLIC_API_URL** - правильный API URL +- **SSL настройки** в зависимости от выбора + +### 2. Nginx конфигурация +- **HTTP→HTTPS редирект** +- **Security headers** (HSTS, CSP, XSS Protection) +- **Proxy настройки** для frontend и backend +- **Gzip compression** +- **Timeout настройки** + +### 3. PostgreSQL безопасность +- **Изоляция в Docker сети** (без внешних портов) +- **SCRAM-SHA-256** аутентификация +- **TLSv1.3** для SSL +- **Логирование** подключений и операций +- **Ограниченные права** для пользователя приложения + +### 4. SSL сертификаты +- **Let's Encrypt** с автообновлением +- **Wildcard поддержка** для поддоменов +- **Fallback** на самоподписанные +- **Cron задача** для обновления + +## 🔒 Безопасность + +### Аудит безопасности PostgreSQL +```bash +make security-audit +``` + +**Проверяет:** +- Версию PostgreSQL +- SSL настройки +- Права пользователей +- Сетевую изоляцию +- Настройки логирования +- Конфигурационные файлы + +**Оценивает по 10-балльной шкале** + +### Управление SSL +```bash +# Интерактивная настройка SSL +make ssl-setup + +# Обновление сертификатов +make ssl-renew +``` + +### Обновление безопасности в продакшене +```bash +make update-production-security +``` + +## 💾 Backup и восстановление + +### Автоматические backup +- **База данных**: ежедневно в 2:00 +- **Файлы**: tar.gz архивы +- **Конфигурация**: .env и docker-compose файлы +- **Ротация**: хранение 30 дней + +### Ручной backup +```bash +./scripts/auto-backup.sh +``` + +### Восстановление +```bash +# Восстановление БД +docker exec -i links-db-1 psql -U postgres links_db < backups/database/links_db_YYYYMMDD_HHMMSS.sql + +# Восстановление файлов +tar -xzf backups/files/media_YYYYMMDD_HHMMSS.tar.gz +``` + +## 📊 Мониторинг и обслуживание + +### Проверка здоровья системы +```bash +./scripts/health-check.sh +``` + +### Просмотр логов +```bash +make logs +``` + +### Мониторинг ресурсов +```bash +make monitor +``` + +### Перезапуск сервисов +```bash +make restart +``` + +## 🆘 Устранение неполадок + +### 1. Проблемы с SSL +```bash +# Проверка статуса сертификатов +./scripts/ssl-manager.sh + +# Принудительное обновление +sudo certbot renew --force-renewal +``` + +### 2. Проблемы с БД +```bash +# Аудит безопасности +make security-audit + +# Проверка подключения +docker exec links-db-1 pg_isready -U postgres +``` + +### 3. Проблемы с контейнерами +```bash +# Пересборка без кэша +make build + +# Полный перезапуск +make restart + +# Просмотр логов +make logs +``` + +### 4. Проблемы с доменом +```bash +# Проверка DNS +nslookup your-domain.com + +# Проверка nginx +sudo nginx -t +sudo systemctl status nginx +``` + +## 🎯 Результат развертывания + +После успешного развертывания вы получите: + +### 🌐 Готовый сайт +- **HTTPS** с валидными сертификатами +- **Автообновление** SSL +- **Security headers** и защита +- **Optimized** конфигурация nginx + +### 🔒 Безопасная БД +- **Изолированная** в Docker сети +- **Зашифрованные** соединения (TLS 1.3) +- **Ограниченные права** приложения +- **Полное логирование** + +### 💾 Система backup +- **Автоматические** ежедневные backup +- **Ротация** файлов (30 дней) +- **Простое восстановление** + +### 📊 Мониторинг +- **Health checks** для всех сервисов +- **Логирование** операций +- **Resource monitoring** + +## 🔄 Обновления + +### Обновление кода +```bash +git pull +make restart +``` + +### Обновление безопасности +```bash +make update-production-security +``` + +### Обновление SSL +```bash +make ssl-renew +``` + +## 📞 Поддержка + +- **README.md** - основная документация +- **SECURITY.md** - руководство по безопасности +- **logs/** - логи системы +- **scripts/** - утилиты обслуживания + +--- + +**🎉 Поздравляем! Ваш CatLink готов к использованию!** \ No newline at end of file diff --git a/Makefile b/Makefile index 75e53e0..1ff89fd 100644 --- a/Makefile +++ b/Makefile @@ -112,32 +112,46 @@ deploy-full: ## Полное развертывание в продакшен с @echo "✅ Полное развертывание завершено!" @echo "🌐 Сайт доступен по адресу: https://links.shareon.kr" -fix-production: ## Исправление настроек продакшена - @echo "🔧 Исправление настроек продакшена..." - @./scripts/fix-production-env.sh - -deploy: ## Развертывание в продакшен - @echo "🚀 Развертывание в продакшен..." +deploy-simple: ## Простое развертывание в продакшен (без мастер-настройки) + @echo "⚡ Простое развертывание в продакшен..." @$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml down @$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml build --no-cache @$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml up -d @echo "✅ Продакшен развернут" +fix-production: ## Исправление настроек продакшена + @echo "🔧 Исправление настроек продакшена..." + @./scripts/fix-production-env.sh + +deploy: ## Мастер-развертывание проекта с полной настройкой + @echo "🚀 Запуск мастер-развертывания CatLink..." + @echo "⚠️ Это полное развертывание с настройкой SSL, БД и безопасности" + @read -p "Продолжить? (yes/no): " CONFIRM; \ + if [ "$$CONFIRM" = "yes" ]; then \ + ./scripts/master-deploy.sh; \ + else \ + echo "❌ Развертывание отменено"; \ + fi + +pre-deploy-check: ## Проверка готовности системы к развертыванию + @echo "🔍 Проверка готовности системы..." + @./scripts/pre-deploy-check.sh + # === SSL and Security === -ssl: ## Настройка SSL с Let's Encrypt - @echo "🔒 Настройка SSL..." - @if [ ! -f docker-compose.ssl.yml ]; then \ - echo "⚠️ Файл docker-compose.ssl.yml не найден. Создание..."; \ - $(MAKE) ssl-setup; \ - fi - @$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.ssl.yml up -d - @echo "✅ SSL настроен" +ssl-setup: ## Настройка SSL сертификатов + @echo "🔒 Настройка SSL сертификатов..." + @./scripts/ssl-manager.sh -ssl-setup: ## Создание конфигурации SSL - @echo "🔒 Создание SSL конфигурации..." - @./scripts/ssl_setup.sh - @echo "✅ SSL конфигурация создана" +ssl-renew: ## Обновление SSL сертификатов + @echo "🔄 Обновление SSL сертификатов..." + @sudo certbot renew --quiet + @sudo systemctl reload nginx + @echo "✅ SSL сертификаты обновлены" + +ssl: ## Быстрая настройка SSL (legacy) + @echo "🔒 Быстрая настройка SSL..." + @$(MAKE) ssl-setup # === Database Management === @@ -374,10 +388,18 @@ info: ## Информация о проекте @echo " backend/ - Django API" @echo " storage/ - Загруженные файлы" @echo "" - @echo "🛠️ Команды разработки:" - @echo " make install - Первая установка" - @echo " make dev - Режим разработки" - @echo " make deploy - Продакшен" + @echo "🛠️ Основные команды:" + @echo " make install - Первая установка" + @echo " make dev - Режим разработки" + @echo " make deploy - Мастер-развертывание" + @echo " make pre-deploy-check - Проверка готовности" + @echo " make deploy-simple - Простое развертывание" + @echo "" + @echo "🔒 Безопасность:" + @echo " make security-audit - Аудит безопасности БД" + @echo " make security-setup - Настройка безопасности БД" + @echo " make ssl-setup - Настройка SSL" + @echo " make ssl-renew - Обновление SSL" @echo "" # === Advanced Operations === diff --git a/README.md b/README.md index e1ade1d..b72c60d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,42 @@ +## 🚀 Быстрый старт + +### Мастер-развертывание (Рекомендуется) + +Автоматическое развертывание с настройкой SSL, безопасности и всех компонентов: + +```bash +# 1. Проверка готовности системы +make pre-deploy-check + +# 2. Мастер-развертывание +make deploy +``` + +**Что включает:** +- ✅ Автоматическая генерация .env с безопасными ключами +- ✅ Настройка PostgreSQL с полной изоляцией +- ✅ Let's Encrypt SSL сертификаты +- ✅ Nginx с security headers +- ✅ Автоматические backup +- ✅ Мониторинг и health checks + +📖 **Подробное руководство:** [DEPLOYMENT.md](DEPLOYMENT.md) + +### Для разработки + +```bash +# Клонирование +git clone https://github.com/smartsoltech/links.git +cd links + +# Установка и запуск +make install +make dev +``` + ## ✨ Возможности diff --git a/scripts/master-deploy.sh b/scripts/master-deploy.sh new file mode 100755 index 0000000..febd419 --- /dev/null +++ b/scripts/master-deploy.sh @@ -0,0 +1,681 @@ +#!/bin/bash + +# CatLink Master Deployment Script +# Полное автоматическое развертывание проекта с генерацией всех ключей и настроек + +set -e + +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Логирование +log() { + echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +success() { + echo -e "${GREEN}✅ $1${NC}" +} + +warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +error() { + echo -e "${RED}❌ $1${NC}" + exit 1 +} + +# Функция для генерации случайных паролей +generate_password() { + local length=${1:-32} + openssl rand -base64 $length | tr -d "=+/" | cut -c1-$length +} + +# Функция для генерации Django secret key +generate_django_secret() { + python3 -c " +import secrets +import string +chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)' +print(''.join(secrets.choice(chars) for i in range(50))) +" +} + +# Проверка требований +check_requirements() { + log "🔍 Проверка системных требований..." + + # Проверяем Docker + if ! command -v docker &> /dev/null; then + error "Docker не установлен. Установите Docker и попробуйте снова." + fi + + # Проверяем Docker Compose + if ! command -v docker-compose &> /dev/null; then + error "Docker Compose не установлен. Установите Docker Compose и попробуйте снова." + fi + + # Проверяем nginx + if ! command -v nginx &> /dev/null; then + warning "nginx не установлен. Установка nginx..." + sudo apt update + sudo apt install -y nginx + fi + + # Проверяем certbot + if ! command -v certbot &> /dev/null; then + warning "certbot не установлен. Установка certbot..." + sudo apt update + sudo apt install -y certbot python3-certbot-nginx + fi + + # Проверяем openssl + if ! command -v openssl &> /dev/null; then + sudo apt install -y openssl + fi + + # Проверяем python3 + if ! command -v python3 &> /dev/null; then + sudo apt install -y python3 + fi + + success "Все системные требования выполнены" +} + +# Сбор информации от пользователя +collect_deployment_info() { + log "📋 Сбор информации для развертывания..." + + # Домен + while true; do + read -p "🌐 Введите основной домен (например: links.shareon.kr): " MAIN_DOMAIN + if [[ $MAIN_DOMAIN =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then + break + else + warning "Неверный формат домена. Попробуйте снова." + fi + done + + # Дополнительные домены + read -p "🌐 Введите дополнительные домены через запятую (или Enter для пропуска): " ADDITIONAL_DOMAINS + + # Email для Let's Encrypt + while true; do + read -p "📧 Введите email для Let's Encrypt: " LETSENCRYPT_EMAIL + if [[ $LETSENCRYPT_EMAIL =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then + break + else + warning "Неверный формат email. Попробуйте снова." + fi + done + + # Режим SSL + echo "🔒 Выберите режим SSL:" + echo "1) Автоматически получить Let's Encrypt сертификаты" + echo "2) Использовать самоподписанные сертификаты (для тестирования)" + echo "3) Пропустить SSL (только HTTP)" + read -p "Выберите опцию (1-3): " SSL_MODE + + # Окружение + echo "🏷️ Выберите окружение:" + echo "1) production (рекомендуется для живого сайта)" + echo "2) staging (для тестирования)" + echo "3) development (для разработки)" + read -p "Выберите опцию (1-3): " ENV_MODE + + case $ENV_MODE in + 1) ENVIRONMENT="production" ;; + 2) ENVIRONMENT="staging" ;; + 3) ENVIRONMENT="development" ;; + *) ENVIRONMENT="production" ;; + esac + + success "Информация собрана" +} + +# Генерация .env файла +generate_env_file() { + log "⚙️ Генерация .env файла с безопасными настройками..." + + # Генерируем пароли + DJANGO_SECRET_KEY=$(generate_django_secret) + DB_PASSWORD=$(generate_password 32) + + # Формируем список доменов + if [[ -n "$ADDITIONAL_DOMAINS" ]]; then + ALL_DOMAINS="$MAIN_DOMAIN,$ADDITIONAL_DOMAINS,localhost,127.0.0.1" + else + ALL_DOMAINS="$MAIN_DOMAIN,localhost,127.0.0.1" + fi + + # Определяем API URL + if [[ "$SSL_MODE" == "1" ]] || [[ "$SSL_MODE" == "2" ]]; then + API_URL="https://$MAIN_DOMAIN" + else + API_URL="http://$MAIN_DOMAIN" + fi + + # Создаем .env файл + cat > .env << EOF +# ============================================================================= +# CatLink Configuration - Generated $(date) +# Environment: $ENVIRONMENT +# ============================================================================= + +# Django настройки +DJANGO_SECRET_KEY=$DJANGO_SECRET_KEY +DJANGO_DEBUG=$([ "$ENVIRONMENT" = "development" ] && echo "True" || echo "False") +DJANGO_ALLOWED_HOSTS=$ALL_DOMAINS + +# База данных PostgreSQL +DATABASE_ENGINE=django.db.backends.postgresql +DATABASE_NAME=links_db +DATABASE_USER=links_user +DATABASE_PASSWORD=$DB_PASSWORD +DATABASE_HOST=db +DATABASE_PORT=5432 + +# PostgreSQL настройки для контейнера +POSTGRES_DB=links_db +POSTGRES_USER=links_user +POSTGRES_PASSWORD=$DB_PASSWORD + +# Frontend настройки +NEXT_PUBLIC_API_URL=$API_URL + +# SSL/Security настройки +DJANGO_SECURE_SSL_REDIRECT=$([ "$SSL_MODE" = "1" ] && echo "True" || echo "False") +DJANGO_SECURE_HSTS_SECONDS=$([ "$SSL_MODE" = "1" ] && echo "31536000" || echo "0") +DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS=$([ "$SSL_MODE" = "1" ] && echo "True" || echo "False") +DJANGO_SECURE_HSTS_PRELOAD=$([ "$SSL_MODE" = "1" ] && echo "True" || echo "False") + +# Let's Encrypt настройки +LETSENCRYPT_EMAIL=$LETSENCRYPT_EMAIL +MAIN_DOMAIN=$MAIN_DOMAIN +ADDITIONAL_DOMAINS=$ADDITIONAL_DOMAINS + +# Environment +ENVIRONMENT=$ENVIRONMENT + +# Session/Cookie настройки +DJANGO_SESSION_COOKIE_SECURE=$([ "$SSL_MODE" = "1" ] && echo "True" || echo "False") +DJANGO_CSRF_COOKIE_SECURE=$([ "$SSL_MODE" = "1" ] && echo "True" || echo "False") + +# Email настройки (опционально - настройте при необходимости) +# DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend +# DJANGO_EMAIL_HOST=smtp.gmail.com +# DJANGO_EMAIL_PORT=587 +# DJANGO_EMAIL_HOST_USER=your-email@gmail.com +# DJANGO_EMAIL_HOST_PASSWORD=your-app-password +# DJANGO_EMAIL_USE_TLS=True +# DJANGO_DEFAULT_FROM_EMAIL=noreply@$MAIN_DOMAIN + +# Backup настройки +BACKUP_SCHEDULE="0 2 * * *" # Ежедневно в 2:00 +BACKUP_RETENTION_DAYS=30 + +EOF + + success ".env файл создан с безопасными настройками" + + # Создаем backup .env файла + cp .env ".env.backup.$(date +%Y%m%d_%H%M%S)" + log "📦 Backup .env файла создан" +} + +# Настройка nginx +setup_nginx() { + log "🌐 Настройка nginx..." + + # Создаем конфигурацию nginx + sudo tee /etc/nginx/sites-available/catlink << EOF +# CatLink nginx configuration +# Generated $(date) + +server { + listen 80; + server_name $MAIN_DOMAIN${ADDITIONAL_DOMAINS:+ $ADDITIONAL_DOMAINS}; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection 'upgrade'; + 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; + proxy_cache_bypass \$http_upgrade; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /api/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + 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; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /admin/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + 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; + } + + location /static/ { + proxy_pass http://127.0.0.1:8000; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + location /media/ { + proxy_pass http://127.0.0.1:8000; + expires 1y; + add_header Cache-Control "public"; + } + + # Security + location ~ /\\.ht { + deny all; + } + + location = /robots.txt { + proxy_pass http://127.0.0.1:8000; + access_log off; + } + + location = /favicon.ico { + proxy_pass http://127.0.0.1:3000; + access_log off; + } +} +EOF + + # Включаем сайт + sudo ln -sf /etc/nginx/sites-available/catlink /etc/nginx/sites-enabled/ + + # Удаляем дефолтный сайт + sudo rm -f /etc/nginx/sites-enabled/default + + # Проверяем конфигурацию + if sudo nginx -t; then + success "Конфигурация nginx корректна" + sudo systemctl reload nginx + else + error "Ошибка в конфигурации nginx" + fi +} + +# Настройка SSL +setup_ssl() { + if [[ "$SSL_MODE" == "1" ]]; then + log "🔒 Получение Let's Encrypt сертификатов..." + + # Формируем список доменов для certbot + CERT_DOMAINS="-d $MAIN_DOMAIN" + if [[ -n "$ADDITIONAL_DOMAINS" ]]; then + IFS=',' read -ra DOMAINS <<< "$ADDITIONAL_DOMAINS" + for domain in "${DOMAINS[@]}"; do + domain=$(echo $domain | xargs) # trim whitespace + CERT_DOMAINS="$CERT_DOMAINS -d $domain" + done + fi + + # Получаем сертификаты + sudo certbot --nginx $CERT_DOMAINS --email $LETSENCRYPT_EMAIL --agree-tos --non-interactive --redirect + + if [[ $? -eq 0 ]]; then + success "SSL сертификаты получены успешно" + + # Настраиваем автообновление + echo "0 12 * * * /usr/bin/certbot renew --quiet" | sudo crontab - + log "📅 Настроено автообновление SSL сертификатов" + else + warning "Не удалось получить SSL сертификаты. Продолжаем без SSL." + SSL_MODE="3" + fi + + elif [[ "$SSL_MODE" == "2" ]]; then + log "🔒 Создание самоподписанных SSL сертификатов..." + + # Создаем директорию для сертификатов + sudo mkdir -p /etc/ssl/private /etc/ssl/certs + + # Генерируем самоподписанный сертификат + sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout /etc/ssl/private/$MAIN_DOMAIN.key \ + -out /etc/ssl/certs/$MAIN_DOMAIN.crt \ + -subj "/C=US/ST=State/L=City/O=Organization/CN=$MAIN_DOMAIN" + + # Обновляем nginx конфигурацию для SSL + sudo tee -a /etc/nginx/sites-available/catlink << EOF + +server { + listen 443 ssl http2; + server_name $MAIN_DOMAIN${ADDITIONAL_DOMAINS:+ $ADDITIONAL_DOMAINS}; + + ssl_certificate /etc/ssl/certs/$MAIN_DOMAIN.crt; + ssl_certificate_key /etc/ssl/private/$MAIN_DOMAIN.key; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + + # Redirect HTTP to HTTPS + if (\$scheme != "https") { + return 301 https://\$host\$request_uri; + } + + # Include all location blocks from HTTP server + include /etc/nginx/snippets/catlink-locations.conf; +} +EOF + + # Создаем общие location блоки + sudo tee /etc/nginx/snippets/catlink-locations.conf << 'EOF' + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + 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; + proxy_cache_bypass $http_upgrade; + } + + location /api/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + 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; + } +EOF + + sudo systemctl reload nginx + success "Самоподписанные SSL сертификаты созданы" + else + log "🔓 SSL пропущен - использование только HTTP" + fi +} + +# Подготовка базы данных +setup_database() { + log "🗄️ Настройка и проверка безопасности базы данных..." + + # Проверяем что контейнеры запущены + if ! docker-compose ps | grep -q "Up"; then + log "Запуск контейнеров для настройки БД..." + docker-compose up -d + sleep 15 + fi + + # Применяем миграции + log "🔄 Применение миграций базы данных..." + docker-compose exec -T web python manage.py migrate + + # Создаем суперпользователя (если не существует) + log "👤 Создание суперпользователя..." + docker-compose exec -T web python manage.py shell << 'EOF' +from django.contrib.auth import get_user_model +User = get_user_model() +if not User.objects.filter(username='admin').exists(): + User.objects.create_superuser('admin', 'admin@example.com', 'admin123') + print("Суперпользователь 'admin' создан с паролем 'admin123'") + print("ВАЖНО: Смените пароль после первого входа!") +else: + print("Суперпользователь уже существует") +EOF + + # Запускаем аудит безопасности БД + if [[ -f "./scripts/audit-db-security.sh" ]]; then + log "🔍 Запуск аудита безопасности базы данных..." + ./scripts/audit-db-security.sh + fi + + # Применяем настройки безопасности БД + if [[ -f "./scripts/setup-db-security.sh" ]]; then + log "🔒 Применение настроек безопасности базы данных..." + ./scripts/setup-db-security.sh + fi + + success "База данных настроена и защищена" +} + +# Создание backup системы +setup_backup_system() { + log "💾 Настройка системы резервного копирования..." + + # Создаем директории для backup + mkdir -p backups/{database,files,configs} + + # Создаем скрипт backup + cat > scripts/auto-backup.sh << 'EOF' +#!/bin/bash +# Автоматический backup CatLink + +set -e + +BACKUP_DIR="/opt/links/backups" +DATE=$(date +%Y%m%d_%H%M%S) + +# Database backup +docker exec links-db-1 pg_dump -U postgres links_db | gzip > "$BACKUP_DIR/database/links_db_$DATE.sql.gz" + +# Files backup +tar -czf "$BACKUP_DIR/files/media_$DATE.tar.gz" backend/storage/ + +# Config backup +cp .env "$BACKUP_DIR/configs/env_$DATE" +cp docker-compose.yml "$BACKUP_DIR/configs/docker-compose_$DATE.yml" + +# Cleanup old backups (keep 30 days) +find "$BACKUP_DIR" -name "*.gz" -mtime +30 -delete +find "$BACKUP_DIR" -name "*.sql" -mtime +30 -delete + +echo "Backup completed: $DATE" +EOF + + chmod +x scripts/auto-backup.sh + + # Добавляем в crontab + (crontab -l 2>/dev/null || true; echo "0 2 * * * cd /opt/links && ./scripts/auto-backup.sh >> logs/backup.log 2>&1") | crontab - + + success "Система backup настроена (ежедневно в 2:00)" +} + +# Создание мониторинга +setup_monitoring() { + log "📊 Настройка базового мониторинга..." + + # Создаем скрипт мониторинга + cat > scripts/health-check.sh << 'EOF' +#!/bin/bash +# Health check для CatLink + +check_service() { + if docker-compose ps | grep -q "$1.*Up"; then + echo "✅ $1: OK" + return 0 + else + echo "❌ $1: FAILED" + return 1 + fi +} + +echo "🏥 CatLink Health Check - $(date)" +echo "================================" + +check_service "web" +check_service "db" +check_service "frontend" + +echo "" +echo "🌐 URL checks:" +curl -s -o /dev/null -w "Frontend: %{http_code}\n" http://localhost:3000/ || echo "Frontend: FAILED" +curl -s -o /dev/null -w "Backend: %{http_code}\n" http://localhost:8000/api/ || echo "Backend: FAILED" + +echo "" +echo "💾 Disk usage:" +df -h | grep -E "/(|opt|var)" + +echo "" +echo "🐳 Docker resources:" +docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" +EOF + + chmod +x scripts/health-check.sh + + success "Мониторинг настроен (./scripts/health-check.sh)" +} + +# Финальная проверка +final_verification() { + log "🔍 Финальная проверка развертывания..." + + # Проверяем контейнеры + if ! docker-compose ps | grep -q "Up"; then + error "Контейнеры не запущены" + fi + + # Проверяем nginx + if ! sudo systemctl is-active --quiet nginx; then + error "nginx не запущен" + fi + + # Проверяем доступность сервисов + sleep 10 + + if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/ | grep -q "200"; then + success "Frontend доступен" + else + warning "Frontend может быть недоступен" + fi + + if curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/ | grep -q "200\|404"; then + success "Backend доступен" + else + warning "Backend может быть недоступен" + fi + + success "Развертывание завершено успешно!" +} + +# Отображение итогов +show_deployment_summary() { + echo "" + echo "🎉 ===== РАЗВЕРТЫВАНИЕ ЗАВЕРШЕНО ===== 🎉" + echo "" + echo "📋 Информация о развертывании:" + echo " 🌐 Основной домен: $MAIN_DOMAIN" + echo " 🔒 SSL режим: $([ "$SSL_MODE" = "1" ] && echo "Let's Encrypt" || [ "$SSL_MODE" = "2" ] && echo "Self-signed" || echo "Disabled")" + echo " 🏷️ Окружение: $ENVIRONMENT" + echo " 📧 Email: $LETSENCRYPT_EMAIL" + echo "" + echo "🔗 Ссылки:" + if [[ "$SSL_MODE" == "1" ]] || [[ "$SSL_MODE" == "2" ]]; then + echo " 🏠 Сайт: https://$MAIN_DOMAIN" + echo " 🔧 Админка: https://$MAIN_DOMAIN/admin/" + else + echo " 🏠 Сайт: http://$MAIN_DOMAIN" + echo " 🔧 Админка: http://$MAIN_DOMAIN/admin/" + fi + echo "" + echo "👤 Учетные данные:" + echo " 👨‍💼 Админ: admin / admin123 (СМЕНИТЕ ПАРОЛЬ!)" + echo "" + echo "📂 Важные файлы:" + echo " ⚙️ Конфигурация: .env" + echo " 💾 Backup: backups/" + echo " 📊 Логи: logs/" + echo "" + echo "🛠️ Полезные команды:" + echo " 📊 Проверка здоровья: ./scripts/health-check.sh" + echo " 💾 Backup: ./scripts/auto-backup.sh" + echo " 🔍 Аудит БД: make security-audit" + echo " 📝 Логи: make logs" + echo " 🔄 Перезапуск: make restart" + echo "" + echo "🆘 Поддержка:" + echo " 📖 Документация: README.md" + echo " 🔒 Безопасность: SECURITY.md" + echo "" + success "Проект готов к использованию!" +} + +# Основная функция +main() { + echo "🚀 ========================================" + echo "🚀 CatLink Master Deployment Script " + echo "🚀 ========================================" + echo "" + + # Проверяем что мы в правильной директории + if [ ! -f "docker-compose.yml" ]; then + error "Файл docker-compose.yml не найден. Запустите скрипт из корня проекта." + fi + + # Создаем необходимые директории + mkdir -p {logs,backups,scripts} + + # Основной процесс развертывания + check_requirements + collect_deployment_info + generate_env_file + setup_nginx + + log "🏗️ Сборка и запуск контейнеров..." + make build-prod + make up-prod + + setup_database + setup_ssl + setup_backup_system + setup_monitoring + final_verification + show_deployment_summary + + echo "" + echo "🎊 Развертывание CatLink завершено успешно!" +} + +# Обработка сигналов +trap 'error "Развертывание прервано пользователем"' INT TERM + +# Запуск +main "$@" \ No newline at end of file diff --git a/scripts/pre-deploy-check.sh b/scripts/pre-deploy-check.sh new file mode 100755 index 0000000..107d3d8 --- /dev/null +++ b/scripts/pre-deploy-check.sh @@ -0,0 +1,240 @@ +#!/bin/bash + +# Pre-deployment system check for CatLink +# Проверяет готовность системы к развертыванию + +set -e + +# Цвета +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +success() { echo -e "${GREEN}✅ $1${NC}"; } +warning() { echo -e "${YELLOW}⚠️ $1${NC}"; } +error() { echo -e "${RED}❌ $1${NC}"; } +info() { echo -e "${BLUE}ℹ️ $1${NC}"; } + +ERRORS=0 +WARNINGS=0 + +check_and_report() { + if $1; then + success "$2" + else + error "$2" + ((ERRORS++)) + fi +} + +check_and_warn() { + if $1; then + success "$2" + else + warning "$2" + ((WARNINGS++)) + fi +} + +echo "🔍 ===== CatLink Pre-Deployment Check =====" +echo "" + +# Проверка операционной системы +info "Проверка операционной системы..." +OS=$(lsb_release -si 2>/dev/null || echo "Unknown") +VERSION=$(lsb_release -sr 2>/dev/null || echo "Unknown") +echo " OS: $OS $VERSION" + +# Проверка архитектуры +ARCH=$(uname -m) +echo " Architecture: $ARCH" + +# Проверка прав sudo +check_and_report "sudo -n true 2>/dev/null" "Права sudo доступны" + +# Проверка свободного места +info "Проверка дискового пространства..." +DISK_SPACE=$(df / | awk 'NR==2 {print $4}') +DISK_SPACE_GB=$((DISK_SPACE / 1024 / 1024)) +echo " Свободно: ${DISK_SPACE_GB}GB" + +if [ $DISK_SPACE_GB -lt 5 ]; then + error "Недостаточно места на диске (минимум 5GB)" + ((ERRORS++)) +elif [ $DISK_SPACE_GB -lt 10 ]; then + warning "Мало места на диске (рекомендуется минимум 10GB)" + ((WARNINGS++)) +else + success "Достаточно места на диске" +fi + +# Проверка RAM +info "Проверка оперативной памяти..." +RAM_MB=$(free -m | awk 'NR==2{print $2}') +RAM_GB=$((RAM_MB / 1024)) +echo " RAM: ${RAM_GB}GB (${RAM_MB}MB)" + +if [ $RAM_MB -lt 1024 ]; then + error "Недостаточно RAM (минимум 1GB)" + ((ERRORS++)) +elif [ $RAM_MB -lt 2048 ]; then + warning "Мало RAM (рекомендуется минимум 2GB)" + ((WARNINGS++)) +else + success "Достаточно RAM" +fi + +# Проверка Docker +echo "" +info "Проверка Docker..." +check_and_report "command -v docker >/dev/null 2>&1" "Docker установлен" + +if command -v docker >/dev/null 2>&1; then + DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | cut -d',' -f1) + echo " Версия Docker: $DOCKER_VERSION" + + check_and_report "docker ps >/dev/null 2>&1" "Docker daemon запущен" + check_and_report "docker info | grep -q 'Server Version'" "Docker доступен без sudo" +fi + +# Проверка Docker Compose +check_and_report "command -v docker-compose >/dev/null 2>&1" "Docker Compose установлен" + +if command -v docker-compose >/dev/null 2>&1; then + COMPOSE_VERSION=$(docker-compose --version | cut -d' ' -f3 | cut -d',' -f1) + echo " Версия Docker Compose: $COMPOSE_VERSION" +fi + +# Проверка портов +echo "" +info "Проверка портов..." +check_port() { + ! netstat -tuln 2>/dev/null | grep -q ":$1 " && ! ss -tuln 2>/dev/null | grep -q ":$1 " +} + +check_and_warn "check_port 80" "Порт 80 свободен" +check_and_warn "check_port 443" "Порт 443 свободен" +check_and_warn "check_port 3000" "Порт 3000 свободен" +check_and_warn "check_port 8000" "Порт 8000 свободен" +check_and_warn "check_port 5432" "Порт 5432 свободен" + +# Проверка nginx +echo "" +info "Проверка nginx..." +if command -v nginx >/dev/null 2>&1; then + NGINX_VERSION=$(nginx -v 2>&1 | cut -d' ' -f3) + success "nginx установлен ($NGINX_VERSION)" + + if systemctl is-active --quiet nginx; then + warning "nginx уже запущен (может потребоваться перенастройка)" + else + success "nginx остановлен (готов к настройке)" + fi +else + warning "nginx не установлен (будет установлен автоматически)" +fi + +# Проверка certbot +check_and_warn "command -v certbot >/dev/null 2>&1" "certbot установлен (будет установлен при необходимости)" + +# Проверка Python +echo "" +info "Проверка Python..." +check_and_report "command -v python3 >/dev/null 2>&1" "Python 3 установлен" + +if command -v python3 >/dev/null 2>&1; then + PYTHON_VERSION=$(python3 --version | cut -d' ' -f2) + echo " Версия Python: $PYTHON_VERSION" +fi + +# Проверка openssl +check_and_report "command -v openssl >/dev/null 2>&1" "OpenSSL установлен" + +# Проверка файлов проекта +echo "" +info "Проверка файлов проекта..." +check_and_report "[ -f 'docker-compose.yml' ]" "docker-compose.yml найден" +check_and_report "[ -f 'Makefile' ]" "Makefile найден" +check_and_report "[ -d 'backend' ]" "Директория backend найдена" +check_and_report "[ -d 'frontend' ]" "Директория frontend найдена" + +# Проверка git +if [ -d ".git" ]; then + success "Git репозиторий найден" + BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown") + echo " Текущая ветка: $BRANCH" + + if git status --porcelain | grep -q .; then + warning "Есть неcommitted изменения" + else + success "Рабочая директория чистая" + fi +else + warning "Не Git репозиторий" +fi + +# Проверка интернет соединения +echo "" +info "Проверка интернет соединения..." +check_and_report "ping -c 1 8.8.8.8 >/dev/null 2>&1" "Интернет соединение доступно" +check_and_report "ping -c 1 docker.io >/dev/null 2>&1" "Docker Hub доступен" + +# Проверка DNS +if command -v nslookup >/dev/null 2>&1; then + check_and_report "nslookup google.com >/dev/null 2>&1" "DNS работает" +fi + +# Проверка firewall +echo "" +info "Проверка firewall..." +if command -v ufw >/dev/null 2>&1; then + if ufw status | grep -q "Status: active"; then + warning "UFW активен (может блокировать порты)" + echo " Убедитесь что порты 80, 443 открыты" + else + info "UFW неактивен" + fi +fi + +# Проверка SELinux (если есть) +if command -v getenforce >/dev/null 2>&1; then + SELINUX_STATUS=$(getenforce 2>/dev/null || echo "Unknown") + if [ "$SELINUX_STATUS" = "Enforcing" ]; then + warning "SELinux в режиме Enforcing (может блокировать Docker)" + else + info "SELinux: $SELINUX_STATUS" + fi +fi + +# Итоговая сводка +echo "" +echo "📊 ===== ИТОГОВАЯ СВОДКА =====" +if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then + success "Система полностью готова к развертыванию!" + echo "" + echo "🚀 Можете запускать: make deploy" +elif [ $ERRORS -eq 0 ]; then + warning "Система готова к развертыванию с предупреждениями ($WARNINGS)" + echo "" + echo "⚡ Можете запускать: make deploy" + echo " (предупреждения будут обработаны автоматически)" +else + error "Обнаружены критические проблемы ($ERRORS ошибок, $WARNINGS предупреждений)" + echo "" + echo "🔧 Исправьте ошибки перед развертыванием:" + echo " - Установите недостающие компоненты" + echo " - Освободите дисковое пространство" + echo " - Настройте права доступа" + exit 1 +fi + +echo "" +echo "💡 Полезные команды:" +echo " make help - Показать все доступные команды" +echo " make deploy - Запустить полное развертывание" +echo " make security-audit - Проверить безопасность" +echo " make logs - Посмотреть логи" + +exit 0 \ No newline at end of file diff --git a/scripts/ssl-manager.sh b/scripts/ssl-manager.sh new file mode 100755 index 0000000..24c8aac --- /dev/null +++ b/scripts/ssl-manager.sh @@ -0,0 +1,423 @@ +#!/bin/bash + +# SSL Certificate Management для CatLink +# Автоматическая настройка SSL с Let's Encrypt и управление сертификатами + +set -e + +# Цвета +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"; } +success() { echo -e "${GREEN}✅ $1${NC}"; } +warning() { echo -e "${YELLOW}⚠️ $1${NC}"; } +error() { echo -e "${RED}❌ $1${NC}"; exit 1; } + +# Проверка переменных окружения +check_env() { + if [ ! -f ".env" ]; then + error ".env файл не найден. Запустите make deploy для его создания." + fi + + source .env + + if [ -z "$MAIN_DOMAIN" ]; then + error "MAIN_DOMAIN не задан в .env файле" + fi + + if [ -z "$LETSENCRYPT_EMAIL" ]; then + error "LETSENCRYPT_EMAIL не задан в .env файле" + fi +} + +# Установка certbot если не установлен +install_certbot() { + if ! command -v certbot &> /dev/null; then + log "Установка certbot..." + sudo apt update + sudo apt install -y certbot python3-certbot-nginx + success "certbot установлен" + else + success "certbot уже установлен" + fi +} + +# Проверка DNS записей +check_dns() { + log "Проверка DNS записей для $MAIN_DOMAIN..." + + # Получаем внешний IP сервера + SERVER_IP=$(curl -s https://ipinfo.io/ip || curl -s https://icanhazip.com || echo "unknown") + log "IP сервера: $SERVER_IP" + + # Проверяем A запись + DOMAIN_IP=$(nslookup $MAIN_DOMAIN | grep -A 1 "Name:" | tail -n1 | awk '{print $2}' || echo "unknown") + log "IP домена $MAIN_DOMAIN: $DOMAIN_IP" + + if [ "$SERVER_IP" = "$DOMAIN_IP" ]; then + success "DNS запись настроена корректно" + return 0 + else + warning "DNS запись может быть настроена неверно" + warning "Сервер: $SERVER_IP, Домен: $DOMAIN_IP" + read -p "Продолжить? (yes/no): " CONTINUE + if [ "$CONTINUE" != "yes" ]; then + error "Настройте DNS запись и попробуйте снова" + fi + fi +} + +# Получение Let's Encrypt сертификата +obtain_letsencrypt() { + log "Получение Let's Encrypt сертификата для $MAIN_DOMAIN..." + + # Формируем список доменов + CERT_DOMAINS="-d $MAIN_DOMAIN" + if [ -n "$ADDITIONAL_DOMAINS" ]; then + IFS=',' read -ra DOMAINS <<< "$ADDITIONAL_DOMAINS" + for domain in "${DOMAINS[@]}"; do + domain=$(echo $domain | xargs) # trim whitespace + if [ -n "$domain" ]; then + CERT_DOMAINS="$CERT_DOMAINS -d $domain" + log "Добавлен домен: $domain" + fi + done + fi + + log "Домены для сертификата: $CERT_DOMAINS" + + # Временно останавливаем nginx для standalone режима + if systemctl is-active --quiet nginx; then + log "Остановка nginx для получения сертификата..." + sudo systemctl stop nginx + NGINX_WAS_RUNNING=true + else + NGINX_WAS_RUNNING=false + fi + + # Получаем сертификат в standalone режиме + if sudo certbot certonly --standalone \ + $CERT_DOMAINS \ + --email "$LETSENCRYPT_EMAIL" \ + --agree-tos \ + --non-interactive \ + --expand; then + + success "Сертификат получен успешно" + + # Запускаем nginx обратно + if [ "$NGINX_WAS_RUNNING" = true ]; then + sudo systemctl start nginx + fi + + return 0 + else + error "Не удалось получить сертификат" + fi +} + +# Создание самоподписанного сертификата +create_selfsigned() { + log "Создание самоподписанного сертификата для $MAIN_DOMAIN..." + + # Создаем директории + sudo mkdir -p /etc/ssl/private /etc/ssl/certs + + # Генерируем ключ и сертификат + sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout "/etc/ssl/private/${MAIN_DOMAIN}.key" \ + -out "/etc/ssl/certs/${MAIN_DOMAIN}.crt" \ + -subj "/C=US/ST=State/L=City/O=CatLink/CN=${MAIN_DOMAIN}" \ + -extensions v3_req \ + -config <(cat < HTTPS redirect +server { + listen 80; + server_name $MAIN_DOMAIN${ADDITIONAL_DOMAINS:+ $ADDITIONAL_DOMAINS}; + + # Let's Encrypt challenge + location /.well-known/acme-challenge/ { + root /var/www/html; + } + + # Redirect all other requests to HTTPS + location / { + return 301 https://\$server_name\$request_uri; + } +} + +# HTTPS server +server { + listen 443 ssl http2; + server_name $MAIN_DOMAIN${ADDITIONAL_DOMAINS:+ $ADDITIONAL_DOMAINS}; + + # SSL Configuration + ssl_certificate $SSL_CERT; + ssl_certificate_key $SSL_KEY; + + # SSL Security + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; + + # Frontend (Next.js) + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection 'upgrade'; + 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; + proxy_cache_bypass \$http_upgrade; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + # Backend API + location /api/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + 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; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + # Admin interface + location /admin/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + 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 /static/ { + proxy_pass http://127.0.0.1:8000; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Media files + location /media/ { + proxy_pass http://127.0.0.1:8000; + expires 1y; + add_header Cache-Control "public"; + } + + # Security + location ~ /\\.ht { + deny all; + } + + location = /robots.txt { + proxy_pass http://127.0.0.1:8000; + access_log off; + } + + location = /favicon.ico { + proxy_pass http://127.0.0.1:3000; + access_log off; + } +} +EOF + + # Включаем SSL конфигурацию + sudo ln -sf /etc/nginx/sites-available/catlink-ssl /etc/nginx/sites-enabled/catlink + + # Проверяем конфигурацию + if sudo nginx -t; then + success "Конфигурация nginx обновлена" + sudo systemctl reload nginx + else + error "Ошибка в конфигурации nginx" + fi +} + +# Настройка автообновления сертификатов +setup_auto_renewal() { + log "Настройка автообновления Let's Encrypt сертификатов..." + + # Создаем скрипт обновления + sudo tee /usr/local/bin/certbot-renew-catlink << 'EOF' +#!/bin/bash +# CatLink SSL certificate renewal script + +certbot renew --quiet --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx" + +# Проверяем успешность обновления +if [ $? -eq 0 ]; then + echo "$(date): SSL certificates renewed successfully" >> /var/log/catlink-ssl.log +else + echo "$(date): SSL certificate renewal failed" >> /var/log/catlink-ssl.log +fi +EOF + + sudo chmod +x /usr/local/bin/certbot-renew-catlink + + # Добавляем в crontab + (sudo crontab -l 2>/dev/null | grep -v certbot-renew-catlink; echo "0 12 * * * /usr/local/bin/certbot-renew-catlink") | sudo crontab - + + success "Автообновление сертификатов настроено" +} + +# Проверка статуса SSL +check_ssl_status() { + log "Проверка статуса SSL..." + + if [ -f "/etc/letsencrypt/live/${MAIN_DOMAIN}/fullchain.pem" ]; then + CERT_EXPIRY=$(openssl x509 -enddate -noout -in "/etc/letsencrypt/live/${MAIN_DOMAIN}/fullchain.pem" | cut -d= -f2) + success "Let's Encrypt сертификат активен до: $CERT_EXPIRY" + elif [ -f "/etc/ssl/certs/${MAIN_DOMAIN}.crt" ]; then + CERT_EXPIRY=$(openssl x509 -enddate -noout -in "/etc/ssl/certs/${MAIN_DOMAIN}.crt" | cut -d= -f2) + warning "Самоподписанный сертификат активен до: $CERT_EXPIRY" + else + error "SSL сертификат не найден" + fi + + # Проверяем HTTPS соединение + if command -v curl &> /dev/null; then + if curl -s -I "https://${MAIN_DOMAIN}" | grep -q "HTTP"; then + success "HTTPS соединение работает" + else + warning "HTTPS соединение может не работать" + fi + fi +} + +# Основное меню +main() { + echo "🔒 ===== CatLink SSL Certificate Manager =====" + echo "" + + check_env + + echo "Выберите действие:" + echo "1) Получить Let's Encrypt сертификат (рекомендуется)" + echo "2) Создать самоподписанный сертификат (для тестирования)" + echo "3) Проверить статус существующих сертификатов" + echo "4) Настроить автообновление" + echo "5) Обновить nginx конфигурацию" + echo "" + read -p "Выберите опцию (1-5): " choice + + case $choice in + 1) + install_certbot + check_dns + obtain_letsencrypt + update_nginx_ssl "letsencrypt" + setup_auto_renewal + check_ssl_status + ;; + 2) + create_selfsigned + update_nginx_ssl "selfsigned" + check_ssl_status + ;; + 3) + check_ssl_status + ;; + 4) + setup_auto_renewal + ;; + 5) + echo "Какой тип SSL использовать?" + echo "1) Let's Encrypt" + echo "2) Самоподписанный" + read -p "Выберите (1-2): " ssl_type + if [ "$ssl_type" = "1" ]; then + update_nginx_ssl "letsencrypt" + else + update_nginx_ssl "selfsigned" + fi + ;; + *) + error "Неверный выбор" + ;; + esac + + echo "" + success "SSL настройка завершена!" + echo "" + echo "🌐 Проверьте сайт: https://${MAIN_DOMAIN}" +} + +# Запуск +main "$@" \ No newline at end of file