Files
links/Makefile
Andrey K. Choi fd76f56249
Some checks failed
continuous-integration/drone/push Build is failing
🚀 Расширена команда build-prod с автоматической настройкой nginx
 Новые возможности:
- build-prod теперь проверяет и устанавливает nginx + certbot
- Автоматическая настройка проксирования порта 80 → 3000 (frontend)
- Настройка маршрутизации API/admin → порт 8000 (backend)
- SSL конфигурация с современными стандартами безопасности

🔧 Новые команды:
- make build-prod - сборка + nginx настройка
- make ssl-cert - получение SSL сертификата
- make deploy-full - полное развертывание с SSL

📝 Документация:
- docs/NGINX_DEPLOYMENT.md - подробное руководство
- scripts/test-nginx-config.sh - тестовый скрипт

🌐 Маршрутизация:
- https://links.shareon.kr/ → localhost:3000 (Next.js)
- https://links.shareon.kr/api/ → localhost:8000 (Django)
- https://links.shareon.kr/admin/ → localhost:8000 (Django)

🔒 Безопасность: HTTPS редирект, HSTS, защитные заголовки
2025-11-02 11:05:51 +09:00

481 lines
19 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters

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

# CatLink Development and Deployment Makefile
# ================================================
# Docker Compose command detection
DOCKER_COMPOSE := $(shell which docker-compose 2>/dev/null || echo "docker compose")
.PHONY: help install update dev build deploy ssl clean logs test restart shell backup restore
# Default target
help: ## Показать доступные команды
@echo "CatLink - Makefile Commands"
@echo "=========================="
@echo ""
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
@echo ""
# === Development Commands ===
install: ## Установка и первый запуск
@echo "🚀 Установка CatLink..."
@./setup.sh
@echo "✅ Установка завершена!"
@echo "📱 Frontend: http://localhost:3000"
@echo "🔧 Backend API: http://localhost:8000"
@echo "📊 Admin: http://localhost:8000/admin"
dev: ## Запуск в режиме разработки
@echo "🔧 Запуск в режиме разработки..."
@$(DOCKER_COMPOSE) up
dev-bg: ## Запуск в фоне для разработки
@echo "🔧 Запуск в фоне..."
@$(DOCKER_COMPOSE) up -d
@echo "✅ Запущено в фоне"
@echo "📱 Frontend: http://localhost:3000"
@echo "🔧 Backend: http://localhost:8000"
up: ## Запуск с пересборкой (legacy)
@$(DOCKER_COMPOSE) up -d --build
down: ## Остановка всех сервисов
@echo "⏹️ Остановка сервисов..."
@$(DOCKER_COMPOSE) down
@echo "✅ Сервисы остановлены"
stop: ## Остановка всех сервисов (alias)
@$(MAKE) down
restart: ## Перезапуск сервисов
@echo "🔄 Перезапуск сервисов..."
@$(DOCKER_COMPOSE) down
@$(DOCKER_COMPOSE) up -d
@echo "✅ Сервисы перезапущены"
# === Build Commands ===
build: ## Сборка без кэша
@echo "🏗️ Сборка контейнеров..."
@$(DOCKER_COMPOSE) build --no-cache
@echo "✅ Сборка завершена"
build-prod: ## Сборка для продакшена с настройкой nginx
@echo "🏗️ Сборка для продакшена..."
@$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml build --no-cache
@echo "🔧 Проверка и настройка nginx + certbot..."
@bash -c 'if ! command -v nginx &> /dev/null; then \
echo "📥 Установка nginx..."; \
sudo apt update && sudo apt install -y nginx; \
else \
echo "✅ nginx уже установлен"; \
fi'
@bash -c 'if ! command -v certbot &> /dev/null; then \
echo "📥 Установка certbot..."; \
sudo apt update && sudo apt install -y certbot python3-certbot-nginx; \
else \
echo "✅ certbot уже установлен"; \
fi'
@echo "⚙️ Настройка nginx конфигурации..."
@sudo bash -c 'cat > /etc/nginx/sites-available/links << EOF\n\
server {\n\
listen 80;\n\
server_name links.shareon.kr sharon.kr;\n\
\n\
# Redirect all HTTP requests to HTTPS\n\
return 301 https://\$$server_name\$$request_uri;\n\
}\n\
\n\
server {\n\
listen 443 ssl http2;\n\
server_name links.shareon.kr sharon.kr;\n\
\n\
# SSL certificates (will be configured by certbot)\n\
# ssl_certificate /etc/letsencrypt/live/links.shareon.kr/fullchain.pem;\n\
# ssl_certificate_key /etc/letsencrypt/live/links.shareon.kr/privkey.pem;\n\
\n\
# Modern SSL configuration\n\
ssl_protocols TLSv1.2 TLSv1.3;\n\
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;\n\
ssl_prefer_server_ciphers off;\n\
ssl_session_cache shared:SSL:10m;\n\
\n\
# Security headers\n\
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;\n\
add_header X-Frame-Options DENY;\n\
add_header X-Content-Type-Options nosniff;\n\
add_header X-XSS-Protection "1; mode=block";\n\
\n\
# Proxy to frontend (Next.js)\n\
location / {\n\
proxy_pass http://localhost:3000;\n\
proxy_http_version 1.1;\n\
proxy_set_header Upgrade \$$http_upgrade;\n\
proxy_set_header Connection "upgrade";\n\
proxy_set_header Host \$$host;\n\
proxy_set_header X-Real-IP \$$remote_addr;\n\
proxy_set_header X-Forwarded-For \$$proxy_add_x_forwarded_for;\n\
proxy_set_header X-Forwarded-Proto \$$scheme;\n\
proxy_cache_bypass \$$http_upgrade;\n\
proxy_read_timeout 86400;\n\
}\n\
\n\
# Proxy API requests to backend (Django)\n\
location /api/ {\n\
proxy_pass http://localhost:8000;\n\
proxy_set_header Host \$$host;\n\
proxy_set_header X-Real-IP \$$remote_addr;\n\
proxy_set_header X-Forwarded-For \$$proxy_add_x_forwarded_for;\n\
proxy_set_header X-Forwarded-Proto \$$scheme;\n\
}\n\
\n\
# Proxy admin requests to backend (Django)\n\
location /admin/ {\n\
proxy_pass http://localhost:8000;\n\
proxy_set_header Host \$$host;\n\
proxy_set_header X-Real-IP \$$remote_addr;\n\
proxy_set_header X-Forwarded-For \$$proxy_add_x_forwarded_for;\n\
proxy_set_header X-Forwarded-Proto \$$scheme;\n\
}\n\
\n\
# Serve static files from Django\n\
location /static/ {\n\
proxy_pass http://localhost:8000;\n\
proxy_set_header Host \$$host;\n\
expires 1y;\n\
add_header Cache-Control "public, immutable";\n\
}\n\
\n\
# Serve media files from Django\n\
location /media/ {\n\
proxy_pass http://localhost:8000;\n\
proxy_set_header Host \$$host;\n\
expires 1y;\n\
add_header Cache-Control "public";\n\
}\n\
}\n\
EOF'
@sudo ln -sf /etc/nginx/sites-available/links /etc/nginx/sites-enabled/
@sudo rm -f /etc/nginx/sites-enabled/default
@echo "🧪 Проверка конфигурации nginx..."
@sudo nginx -t
@echo "🔄 Перезапуск nginx..."
@sudo systemctl restart nginx
@sudo systemctl enable nginx
@echo "✅ Продакшен сборка и nginx настройка завершены"
@echo "📝 Для получения SSL сертификата выполните:"
@echo " sudo certbot --nginx -d links.shareon.kr -d sharon.kr"
ssl-cert: ## Получить SSL сертификат от Let's Encrypt
@echo "🔒 Получение SSL сертификата..."
@sudo certbot --nginx -d links.shareon.kr -d sharon.kr --non-interactive --agree-tos --email shadow85@list.ru
@echo "✅ SSL сертификат получен и настроен"
up-prod: ## Запуск в продакшен режиме
@echo "🚀 Запуск в продакшен режиме..."
@$(DOCKER_COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml up -d
@echo "✅ Продакшен запущен"
@echo "📱 Frontend: http://localhost:3000"
@echo "🔧 Backend: http://localhost:8000"
update: ## Обновление зависимостей и пересборка
@echo "📦 Обновление зависимостей..."
@git pull
@$(DOCKER_COMPOSE) down
@$(DOCKER_COMPOSE) build --no-cache
@$(DOCKER_COMPOSE) up -d
@echo "✅ Обновление завершено"
# === Production Deployment ===
deploy-full: ## Полное развертывание в продакшен с SSL
@echo "🚀 Полное развертывание в продакшен..."
@make build-prod
@make up-prod
@sleep 10
@make migrate
@make ssl-cert
@echo "✅ Полное развертывание завершено!"
@echo "🌐 Сайт доступен по адресу: https://links.shareon.kr"
deploy: ## Развертывание в продакшен
@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 "✅ Продакшен развернут"
# === 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_setup.sh
@echo "✅ SSL конфигурация создана"
# === Database Management ===
migrate: ## Выполнить миграции базы данных
@echo "🗄️ Выполнение миграций..."
@$(DOCKER_COMPOSE) exec web python manage.py migrate
@echo "✅ Миграции выполнены"
makemigrations: ## Создать новые миграции
@echo "🗄️ Создание миграций..."
@$(DOCKER_COMPOSE) exec web python manage.py makemigrations
@echo "✅ Миграции созданы"
superuser: ## Создать суперпользователя
@echo "👤 Создание суперпользователя..."
@$(DOCKER_COMPOSE) exec web python manage.py createsuperuser
@echo "✅ Суперпользователь создан"
# === Maintenance ===
logs: ## Просмотр логов
@$(DOCKER_COMPOSE) logs -f
logs-web: ## Логи backend
@$(DOCKER_COMPOSE) logs -f web
logs-frontend: ## Логи frontend
@$(DOCKER_COMPOSE) logs -f frontend
shell: ## Django shell
@$(DOCKER_COMPOSE) exec web python manage.py shell
shell-db: ## Подключение к базе данных
@$(DOCKER_COMPOSE) exec db psql -U links_user -d links_db
backup: ## Создать бэкап базы данных
@echo "💾 Создание бэкапа..."
@mkdir -p backups
@$(DOCKER_COMPOSE) exec db pg_dump -U links_user links_db > backups/backup_$(shell date +%Y%m%d_%H%M%S).sql
@echo "✅ Бэкап создан в папке backups/"
restore: ## Восстановить из бэкапа
@echo "📥 Восстановление из бэкапа..."
@ls -la backups/
@read -p "Введите имя файла бэкапа: " BACKUP_FILE; \
docker-compose exec -T db psql -U links_user -d links_db < backups/$$BACKUP_FILE
@echo "✅ База данных восстановлена"
# === Testing and Quality ===
test: ## Запуск тестов
@echo "🧪 Запуск тестов..."
@$(DOCKER_COMPOSE) exec web python manage.py test
@echo "✅ Тесты завершены"
test-legacy: ## Запуск тестов (legacy pytest)
@$(DOCKER_COMPOSE) exec web pytest --maxfail=1 --disable-warnings -q
lint: ## Проверка кода
@echo "🔍 Проверка кода..."
@$(DOCKER_COMPOSE) exec web flake8 . || true
@$(DOCKER_COMPOSE) exec frontend npm run lint || true
@echo "✅ Проверка завершена"
format: ## Форматирование кода
@echo "🎨 Форматирование кода..."
@$(DOCKER_COMPOSE) exec web black . || true
@$(DOCKER_COMPOSE) exec frontend npm run format || true
@echo "✅ Код отформатирован"
# === CI/CD Operations ===
ci-lint: ## Локальный запуск CI линтинга
@echo "🔍 Запуск CI линтинга локально..."
@bash ./scripts/ci/lint.sh
@echo "✅ CI линтинг завершен"
ci-test: ## Локальный запуск CI тестов
@echo "🧪 Запуск CI тестов локально..."
@bash ./scripts/ci/test.sh
@echo "✅ CI тесты завершены"
ci-security: ## Локальный запуск проверки безопасности
@echo "🔒 Запуск проверки безопасности..."
@bash ./scripts/ci/security-scan.sh
@echo "✅ Проверка безопасности завершена"
ci-build: ## Локальная сборка как в CI
@echo "🏗️ Запуск CI сборки локально..."
@bash ./scripts/ci/build.sh
@echo "✅ CI сборка завершена"
ci-build-prod: ## Локальная сборка продакшен образов
@echo "🏗️ Сборка продакшен образов..."
@bash ./scripts/ci/build-production.sh
@echo "✅ Продакшен образы собраны"
ci-publish: ## Публикация образов в registry
@echo "📤 Публикация образов..."
@bash ./scripts/ci/publish.sh
@echo "✅ Образы опубликованы"
ci-deploy-staging: ## Деплой на staging
@echo "🚀 Деплой на staging..."
@bash ./scripts/ci/deploy-staging.sh
@echo "✅ Staging деплой завершен"
ci-deploy-production: ## Деплой на production
@echo "🚀 Деплой на production..."
@bash ./scripts/ci/deploy-production.sh
@echo "✅ Production деплой завершен"
ci-pipeline: ## Полный CI/CD пайплайн локально
@echo "🚀 Запуск полного CI/CD пайплайна..."
@$(MAKE) ci-lint
@$(MAKE) ci-test
@$(MAKE) ci-security
@$(MAKE) ci-build
@echo "✅ Полный пайплайн завершен"
drone-validate: ## Валидация .drone.yml
@echo "✅ Валидация Drone конфигурации..."
@if command -v drone >/dev/null 2>&1; then \
drone lint .drone.yml; \
else \
echo "⚠️ Drone CLI не установлен, используем docker..."; \
docker run --rm -v "$(PWD):/repo" -w /repo drone/cli:alpine lint .drone.yml; \
fi
@echo "✅ Валидация завершена"
drone-sign: ## Подпись .drone.yml (требует настройки)
@echo "🔐 Подпись Drone конфигурации..."
@if [ -z "$(DRONE_SECRET)" ]; then \
echo "❌ DRONE_SECRET не установлен"; \
exit 1; \
fi
@drone sign smartsoltech/links --save
@echo "✅ Конфигурация подписана"
# === Helper scripts and automation ===
generate-env: ## Сгенерировать .env (автоматически из .env.example)
@echo "🧭 Генерация .env файла из .env.example"
@bash ./scripts/generate_env.sh --yes
generate-env-interactive: ## Сгенерировать .env (интерактивно)
@echo "🧭 Генерация .env файла (интерактивно)"
@bash ./scripts/generate_env.sh
generate-env-prod: ## Сгенерировать .env для продакшена
@echo "🚀 Генерация .env для продакшена"
@bash ./scripts/generate_env.sh --yes
@echo "⚠️ ВНИМАНИЕ: Измените значения в .env для продакшена!"
@echo " - DJANGO_SECRET_KEY (сгенерируйте новый)"
@echo " - DJANGO_DEBUG=False"
@echo " - DATABASE_PASSWORD (установите надежный пароль)"
@echo " - DJANGO_ALLOWED_HOSTS (добавьте ваш домен)"
create-superuser-noninteractive: ## Создать/обновить суперпользователя из .env (неинтерактивно)
@echo "👤 Создание/обновление суперпользователя из .env"
@bash ./scripts/create_superuser.sh
rebuild-no-cache: ## Пересобрать и поднять контейнеры без кэша (scripts/rebuild_no_cache.sh)
@echo "♻️ Пересборка контейнеров без кэша"
@bash ./scripts/rebuild_no_cache.sh
migrate-full: ## makemigrations, migrate и collectstatic
@echo "⚙️ Полный набор операций миграции и сбора статики"
@bash ./scripts/migrate_and_collect.sh
ssl-host-setup: ## Локальная установка nginx + certbot и настройка прокси (HOST)
@echo "🔐 Настройка nginx/letsencrypt на хосте"
@echo "Использование: make ssl-host-setup DOMAIN=example.com EMAIL=you@example.com"
@if [ -z "${DOMAIN}" ]; then echo "ERROR: DOMAIN variable required"; exit 1; fi
@if [ -z "${EMAIL}" ]; then echo "ERROR: EMAIL variable required"; exit 1; fi
@sudo bash ./scripts/ssl_setup.sh ${DOMAIN} ${EMAIL}
# === Cleanup ===
clean: ## Очистка системы
@echo "🧹 Очистка..."
@$(DOCKER_COMPOSE) down -v
@docker system prune -f
@docker volume prune -f
@echo "✅ Очистка завершена"
clean-all: ## Полная очистка (ОСТОРОЖНО!)
@echo "⚠️ ВНИМАНИЕ: Это удалит ВСЕ данные!"
@read -p "Продолжить? (yes/no): " CONFIRM; \
if [ "$$CONFIRM" = "yes" ]; then \
docker-compose down -v; \
docker system prune -af; \
docker volume prune -f; \
sudo rm -rf storage/; \
echo "✅ Полная очистка завершена"; \
else \
echo "❌ Отменено"; \
fi
# === Status and Info ===
status: ## Статус сервисов
@echo "📊 Статус сервисов:"
@$(DOCKER_COMPOSE) ps
@echo ""
@echo "🌐 URL-адреса:"
@echo " Frontend: http://localhost:3000"
@echo " Backend: http://localhost:8000"
@echo " Admin: http://localhost:8000/admin"
@echo ""
health: ## Проверка здоровья сервисов
@echo "🏥 Проверка здоровья..."
@curl -s http://localhost:3000 > /dev/null && echo "✅ Frontend: OK" || echo "❌ Frontend: ERROR"
@curl -s http://localhost:8000/api/ > /dev/null && echo "✅ Backend: OK" || echo "❌ Backend: ERROR"
@$(DOCKER_COMPOSE) exec db pg_isready -U links_user && echo "✅ Database: OK" || echo "❌ Database: ERROR"
info: ## Информация о проекте
@echo "📋 CatLink - Информация о проекте"
@echo "================================="
@echo "🐱 Название: CatLink"
@echo "📱 Frontend: Next.js 15"
@echo "🔧 Backend: Django 5.2"
@echo "🗄️ База данных: PostgreSQL"
@echo "🐳 Контейнеризация: Docker"
@echo ""
@echo "📁 Структура:"
@echo " frontend/ - Next.js приложение"
@echo " backend/ - Django API"
@echo " storage/ - Загруженные файлы"
@echo ""
@echo "🛠️ Команды разработки:"
@echo " make install - Первая установка"
@echo " make dev - Режим разработки"
@echo " make deploy - Продакшен"
@echo ""
# === Advanced Operations ===
scale: ## Масштабирование сервисов
@echo "📈 Масштабирование..."
@read -p "Количество экземпляров web: " WEB_COUNT; \
read -p "Количество экземпляров frontend: " FRONTEND_COUNT; \
docker-compose up -d --scale web=$$WEB_COUNT --scale frontend=$$FRONTEND_COUNT
@echo "✅ Масштабирование применено"
monitor: ## Мониторинг ресурсов
@echo "📊 Мониторинг ресурсов..."
@docker stats
reset: ## Сброс к заводским настройкам
@echo "⚠️ ВНИМАНИЕ: Сброс к заводским настройкам!"
@read -p "Продолжить? (yes/no): " CONFIRM; \
if [ "$$CONFIRM" = "yes" ]; then \
$(MAKE) clean-all; \
$(MAKE) install; \
echo "✅ Сброс завершен"; \
else \
echo "❌ Отменено"; \
fi