🚀 Добавлен мастер-скрипт развертывания с полной автоматизацией
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:
2025-11-04 14:07:58 +09:00
parent 735c1984f9
commit e1bb1ab90a
7 changed files with 1933 additions and 22 deletions

186
COMMANDS.md Normal file
View 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
View 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 готов к использованию!**

View File

@@ -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 ===

View File

@@ -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
View 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
View 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
View 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 "$@"