From a64d8469df946aeb807cc2d737f93f5cac7c301f Mon Sep 17 00:00:00 2001 From: jze9 Date: Sun, 17 May 2026 19:32:48 +0500 Subject: [PATCH] start deplou --- .env.example | 39 ++++--- DEPLOY.md | 170 +++++++++++++++++++++++++++++++ web-react/src/App.jsx | 3 +- web-react/src/pages/NotFound.jsx | 45 ++++++++ 4 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 DEPLOY.md create mode 100644 web-react/src/pages/NotFound.jsx diff --git a/.env.example b/.env.example index 2b2b00d..a118964 100644 --- a/.env.example +++ b/.env.example @@ -1,29 +1,28 @@ -DATABASE_URL=postgresql+asyncpg://user:password@host:5432/news -REDIS_URL=redis://host:6379/0 -JWT_SECRET=your-very-secret-key-change-me +# ============= БАЗА ДАННЫХ ============= +DATABASE_URL=postgresql+asyncpg://news_admin:news_secure_2026@192.168.1.11:5432/news +# ============= MINIO / ХРАНИЛИЩЕ ============= +MINIO_ENDPOINT=minio:9000 MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MINIO_BUCKET=news-media MINIO_PUBLIC_URL=http://localhost:9000 +# ============= JWT / БЕЗОПАСНОСТЬ ============= +JWT_SECRET=your-super-secret-key-change-in-production +JWT_ALGORITHM=HS256 + +# ============= ВКОНТАКТЕ API ============= +VK_API_VERSION=5.131 +VK_SERVICE_TOKEN=your_vk_service_token_here + +# ============= АДМИНИСТРАТОР ============= +ADMIN_USERNAME=admin +ADMIN_PASSWORD=your-strong-password + +# ============= ДОКУМЕНТАЦИЯ API ============= DOCS_USERNAME=admin DOCS_PASSWORD=admin -# CORS: разрешённые домены через запятую -ALLOWED_ORIGINS=http://localhost,http://localhost:80 - -ADMIN_USERNAME=admin -ADMIN_PASSWORD=changeme -# VK импорт (необязательно) -# Сервисный токен приложения: vk.com/apps → Настройки → Сервисный ключ доступа -VK_ACCESS_TOKEN= -# ID групп через запятую (без минуса): 12345,67890 -VK_GROUP_IDS= -# Статус импортированных постов: published или draft -VK_IMPORT_STATUS=published -# Сколько последних постов проверять за раз -VK_POSTS_PER_RUN=20 -# Время запуска импорта (UTC) -VK_IMPORT_HOUR=6 -VK_IMPORT_MINUTE=0 +# ============= ЛОГИРОВАНИЕ ============= +LOG_LEVEL=INFO diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..2ac3353 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,170 @@ +# Развёртывание news_flet + +## Требования + +- Docker & Docker Compose (20.10+) +- Git +- PostgreSQL 13+ (внешний сервер или локальный контейнер) +- MinIO S3 (локальный в Docker или облачный) + +## Быстрый старт + +### 1. Клонирование и подготовка + +```bash +git clone news_flet +cd news_flet +cp .env.example .env +``` + +### 2. Редактирование .env + +Заполнить критические переменные: +```bash +DATABASE_URL=postgresql+asyncpg://user:password@host:5432/news +JWT_SECRET=<генерируем на продакшене> +ADMIN_PASSWORD=<сильный пароль> +VK_SERVICE_TOKEN= +``` + +### 3. Запуск контейнеров + +```bash +docker compose build +docker compose up -d +``` + +Сервис поднимается на: +- **Frontend (React)**: http://localhost:80 +- **API**: http://localhost/api/ (за nginx) +- **MinIO**: http://localhost:9000 (если локально) +- **API Docs**: http://localhost/api/docs + +### 4. Первый запуск + +При старте API: +- Автоматически запускает Alembic миграции +- Создаёт таблицы в БД (если нет) +- Создаёт default админ юзера (если нет) + +Логин админ-панели: +``` +URL: http://localhost/admin/login +Username: admin +Password: <из .env ADMIN_PASSWORD> +``` + +## Структура docker-compose + +```yaml +services: + api: # FastAPI + Alembic + VK-парсер + web: # React SPA + nginx + minio: # S3-совместимое хранилище (опционально) +``` + +## Переменные окружения + +| Переменная | Обязательна | Описание | +|-----------|-----------|---------| +| `DATABASE_URL` | ✅ | PostgreSQL + asyncpg подключение | +| `JWT_SECRET` | ✅ | Ключ для подписи JWT токенов | +| `ADMIN_PASSWORD` | ✅ | Пароль дефолт админа | +| `VK_SERVICE_TOKEN` | ✅ | Токен сервиса ВКонтакте | +| `MINIO_ENDPOINT` | — | MinIO хост (default: `minio:9000`) | +| `MINIO_PUBLIC_URL` | — | Публичный URL для доступа к файлам | +| `LOG_LEVEL` | — | DEBUG/INFO/WARNING (default: INFO) | + +## Архитектура + +### Frontend (`web-react/`) +- React 18 + React Router +- Admin панель: управление статьями, медиа, источниками ВК +- Публичный фид с поиском по категориям и тегам +- TipTap редактор с поддержкой видео, картинок, таблиц + +### Backend (`api/`) +- FastAPI + SQLAlchemy async +- VK-парсер: загрузка статей из групп/публичных страниц +- yt-dlp: скачивание видео из ВК на MinIO +- Slug-based медиа: организованное хранилище на S3 +- JWT auth + role-based access control + +### Storage (`minio/`) +- S3-совместимое хранилище +- Структура: `articles/{slug}-{uuid}/images/` +- Публичный доступ к медиа через HTTP + +## Миграции БД + +При запуске API проверяет и применяет миграции через Alembic: + +```bash +# Ручно (внутри контейнера api): +docker compose exec api alembic upgrade head +``` + +Новая миграция при изменении схемы: +```bash +docker compose exec api alembic revision --autogenerate -m "description" +``` + +## Мониторинг + +### Логи + +```bash +docker compose logs -f api +docker compose logs -f web +``` + +### API документация + +Доступна по адресу `/api/docs` (требует auth) + +## Production рекомендации + +- 🔒 Установить SSL сертификат (Let's Encrypt) +- 🔐 Сменить все default пароли и токены +- 💾 Настроить резервное копирование БД +- 📊 Включить мониторинг (Prometheus/Grafana) +- 🛡️ Настроить firewall и rate limiting +- 🌍 Использовать CDN для медиа-файлов + +## Решение проблем + +### БД не подключается +```bash +# Проверить подключение: +docker compose exec api python -c "import asyncio; from bd.database import engine; asyncio.run(engine.connect())" +``` + +### MinIO не доступен +```bash +# Проверить health: +curl http://localhost:9000/minio/health/live +``` + +### Миграции не применились +```bash +# Ручной запуск: +docker compose exec api alembic upgrade head +``` + +## Развёртывание на сервере + +1. SSH на сервер +2. `git clone ...` → `cd news_flet` +3. Скопировать и отредактировать `.env` +4. `docker compose up -d` +5. Проверить: `curl http://localhost/` + +Если используется reverse proxy (nginx): +```nginx +location / { + proxy_pass http://localhost:80; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +``` diff --git a/web-react/src/App.jsx b/web-react/src/App.jsx index 7fc12a5..56ef133 100644 --- a/web-react/src/App.jsx +++ b/web-react/src/App.jsx @@ -5,6 +5,7 @@ import { useTheme } from './hooks/useTheme' import NewsFeed from './pages/NewsFeed' import NewsDetail from './pages/NewsDetail' +import NotFound from './pages/NotFound' import Login from './pages/admin/Login' import Dashboard from './pages/admin/Dashboard' import ArticlesList from './pages/admin/ArticlesList' @@ -36,7 +37,7 @@ export default function App() { } /> } /> - } /> + } /> ) } diff --git a/web-react/src/pages/NotFound.jsx b/web-react/src/pages/NotFound.jsx new file mode 100644 index 0000000..2d31d45 --- /dev/null +++ b/web-react/src/pages/NotFound.jsx @@ -0,0 +1,45 @@ +import React from 'react' +import { useNavigate } from 'react-router-dom' + +export default function NotFound() { + const navigate = useNavigate() + + return ( +
+

404

+

Страница не найдена

+

+ Кажется, такой страницы не существует +

+ +
+ ) +}