🚀 Добавлен мастер-скрипт развертывания с полной автоматизацией
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
✨ Новые возможности: - Мастер-развертывание с автоматической настройкой всех компонентов - Генерация безопасных .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 сертификатов
This commit is contained in:
186
COMMANDS.md
Normal file
186
COMMANDS.md
Normal file
@@ -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`
|
||||
323
DEPLOYMENT.md
Normal file
323
DEPLOYMENT.md
Normal file
@@ -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 готов к использованию!**
|
||||
66
Makefile
66
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 ===
|
||||
|
||||
36
README.md
36
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
|
||||
```
|
||||
|
||||
## ✨ Возможности
|
||||
|
||||
|
||||
|
||||
681
scripts/master-deploy.sh
Executable file
681
scripts/master-deploy.sh
Executable file
@@ -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 "$@"
|
||||
240
scripts/pre-deploy-check.sh
Executable file
240
scripts/pre-deploy-check.sh
Executable file
@@ -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
|
||||
423
scripts/ssl-manager.sh
Executable file
423
scripts/ssl-manager.sh
Executable file
@@ -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 <<EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
CN = ${MAIN_DOMAIN}
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = ${MAIN_DOMAIN}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Устанавливаем права
|
||||
sudo chmod 600 "/etc/ssl/private/${MAIN_DOMAIN}.key"
|
||||
sudo chmod 644 "/etc/ssl/certs/${MAIN_DOMAIN}.crt"
|
||||
|
||||
success "Самоподписанный сертификат создан"
|
||||
}
|
||||
|
||||
# Обновление nginx конфигурации для SSL
|
||||
update_nginx_ssl() {
|
||||
local ssl_type=$1
|
||||
|
||||
log "Обновление nginx конфигурации для SSL ($ssl_type)..."
|
||||
|
||||
if [ "$ssl_type" = "letsencrypt" ]; then
|
||||
SSL_CERT="/etc/letsencrypt/live/${MAIN_DOMAIN}/fullchain.pem"
|
||||
SSL_KEY="/etc/letsencrypt/live/${MAIN_DOMAIN}/privkey.pem"
|
||||
else
|
||||
SSL_CERT="/etc/ssl/certs/${MAIN_DOMAIN}.crt"
|
||||
SSL_KEY="/etc/ssl/private/${MAIN_DOMAIN}.key"
|
||||
fi
|
||||
|
||||
# Создаем SSL конфигурацию
|
||||
sudo tee /etc/nginx/sites-available/catlink-ssl << EOF
|
||||
# CatLink SSL nginx configuration
|
||||
# Generated $(date)
|
||||
|
||||
# HTTP -> 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 "$@"
|
||||
Reference in New Issue
Block a user