REFACTORING DIRECTORIES
This commit is contained in:
parent
c645019380
commit
c8e1d5046c
|
|
@ -0,0 +1 @@
|
||||||
|
{"value": "a63a416be5a5db101fd6db5ca604ae99833d23d0322428f256dd922eb2540c5a"}
|
||||||
199
.env.example
199
.env.example
|
|
@ -1,95 +1,150 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# ENVIRONMENT CONFIGURATION EXAMPLE
|
# MY UPLOADER BOT - ENVIRONMENT CONFIGURATION
|
||||||
# Copy this file to .env and configure your values
|
# =============================================================================
|
||||||
|
# Скопируйте этот файл в .env и настройте под свою среду
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ОСНОВНЫЕ НАСТРОЙКИ
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# Application Settings
|
# Environment: development, production, testing
|
||||||
DEBUG=false
|
NODE_ENV=development
|
||||||
ENVIRONMENT=production
|
DEBUG=true
|
||||||
SECRET_KEY=your-super-secret-key-change-this-in-production
|
|
||||||
ENCRYPTION_KEY=your-encryption-key-for-file-encryption
|
|
||||||
|
|
||||||
# Server Configuration
|
# =============================================================================
|
||||||
HOST=0.0.0.0
|
# DATABASE (PostgreSQL)
|
||||||
PORT=15100
|
# =============================================================================
|
||||||
WORKERS=4
|
|
||||||
AUTO_RELOAD=false
|
|
||||||
|
|
||||||
# Database Configuration (PostgreSQL)
|
DATABASE_URL=postgresql://my_user:CHANGE_ME_SECURE_PASSWORD@localhost:5432/my_uploader_db
|
||||||
DATABASE_URL=postgresql+asyncpg://postgres:password@localhost:5432/myuploader
|
POSTGRES_HOST=localhost
|
||||||
DATABASE_POOL_SIZE=20
|
POSTGRES_PORT=5432
|
||||||
DATABASE_MAX_OVERFLOW=30
|
POSTGRES_DB=my_uploader_db
|
||||||
DATABASE_POOL_TIMEOUT=30
|
POSTGRES_USER=my_user
|
||||||
DATABASE_POOL_RECYCLE=3600
|
POSTGRES_PASSWORD=CHANGE_ME_SECURE_PASSWORD
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# REDIS CACHE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
# Redis Configuration
|
|
||||||
REDIS_URL=redis://localhost:6379/0
|
REDIS_URL=redis://localhost:6379/0
|
||||||
REDIS_POOL_SIZE=10
|
REDIS_HOST=localhost
|
||||||
REDIS_MAX_CONNECTIONS=20
|
REDIS_PORT=6379
|
||||||
REDIS_SOCKET_TIMEOUT=5
|
REDIS_PASSWORD=
|
||||||
REDIS_SOCKET_CONNECT_TIMEOUT=5
|
|
||||||
|
|
||||||
# Security Settings
|
# =============================================================================
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES=60
|
# SECURITY KEYS
|
||||||
REFRESH_TOKEN_EXPIRE_DAYS=30
|
# =============================================================================
|
||||||
PASSWORD_MIN_LENGTH=8
|
# ВАЖНО: Генерируйте новые ключи для production!
|
||||||
RATE_LIMIT_ENABLED=true
|
|
||||||
CORS_ORIGINS=["http://localhost:3000","https://yourdomain.com"]
|
|
||||||
|
|
||||||
# Storage Configuration
|
SECRET_KEY=CHANGE_ME_SECRET_KEY_FOR_PRODUCTION_MIN_32_CHARS
|
||||||
STORAGE_PATH=./data/storage
|
JWT_SECRET=CHANGE_ME_JWT_SECRET_FOR_PRODUCTION_MIN_32_CHARS
|
||||||
MAX_FILE_SIZE=10737418240
|
ENCRYPTION_KEY=CHANGE_ME_ENCRYPTION_KEY_32_CHARS_LONG
|
||||||
MAX_CHUNK_SIZE=10485760
|
|
||||||
CHUNK_SIZE=1048576
|
|
||||||
ENCRYPT_FILES=true
|
|
||||||
CLEANUP_TEMP_FILES=true
|
|
||||||
|
|
||||||
# User Limits
|
# =============================================================================
|
||||||
MAX_UPLOADS_PER_DAY=100
|
# MY NETWORK SETTINGS
|
||||||
MAX_STORAGE_PER_USER=107374182400
|
# =============================================================================
|
||||||
MAX_FILES_PER_USER=10000
|
|
||||||
DAILY_TRANSACTION_LIMIT=10
|
|
||||||
MAX_TRANSACTION_AMOUNT=5
|
|
||||||
|
|
||||||
# TON Blockchain Configuration
|
MY_NETWORK_NODE_ID=local-dev-node
|
||||||
TON_API_ENDPOINT=https://toncenter.com/api/v2
|
MY_NETWORK_PORT=15100
|
||||||
TON_API_KEY=your-ton-api-key
|
MY_NETWORK_HOST=0.0.0.0
|
||||||
TON_TESTNET=false
|
MY_NETWORK_DOMAIN=localhost
|
||||||
TON_WALLET_VERSION=v4
|
MY_NETWORK_SSL_ENABLED=false
|
||||||
|
|
||||||
# Logging Configuration
|
# Bootstrap узлы для подключения к сети
|
||||||
LOG_LEVEL=INFO
|
MY_NETWORK_BOOTSTRAP_NODES=my-public-node-3.projscale.dev:15100
|
||||||
LOG_FORMAT=json
|
|
||||||
|
# =============================================================================
|
||||||
|
# API SETTINGS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
API_HOST=0.0.0.0
|
||||||
|
API_PORT=15100
|
||||||
|
API_WORKERS=2
|
||||||
|
MAX_UPLOAD_SIZE=50MB
|
||||||
|
UPLOAD_PATH=./uploads
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# LOGGING
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
LOG_LEVEL=DEBUG
|
||||||
|
LOG_FORMAT=text
|
||||||
LOG_FILE=./logs/app.log
|
LOG_FILE=./logs/app.log
|
||||||
LOG_ROTATION=daily
|
|
||||||
LOG_RETENTION_DAYS=30
|
|
||||||
|
|
||||||
# Email Configuration (Optional)
|
# =============================================================================
|
||||||
|
# MONITORING (Опционально)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Grafana
|
||||||
|
GRAFANA_PASSWORD=admin123
|
||||||
|
|
||||||
|
# Prometheus
|
||||||
|
PROMETHEUS_RETENTION=15d
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EMAIL SETTINGS (Опционально)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
SMTP_HOST=smtp.gmail.com
|
SMTP_HOST=smtp.gmail.com
|
||||||
SMTP_PORT=587
|
SMTP_PORT=587
|
||||||
SMTP_USERNAME=your-email@gmail.com
|
SMTP_USER=your-email@gmail.com
|
||||||
SMTP_PASSWORD=your-app-password
|
SMTP_PASSWORD=your-app-password
|
||||||
SMTP_TLS=true
|
SMTP_FROM=noreply@yourdomain.com
|
||||||
FROM_EMAIL=noreply@yourdomain.com
|
|
||||||
|
|
||||||
# Monitoring Configuration
|
# =============================================================================
|
||||||
METRICS_ENABLED=true
|
# SOCIAL AUTH (Опционально)
|
||||||
METRICS_PORT=9090
|
# =============================================================================
|
||||||
HEALTH_CHECK_ENABLED=true
|
|
||||||
|
|
||||||
# External Services (Optional)
|
# GitHub OAuth
|
||||||
WEBHOOK_URL=https://yourdomain.com/webhooks
|
GITHUB_CLIENT_ID=your-github-client-id
|
||||||
BACKUP_ENABLED=true
|
GITHUB_CLIENT_SECRET=your-github-client-secret
|
||||||
|
|
||||||
|
# Google OAuth
|
||||||
|
GOOGLE_CLIENT_ID=your-google-client-id
|
||||||
|
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EXTERNAL SERVICES (Опционально)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# AWS S3 (для backup)
|
||||||
|
AWS_ACCESS_KEY_ID=your-aws-access-key
|
||||||
|
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
||||||
|
AWS_BUCKET_NAME=your-backup-bucket
|
||||||
|
AWS_REGION=us-east-1
|
||||||
|
|
||||||
|
# Cloudflare (для CDN)
|
||||||
|
CLOUDFLARE_API_TOKEN=your-cloudflare-token
|
||||||
|
CLOUDFLARE_ZONE_ID=your-zone-id
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# PRODUCTION ТОЛЬКО
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# SSL Сертификаты
|
||||||
|
SSL_CERT_PATH=/etc/ssl/certs/yourdomain.crt
|
||||||
|
SSL_KEY_PATH=/etc/ssl/private/yourdomain.key
|
||||||
|
|
||||||
|
# Backup
|
||||||
BACKUP_SCHEDULE=0 2 * * *
|
BACKUP_SCHEDULE=0 2 * * *
|
||||||
BACKUP_RETENTION_DAYS=30
|
BACKUP_RETENTION_DAYS=30
|
||||||
|
BACKUP_S3_BUCKET=your-backup-bucket
|
||||||
|
|
||||||
# Development Settings (Only for development)
|
# Security
|
||||||
# DEV_RELOAD=true
|
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
|
||||||
# DEV_DEBUG_TOOLBAR=true
|
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
|
||||||
# DEV_PROFILER=true
|
|
||||||
|
|
||||||
# Production Settings (Only for production)
|
# Rate Limiting
|
||||||
# SENTRY_DSN=https://your-sentry-dsn
|
RATE_LIMIT_PER_MINUTE=60
|
||||||
# SSL_ENABLED=true
|
RATE_LIMIT_BURST=10
|
||||||
# SSL_CERT_PATH=/path/to/cert.pem
|
|
||||||
# SSL_KEY_PATH=/path/to/key.pem
|
# =============================================================================
|
||||||
|
# DEVELOPMENT ТОЛЬКО
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Debug mode
|
||||||
|
FLASK_DEBUG=true
|
||||||
|
UVICORN_RELOAD=true
|
||||||
|
|
||||||
|
# Local testing
|
||||||
|
TEST_DATABASE_URL=postgresql://test_user:test_pass@localhost:5433/test_db
|
||||||
187
DOCKER_SETUP.md
187
DOCKER_SETUP.md
|
|
@ -1,187 +0,0 @@
|
||||||
# 🐳 Запуск MY Uploader Bot через Docker
|
|
||||||
|
|
||||||
## 📋 Требования
|
|
||||||
|
|
||||||
- Docker и Docker Compose установлены
|
|
||||||
- Telegram Bot токены от @BotFather
|
|
||||||
|
|
||||||
## ⚡ Быстрый запуск
|
|
||||||
|
|
||||||
### 1. Настройка переменных окружения
|
|
||||||
|
|
||||||
Отредактируйте файл [`.env`](.env) - **ОБЯЗАТЕЛЬНО** заполните Telegram токены:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# ОБЯЗАТЕЛЬНО: Получите токены у @BotFather в Telegram
|
|
||||||
TELEGRAM_API_KEY=123456789:YOUR_ACTUAL_BOT_TOKEN_HERE
|
|
||||||
CLIENT_TELEGRAM_API_KEY=987654321:YOUR_ACTUAL_CLIENT_BOT_TOKEN_HERE
|
|
||||||
```
|
|
||||||
|
|
||||||
Остальные настройки можно оставить по умолчанию для тестирования.
|
|
||||||
|
|
||||||
### 2. Запуск базовых сервисов
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Базовые сервисы (PostgreSQL + Redis + Application)
|
|
||||||
docker-compose -f docker-compose.new.yml up -d postgres redis app
|
|
||||||
|
|
||||||
# Проверка статуса
|
|
||||||
docker-compose -f docker-compose.new.yml ps
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Проверка работы
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Проверка логов приложения
|
|
||||||
docker-compose -f docker-compose.new.yml logs -f app
|
|
||||||
|
|
||||||
# Проверка health endpoints
|
|
||||||
curl http://localhost:15100/health
|
|
||||||
curl http://localhost:15100/api/my/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Веб-интерфейс
|
|
||||||
|
|
||||||
- **Основное приложение**: http://localhost:15100
|
|
||||||
- **MY Network Monitor**: http://localhost:15100/api/my/monitor/
|
|
||||||
- **Метрики**: http://localhost:9090
|
|
||||||
|
|
||||||
## 🔧 Дополнительные профили
|
|
||||||
|
|
||||||
### Мониторинг (Prometheus + Grafana)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml --profile monitoring up -d
|
|
||||||
|
|
||||||
# Доступ:
|
|
||||||
# Prometheus: http://localhost:9091
|
|
||||||
# Grafana: http://localhost:3001 (admin/admin)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Отдельные сервисы (альтернативная архитектура)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml --profile separate-services up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### Прокси с SSL (Traefik)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml --profile proxy up -d
|
|
||||||
|
|
||||||
# Настройте DOMAIN в .env перед запуском
|
|
||||||
```
|
|
||||||
|
|
||||||
### Автоматические бэкапы
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml --profile backup up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 Диагностика
|
|
||||||
|
|
||||||
### Просмотр логов
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Все сервисы
|
|
||||||
docker-compose -f docker-compose.new.yml logs -f
|
|
||||||
|
|
||||||
# Конкретный сервис
|
|
||||||
docker-compose -f docker-compose.new.yml logs -f app
|
|
||||||
docker-compose -f docker-compose.new.yml logs -f postgres
|
|
||||||
docker-compose -f docker-compose.new.yml logs -f redis
|
|
||||||
```
|
|
||||||
|
|
||||||
### Проверка состояния базы данных
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Подключение к PostgreSQL
|
|
||||||
docker-compose -f docker-compose.new.yml exec postgres psql -U uploader -d uploader_bot
|
|
||||||
|
|
||||||
# Проверка таблиц
|
|
||||||
\dt
|
|
||||||
|
|
||||||
# Выход
|
|
||||||
\q
|
|
||||||
```
|
|
||||||
|
|
||||||
### Проверка Redis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Подключение к Redis
|
|
||||||
docker-compose -f docker-compose.new.yml exec redis redis-cli
|
|
||||||
|
|
||||||
# Проверка ключей
|
|
||||||
KEYS *
|
|
||||||
|
|
||||||
# Выход
|
|
||||||
exit
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛠 Разработка
|
|
||||||
|
|
||||||
### Пересборка приложения
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# После изменения кода
|
|
||||||
docker-compose -f docker-compose.new.yml build app
|
|
||||||
docker-compose -f docker-compose.new.yml up -d app
|
|
||||||
```
|
|
||||||
|
|
||||||
### Выполнение команд внутри контейнера
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Bash в контейнере приложения
|
|
||||||
docker-compose -f docker-compose.new.yml exec app bash
|
|
||||||
|
|
||||||
# Миграции базы данных
|
|
||||||
docker-compose -f docker-compose.new.yml exec app python -m alembic upgrade head
|
|
||||||
|
|
||||||
# Проверка MY Network
|
|
||||||
docker-compose -f docker-compose.new.yml exec app python -c "from app.core.my_network import test_connection; test_connection()"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛑 Остановка
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Остановка всех сервисов
|
|
||||||
docker-compose -f docker-compose.new.yml down
|
|
||||||
|
|
||||||
# Остановка с удалением volumes (ВНИМАНИЕ: удалит все данные!)
|
|
||||||
docker-compose -f docker-compose.new.yml down -v
|
|
||||||
|
|
||||||
# Очистка всех docker ресурсов
|
|
||||||
docker system prune -a
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 MY Network Protocol
|
|
||||||
|
|
||||||
После запуска доступны MY Network endpoints:
|
|
||||||
|
|
||||||
- **Конфигурация bootstrap**: http://localhost:15100/api/my/bootstrap/config
|
|
||||||
- **Статус сети**: http://localhost:15100/api/my/health
|
|
||||||
- **Мониторинг ASCII**: http://localhost:15100/api/my/monitor/
|
|
||||||
- **Метрики**: http://localhost:15100/api/my/metrics
|
|
||||||
|
|
||||||
## ⚠ Важные переменные в .env
|
|
||||||
|
|
||||||
| Переменная | Описание | Обязательна |
|
|
||||||
|------------|----------|-------------|
|
|
||||||
| `TELEGRAM_API_KEY` | Основной бот токен | ✅ ДА |
|
|
||||||
| `CLIENT_TELEGRAM_API_KEY` | Клиентский бот токен | ✅ ДА |
|
|
||||||
| `SECRET_KEY` | Секретный ключ (32+ символов) | ✅ ДА |
|
|
||||||
| `JWT_SECRET_KEY` | JWT секрет (32+ символов) | ✅ ДА |
|
|
||||||
| `POSTGRES_PASSWORD` | Пароль базы данных | ❌ НЕТ |
|
|
||||||
| `DEBUG` | Режим отладки | ❌ НЕТ |
|
|
||||||
| `TESTNET` | Тестовая сеть TON | ❌ НЕТ |
|
|
||||||
|
|
||||||
## 🚀 Готово к продакшену
|
|
||||||
|
|
||||||
Для продакшена дополнительно настройте:
|
|
||||||
|
|
||||||
1. Сильные пароли в `.env`
|
|
||||||
2. `DEBUG=false`
|
|
||||||
3. Правильный `DOMAIN`
|
|
||||||
4. `TESTNET=false` для основной сети TON
|
|
||||||
5. Валидные `TONCENTER_API_KEY`
|
|
||||||
6. SSL сертификаты через Traefik профиль
|
|
||||||
573
README.md
573
README.md
|
|
@ -1,504 +1,101 @@
|
||||||
# My Uploader Bot - Comprehensive File Upload & Blockchain Integration System
|
# MY Network - Универсальная установка
|
||||||
|
|
||||||
A modern, scalable file upload and management system with blockchain integration, built with async Python and enterprise-grade security.
|
🚀 **Универсальный установщик MY Network для любого сервера**
|
||||||
|
|
||||||
## 🚀 Features
|
## ⚡ Быстрая установка
|
||||||
|
|
||||||
### Core Features
|
Один скрипт для полной установки на любом сервере:
|
||||||
- **Chunked File Upload**: Support for large files with resume capability
|
|
||||||
- **Multi-Storage Backend**: Local, S3-compatible storage with automatic failover
|
|
||||||
- **File Processing**: Automatic image optimization, thumbnail generation, media conversion
|
|
||||||
- **Content Management**: Version control, metadata management, search functionality
|
|
||||||
- **User Management**: JWT authentication, API keys, session management
|
|
||||||
|
|
||||||
### Blockchain Integration
|
|
||||||
- **TON Blockchain**: Wallet creation, transaction management, balance tracking
|
|
||||||
- **Smart Contracts**: Interaction with TON smart contracts
|
|
||||||
- **NFT Support**: NFT collection indexing and management
|
|
||||||
- **DeFi Integration**: Staking positions, token balances, yield farming
|
|
||||||
|
|
||||||
### Enterprise Features
|
|
||||||
- **Security**: Rate limiting, CORS, CSP, input validation, file encryption
|
|
||||||
- **Monitoring**: Prometheus metrics, Grafana dashboards, health checks
|
|
||||||
- **Caching**: Redis integration with intelligent cache management
|
|
||||||
- **Background Services**: Async task processing, blockchain indexing
|
|
||||||
- **API Documentation**: OpenAPI/Swagger with interactive interface
|
|
||||||
|
|
||||||
## 🏗️ Architecture
|
|
||||||
|
|
||||||
### Technology Stack
|
|
||||||
- **Backend**: Python 3.11+, Sanic (async web framework)
|
|
||||||
- **Database**: PostgreSQL 15+ with async SQLAlchemy 2.0
|
|
||||||
- **Cache**: Redis 7+ with connection pooling
|
|
||||||
- **Blockchain**: TON SDK for blockchain operations
|
|
||||||
- **Storage**: Local filesystem with S3-compatible support
|
|
||||||
- **Monitoring**: Prometheus, Grafana, structured logging
|
|
||||||
- **Deployment**: Docker Compose with multi-stage builds
|
|
||||||
|
|
||||||
### System Architecture
|
|
||||||
```
|
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ Load Balancer │ │ Grafana │ │ Prometheus │
|
|
||||||
│ (Nginx) │ │ (Monitoring) │ │ (Metrics) │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
│ │ │
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ Sanic App │◄──►│ Redis │ │ PostgreSQL │
|
|
||||||
│ (API Server) │ │ (Cache) │ │ (Database) │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
│ │ │
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ Background │ │ File Storage │ │ TON Blockchain │
|
|
||||||
│ Services │ │ (Local/S3/CDN) │ │ Integration │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔧 Installation & Setup
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Python 3.11+
|
|
||||||
- PostgreSQL 15+
|
|
||||||
- Redis 7+
|
|
||||||
- Docker & Docker Compose (recommended)
|
|
||||||
|
|
||||||
### Quick Start with Docker
|
|
||||||
|
|
||||||
1. **Clone the repository**:
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/your-org/my-uploader-bot.git
|
# Скачать проект
|
||||||
cd my-uploader-bot
|
git clone <repository_url>
|
||||||
|
cd uploader-bot # или my-uploader-bot, или название вашего проекта
|
||||||
|
|
||||||
|
# Запустить установку
|
||||||
|
chmod +x universal_installer.sh
|
||||||
|
sudo ./universal_installer.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Create environment file**:
|
## 📁 Структура проекта
|
||||||
|
|
||||||
|
```
|
||||||
|
my-uploader-bot/
|
||||||
|
├── universal_installer.sh # 🚀 Основной установщик
|
||||||
|
├── app/ # 💻 Код приложения
|
||||||
|
├── scripts/ # 🛠️ Утилиты и скрипты
|
||||||
|
├── deployment/ # 📦 Файлы развертывания
|
||||||
|
├── docs/ # 📚 Документация
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 📦 deployment/
|
||||||
|
- `docker-compose.production.yml` - Основной compose файл
|
||||||
|
- `Dockerfile` - Образ приложения
|
||||||
|
- `requirements.txt` - Python зависимости
|
||||||
|
- `env.example` - Пример переменных окружения
|
||||||
|
|
||||||
|
### 🛠️ scripts/
|
||||||
|
- `diagnose.sh` - Диагностика проблем
|
||||||
|
- `quick_check.sh` - Быстрая проверка статуса
|
||||||
|
- `setup_*.sh` - Скрипты настройки компонентов
|
||||||
|
|
||||||
|
### 📚 docs/
|
||||||
|
- Документация проекта
|
||||||
|
- `archive/` - Устаревшие файлы
|
||||||
|
|
||||||
|
## 🔧 Что делает universal_installer.sh
|
||||||
|
|
||||||
|
1. **🔍 Автопоиск проекта** - находит папку проекта в любой директории
|
||||||
|
2. **📦 Установка зависимостей** - Docker, Docker Compose, Nginx, UFW
|
||||||
|
3. **🔒 Настройка безопасности** - файрвол, fail2ban
|
||||||
|
4. **🗑️ Очистка** - удаляет старые контейнеры
|
||||||
|
5. **⚙️ Конфигурация** - создает .env, настраивает nginx
|
||||||
|
6. **🚀 Запуск** - запускает все сервисы
|
||||||
|
7. **🔧 SystemD service** - автозапуск при перезагрузке
|
||||||
|
8. **✅ Тестирование** - проверяет работу API
|
||||||
|
|
||||||
|
## 🌐 После установки
|
||||||
|
|
||||||
|
Сервер будет доступен на:
|
||||||
|
- `http://YOUR_SERVER_IP/api/health` - API health check
|
||||||
|
- `http://YOUR_SERVER_IP/health` - Альтернативный health check
|
||||||
|
|
||||||
|
## 🛠️ Управление
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
# Статус
|
||||||
# Edit .env with your configuration
|
sudo systemctl status mynetwork
|
||||||
|
|
||||||
|
# Перезапуск
|
||||||
|
sudo systemctl restart mynetwork
|
||||||
|
|
||||||
|
# Логи
|
||||||
|
docker logs $(docker ps --format "{{.Names}}" | grep app | head -1)
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Start services**:
|
## 🔍 Диагностика
|
||||||
|
|
||||||
|
Если что-то не работает:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose -f docker-compose.new.yml up -d
|
# Быстрая диагностика
|
||||||
|
./scripts/diagnose.sh
|
||||||
|
|
||||||
|
# Полная диагностика
|
||||||
|
./scripts/full_diagnosis.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Initialize database**:
|
## 📋 Поддерживаемые системы
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml exec app alembic upgrade head
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Create admin user**:
|
- ✅ Ubuntu 20.04+
|
||||||
```bash
|
- ✅ Debian 11+
|
||||||
docker-compose -f docker-compose.new.yml exec app python -m app.scripts.create_admin
|
- ✅ CentOS 8+ (адаптация)
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Installation
|
## 🆘 Поддержка
|
||||||
|
|
||||||
1. **Install dependencies**:
|
Скрипт автоматически:
|
||||||
```bash
|
- Находит проект в любой директории
|
||||||
# Using Poetry (recommended)
|
- Адаптируется к разным именам контейнеров
|
||||||
poetry install
|
- Работает с разными compose файлами
|
||||||
|
- Создает резервные копии конфигураций
|
||||||
# Or using pip
|
- Показывает детальную диагностику при ошибках
|
||||||
pip install -r requirements_new.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Set up database**:
|
|
||||||
```bash
|
|
||||||
# Create database
|
|
||||||
createdb myuploader
|
|
||||||
|
|
||||||
# Run migrations
|
|
||||||
alembic upgrade head
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Configure Redis**:
|
|
||||||
```bash
|
|
||||||
# Start Redis with custom config
|
|
||||||
redis-server config/redis.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Start application**:
|
|
||||||
```bash
|
|
||||||
# Development mode
|
|
||||||
python -m app
|
|
||||||
|
|
||||||
# Production mode
|
|
||||||
gunicorn app:create_app --bind 0.0.0.0:8000 --worker-class sanic.worker.GunicornWorker
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚙️ Configuration
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
**Database Configuration**:
|
|
||||||
```bash
|
|
||||||
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/myuploader
|
|
||||||
DB_POOL_SIZE=20
|
|
||||||
DB_MAX_OVERFLOW=30
|
|
||||||
```
|
|
||||||
|
|
||||||
**Redis Configuration**:
|
|
||||||
```bash
|
|
||||||
REDIS_URL=redis://localhost:6379/0
|
|
||||||
REDIS_POOL_SIZE=20
|
|
||||||
REDIS_POOL_MAX_CONNECTIONS=100
|
|
||||||
```
|
|
||||||
|
|
||||||
**Security Configuration**:
|
|
||||||
```bash
|
|
||||||
SECRET_KEY=your-super-secret-key-here
|
|
||||||
JWT_SECRET_KEY=your-jwt-secret-key
|
|
||||||
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
|
|
||||||
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
|
|
||||||
```
|
|
||||||
|
|
||||||
**Storage Configuration**:
|
|
||||||
```bash
|
|
||||||
STORAGE_BACKEND=local # or s3, gcs, azure
|
|
||||||
STORAGE_PATH=/app/uploads
|
|
||||||
MAX_FILE_SIZE=104857600 # 100MB
|
|
||||||
ALLOWED_FILE_TYPES=image,video,audio,document
|
|
||||||
```
|
|
||||||
|
|
||||||
**Blockchain Configuration**:
|
|
||||||
```bash
|
|
||||||
TON_NETWORK=mainnet # or testnet
|
|
||||||
TON_API_KEY=your-ton-api-key
|
|
||||||
TON_WALLET_VERSION=v4
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Files
|
|
||||||
|
|
||||||
**Redis Configuration** (`config/redis.conf`):
|
|
||||||
- Optimized for caching workload
|
|
||||||
- Memory management and persistence settings
|
|
||||||
- Security and performance tuning
|
|
||||||
|
|
||||||
**Prometheus Configuration** (`monitoring/prometheus.yml`):
|
|
||||||
- Scraping configuration for all services
|
|
||||||
- Alert rules and metric collection
|
|
||||||
- Storage and retention settings
|
|
||||||
|
|
||||||
## 📊 API Documentation
|
|
||||||
|
|
||||||
### Interactive Documentation
|
|
||||||
- **Swagger UI**: http://localhost:8000/docs
|
|
||||||
- **ReDoc**: http://localhost:8000/redoc
|
|
||||||
- **OpenAPI JSON**: http://localhost:8000/openapi.json
|
|
||||||
|
|
||||||
### Authentication Methods
|
|
||||||
|
|
||||||
1. **JWT Bearer Token**:
|
|
||||||
```bash
|
|
||||||
curl -H "Authorization: Bearer <token>" \
|
|
||||||
https://api.myuploader.com/api/v1/content/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **API Key**:
|
|
||||||
```bash
|
|
||||||
curl -H "X-API-Key: <api_key>" \
|
|
||||||
https://api.myuploader.com/api/v1/content/
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Session Cookie**:
|
|
||||||
```bash
|
|
||||||
curl -b "session=<cookie>" \
|
|
||||||
https://api.myuploader.com/api/v1/content/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Key Endpoints
|
|
||||||
|
|
||||||
**Authentication**:
|
|
||||||
- `POST /api/v1/auth/register` - User registration
|
|
||||||
- `POST /api/v1/auth/login` - User login
|
|
||||||
- `POST /api/v1/auth/refresh` - Token refresh
|
|
||||||
- `DELETE /api/v1/auth/logout` - User logout
|
|
||||||
|
|
||||||
**Content Management**:
|
|
||||||
- `GET /api/v1/content/` - List content
|
|
||||||
- `POST /api/v1/content/` - Create content
|
|
||||||
- `GET /api/v1/content/{id}` - Get content details
|
|
||||||
- `PUT /api/v1/content/{id}` - Update content
|
|
||||||
- `DELETE /api/v1/content/{id}` - Delete content
|
|
||||||
|
|
||||||
**File Upload**:
|
|
||||||
- `POST /api/v1/storage/upload/initiate` - Start upload
|
|
||||||
- `POST /api/v1/storage/upload/chunk` - Upload chunk
|
|
||||||
- `POST /api/v1/storage/upload/complete` - Complete upload
|
|
||||||
- `GET /api/v1/storage/download/{id}` - Download file
|
|
||||||
|
|
||||||
**Blockchain**:
|
|
||||||
- `POST /api/v1/blockchain/wallet/create` - Create wallet
|
|
||||||
- `GET /api/v1/blockchain/wallet/{id}` - Get wallet info
|
|
||||||
- `POST /api/v1/blockchain/transaction/send` - Send transaction
|
|
||||||
- `GET /api/v1/blockchain/transaction/{hash}` - Get transaction status
|
|
||||||
|
|
||||||
## 🛡️ Security
|
|
||||||
|
|
||||||
### Security Features
|
|
||||||
- **Authentication**: Multi-factor authentication support
|
|
||||||
- **Authorization**: Role-based access control (RBAC)
|
|
||||||
- **Input Validation**: Comprehensive request validation
|
|
||||||
- **Rate Limiting**: Per-user and per-endpoint limits
|
|
||||||
- **File Security**: Virus scanning, type validation, encryption
|
|
||||||
- **Network Security**: CORS, CSP, HTTPS enforcement
|
|
||||||
|
|
||||||
### Security Best Practices
|
|
||||||
|
|
||||||
1. **Environment Variables**: Store sensitive data in environment variables
|
|
||||||
2. **Database Security**: Use connection pooling, parameterized queries
|
|
||||||
3. **File Upload Security**: Validate file types, scan for malware
|
|
||||||
4. **API Security**: Implement rate limiting, request validation
|
|
||||||
5. **Monitoring**: Track security events and anomalies
|
|
||||||
|
|
||||||
### Audit Logging
|
|
||||||
All security-relevant events are logged:
|
|
||||||
- Authentication attempts
|
|
||||||
- Authorization failures
|
|
||||||
- File upload/download events
|
|
||||||
- API key usage
|
|
||||||
- Blockchain transactions
|
|
||||||
|
|
||||||
## 📈 Monitoring & Observability
|
|
||||||
|
|
||||||
### Metrics Collection
|
|
||||||
- **Application Metrics**: Request counts, response times, error rates
|
|
||||||
- **System Metrics**: CPU, memory, disk usage
|
|
||||||
- **Database Metrics**: Connection pool, query performance
|
|
||||||
- **Cache Metrics**: Hit rates, memory usage
|
|
||||||
- **Blockchain Metrics**: Transaction status, wallet balances
|
|
||||||
|
|
||||||
### Dashboards
|
|
||||||
- **Application Dashboard**: Request metrics, error rates
|
|
||||||
- **Infrastructure Dashboard**: System resources, service health
|
|
||||||
- **Database Dashboard**: Query performance, connection pools
|
|
||||||
- **Security Dashboard**: Failed logins, rate limits
|
|
||||||
|
|
||||||
### Alerting Rules
|
|
||||||
- High error rates (>5% for 5 minutes)
|
|
||||||
- High response times (>2s for 95th percentile)
|
|
||||||
- Database connection issues
|
|
||||||
- High memory usage (>90%)
|
|
||||||
- Failed blockchain transactions
|
|
||||||
|
|
||||||
## 🔄 Background Services
|
|
||||||
|
|
||||||
### File Conversion Service
|
|
||||||
- **Image Processing**: Resize, optimize, generate thumbnails
|
|
||||||
- **Video Processing**: Transcode, extract thumbnails
|
|
||||||
- **Document Processing**: Extract metadata, generate previews
|
|
||||||
- **Retry Logic**: Automatic retry for failed conversions
|
|
||||||
|
|
||||||
### Blockchain Indexer Service
|
|
||||||
- **Transaction Monitoring**: Track pending transactions
|
|
||||||
- **Wallet Balance Updates**: Sync wallet balances
|
|
||||||
- **NFT Indexing**: Track NFT collections and transfers
|
|
||||||
- **Event Processing**: Process blockchain events
|
|
||||||
|
|
||||||
## 🚀 Deployment
|
|
||||||
|
|
||||||
### Docker Deployment
|
|
||||||
|
|
||||||
1. **Production Build**:
|
|
||||||
```bash
|
|
||||||
docker build -f Dockerfile.new --target production -t my-uploader-bot:latest .
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Deploy with Compose**:
|
|
||||||
```bash
|
|
||||||
docker-compose -f docker-compose.new.yml up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Health Checks**:
|
|
||||||
```bash
|
|
||||||
curl http://localhost:8000/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### Kubernetes Deployment
|
|
||||||
|
|
||||||
1. **Create ConfigMaps**:
|
|
||||||
```bash
|
|
||||||
kubectl create configmap app-config --from-env-file=.env
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Deploy Application**:
|
|
||||||
```bash
|
|
||||||
kubectl apply -f k8s/
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check Status**:
|
|
||||||
```bash
|
|
||||||
kubectl get pods -l app=my-uploader-bot
|
|
||||||
```
|
|
||||||
|
|
||||||
### Production Considerations
|
|
||||||
|
|
||||||
1. **Database**: Use managed PostgreSQL service
|
|
||||||
2. **Cache**: Use managed Redis service
|
|
||||||
3. **Storage**: Use S3-compatible object storage
|
|
||||||
4. **Load Balancer**: Use cloud load balancer
|
|
||||||
5. **SSL/TLS**: Use Let's Encrypt or cloud SSL
|
|
||||||
6. **Monitoring**: Use managed monitoring service
|
|
||||||
|
|
||||||
## 🧪 Testing
|
|
||||||
|
|
||||||
### Running Tests
|
|
||||||
```bash
|
|
||||||
# Run all tests
|
|
||||||
pytest
|
|
||||||
|
|
||||||
# Run with coverage
|
|
||||||
pytest --cov=app
|
|
||||||
|
|
||||||
# Run specific test file
|
|
||||||
pytest tests/test_auth.py
|
|
||||||
|
|
||||||
# Run integration tests
|
|
||||||
pytest tests/integration/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Categories
|
|
||||||
- **Unit Tests**: Individual function/method tests
|
|
||||||
- **Integration Tests**: Service integration tests
|
|
||||||
- **API Tests**: HTTP endpoint tests
|
|
||||||
- **Database Tests**: Database operation tests
|
|
||||||
- **Security Tests**: Security vulnerability tests
|
|
||||||
|
|
||||||
## 🔍 Development
|
|
||||||
|
|
||||||
### Development Setup
|
|
||||||
```bash
|
|
||||||
# Install dev dependencies
|
|
||||||
poetry install --dev
|
|
||||||
|
|
||||||
# Pre-commit hooks
|
|
||||||
pre-commit install
|
|
||||||
|
|
||||||
# Run linting
|
|
||||||
black app/
|
|
||||||
isort app/
|
|
||||||
mypy app/
|
|
||||||
|
|
||||||
# Database migrations
|
|
||||||
alembic revision --autogenerate -m "Description"
|
|
||||||
alembic upgrade head
|
|
||||||
```
|
|
||||||
|
|
||||||
### Code Quality Tools
|
|
||||||
- **Black**: Code formatting
|
|
||||||
- **isort**: Import sorting
|
|
||||||
- **mypy**: Type checking
|
|
||||||
- **bandit**: Security scanning
|
|
||||||
- **pytest**: Testing framework
|
|
||||||
|
|
||||||
### Contributing Guidelines
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create feature branch
|
|
||||||
3. Write tests for new features
|
|
||||||
4. Ensure all tests pass
|
|
||||||
5. Run security scans
|
|
||||||
6. Submit pull request
|
|
||||||
|
|
||||||
## 📝 Migration Guide
|
|
||||||
|
|
||||||
### From v1.x to v2.x
|
|
||||||
|
|
||||||
1. **Database Migration**:
|
|
||||||
```bash
|
|
||||||
# Backup existing database
|
|
||||||
pg_dump myuploader > backup.sql
|
|
||||||
|
|
||||||
# Run new migrations
|
|
||||||
alembic upgrade head
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Configuration Updates**:
|
|
||||||
- Update environment variables
|
|
||||||
- Migrate Redis configuration
|
|
||||||
- Update storage configuration
|
|
||||||
|
|
||||||
3. **API Changes**:
|
|
||||||
- Authentication endpoints changed
|
|
||||||
- New blockchain endpoints added
|
|
||||||
- Response format updates
|
|
||||||
|
|
||||||
## 🐛 Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
**Database Connection Issues**:
|
|
||||||
```bash
|
|
||||||
# Check database connectivity
|
|
||||||
psql -h localhost -U postgres -d myuploader
|
|
||||||
|
|
||||||
# Check connection pool
|
|
||||||
docker-compose logs db
|
|
||||||
```
|
|
||||||
|
|
||||||
**Redis Connection Issues**:
|
|
||||||
```bash
|
|
||||||
# Test Redis connection
|
|
||||||
redis-cli ping
|
|
||||||
|
|
||||||
# Check Redis logs
|
|
||||||
docker-compose logs redis
|
|
||||||
```
|
|
||||||
|
|
||||||
**File Upload Issues**:
|
|
||||||
```bash
|
|
||||||
# Check storage permissions
|
|
||||||
ls -la /app/uploads
|
|
||||||
|
|
||||||
# Check disk space
|
|
||||||
df -h
|
|
||||||
```
|
|
||||||
|
|
||||||
**Blockchain Issues**:
|
|
||||||
```bash
|
|
||||||
# Check TON network status
|
|
||||||
curl https://toncenter.com/api/v2/getAddressInformation
|
|
||||||
|
|
||||||
# Check wallet balance
|
|
||||||
curl -X GET /api/v1/blockchain/wallet/{wallet_id}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Performance Optimization
|
|
||||||
|
|
||||||
1. **Database Optimization**:
|
|
||||||
- Add indexes for frequently queried columns
|
|
||||||
- Optimize query patterns
|
|
||||||
- Use connection pooling
|
|
||||||
|
|
||||||
2. **Cache Optimization**:
|
|
||||||
- Implement cache warming
|
|
||||||
- Use appropriate TTL values
|
|
||||||
- Monitor cache hit rates
|
|
||||||
|
|
||||||
3. **File Storage Optimization**:
|
|
||||||
- Use CDN for static files
|
|
||||||
- Implement file compression
|
|
||||||
- Use efficient storage backends
|
|
||||||
|
|
||||||
## 📚 Additional Resources
|
|
||||||
|
|
||||||
- **API Documentation**: https://docs.myuploader.com
|
|
||||||
- **SDK Documentation**: https://sdk.myuploader.com
|
|
||||||
- **Community Forum**: https://community.myuploader.com
|
|
||||||
- **GitHub Repository**: https://github.com/your-org/my-uploader-bot
|
|
||||||
- **Docker Images**: https://hub.docker.com/r/myuploader/app
|
|
||||||
|
|
||||||
## 📄 License
|
|
||||||
|
|
||||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
||||||
|
|
||||||
## 🤝 Support
|
|
||||||
|
|
||||||
- **Email**: support@myuploader.com
|
|
||||||
- **Discord**: https://discord.gg/myuploader
|
|
||||||
- **GitHub Issues**: https://github.com/your-org/my-uploader-bot/issues
|
|
||||||
- **Documentation**: https://docs.myuploader.com
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Built with ❤️ by the My Uploader Bot Team**
|
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
# 🚀 Инструкции по развертыванию MY Network Bootstrap Node
|
||||||
|
|
||||||
|
## 📋 Что нужно сделать на сервере 2.58.65.188
|
||||||
|
|
||||||
|
### ✅ Шаг 1: Подключение к серверу
|
||||||
|
```bash
|
||||||
|
ssh service@2.58.65.188
|
||||||
|
# Пароль: DMUEjmnh6mDs/qlzhpjDzQ
|
||||||
|
```
|
||||||
|
|
||||||
|
### ✅ Шаг 2: Запуск автоматического развертывания
|
||||||
|
```bash
|
||||||
|
# Переход в root
|
||||||
|
sudo su -
|
||||||
|
|
||||||
|
# Запуск скрипта развертывания
|
||||||
|
chmod +x /tmp/auto_deploy.sh
|
||||||
|
bash /tmp/auto_deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**⏳ Время выполнения: ~15-20 минут**
|
||||||
|
|
||||||
|
### ✅ Шаг 3: Проверка результата
|
||||||
|
После завершения скрипта проверьте:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Статус сервисов
|
||||||
|
systemctl status my-network-bootstrap nginx docker
|
||||||
|
|
||||||
|
# Проверка API
|
||||||
|
curl https://my-public-node-3.projscale.dev/api/my/health
|
||||||
|
|
||||||
|
# Проверка портов (должен быть только 443)
|
||||||
|
netstat -tlnp | grep LISTEN
|
||||||
|
|
||||||
|
# Проверка firewall
|
||||||
|
ufw status numbered
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Что будет развернуто:
|
||||||
|
|
||||||
|
### 🔧 **Базовая инфраструктура:**
|
||||||
|
- ✅ Ubuntu система обновлена
|
||||||
|
- ✅ Docker + Docker Compose установлены
|
||||||
|
- ✅ Python 3 + venv + зависимости
|
||||||
|
- ✅ MariaDB 11.2 (внутренний порт 3306)
|
||||||
|
- ✅ Redis 7 (внутренний порт 6379)
|
||||||
|
|
||||||
|
### 🌐 **MY Network Bootstrap Node:**
|
||||||
|
- ✅ Основное приложение на порту 15100 (внутренний)
|
||||||
|
- ✅ Bootstrap конфигурация для всей сети
|
||||||
|
- ✅ REST API для управления сетью
|
||||||
|
- ✅ Веб-мониторинг с ASCII интерфейсом
|
||||||
|
|
||||||
|
### 🔒 **Безопасность:**
|
||||||
|
- ✅ Nginx proxy только на порт 443 (HTTPS)
|
||||||
|
- ✅ SSL сертификат Let's Encrypt для my-public-node-3.projscale.dev
|
||||||
|
- ✅ UFW firewall - ТОЛЬКО SSH + 443 порт
|
||||||
|
- ✅ Fail2ban защита от атак
|
||||||
|
- ✅ Все внутренние порты заблокированы
|
||||||
|
|
||||||
|
### 🛡️ **Cloudflare совместимость:**
|
||||||
|
- ✅ Настроены IP ranges для Cloudflare
|
||||||
|
- ✅ Real IP header обработка
|
||||||
|
- ✅ CORS headers для публичного API
|
||||||
|
- ✅ Rate limiting для разных endpoints
|
||||||
|
|
||||||
|
## 📡 **Доступные API endpoints:**
|
||||||
|
|
||||||
|
### 🌍 **Публичные (доступны всем):**
|
||||||
|
- **Health Check:** `https://my-public-node-3.projscale.dev/api/my/health`
|
||||||
|
- **Node Info:** `https://my-public-node-3.projscale.dev/api/my/node/info`
|
||||||
|
- **Bootstrap Config:** `https://my-public-node-3.projscale.dev/api/my/bootstrap/config`
|
||||||
|
|
||||||
|
### 🔒 **Ограниченные (только localhost):**
|
||||||
|
- **Monitor Dashboard:** `https://my-public-node-3.projscale.dev/api/my/monitor/`
|
||||||
|
|
||||||
|
## 🎮 **Для других узлов сети:**
|
||||||
|
|
||||||
|
Другие узлы смогут подключаться к этому bootstrap узлу используя:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"bootstrap_nodes": [
|
||||||
|
{
|
||||||
|
"id": "bootstrap-primary",
|
||||||
|
"host": "my-public-node-3.projscale.dev",
|
||||||
|
"port": 443,
|
||||||
|
"ssl": true,
|
||||||
|
"public": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 **Мониторинг:**
|
||||||
|
|
||||||
|
### 🔍 **Автоматический мониторинг:**
|
||||||
|
- ✅ Проверка каждые 2 минуты
|
||||||
|
- ✅ Логирование в `/opt/logs/bootstrap-monitor.log`
|
||||||
|
- ✅ Уведомления о критических проблемах
|
||||||
|
|
||||||
|
### 📈 **Ручная проверка:**
|
||||||
|
```bash
|
||||||
|
# Логи сервиса
|
||||||
|
journalctl -u my-network-bootstrap -f
|
||||||
|
|
||||||
|
# Системный мониторинг
|
||||||
|
tail -f /opt/logs/bootstrap-monitor.log
|
||||||
|
|
||||||
|
# SSL статус
|
||||||
|
certbot certificates
|
||||||
|
|
||||||
|
# Статистика nginx
|
||||||
|
tail -f /var/log/nginx/access.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🆘 **Troubleshooting:**
|
||||||
|
|
||||||
|
### ❌ **Если API недоступен:**
|
||||||
|
```bash
|
||||||
|
systemctl restart my-network-bootstrap nginx
|
||||||
|
curl -v https://my-public-node-3.projscale.dev/api/my/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ **Если SSL не работает:**
|
||||||
|
```bash
|
||||||
|
certbot certificates
|
||||||
|
certbot renew --dry-run
|
||||||
|
systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ **Если firewall блокирует:**
|
||||||
|
```bash
|
||||||
|
ufw status numbered
|
||||||
|
# Проверить что порт 443 разрешен
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 **Финальный чек-лист:**
|
||||||
|
|
||||||
|
После развертывания должно быть:
|
||||||
|
|
||||||
|
- [ ] ✅ `curl https://my-public-node-3.projscale.dev/api/my/health` возвращает 200
|
||||||
|
- [ ] ✅ `curl https://my-public-node-3.projscale.dev/api/my/node/info` показывает информацию об узле
|
||||||
|
- [ ] ✅ `curl https://my-public-node-3.projscale.dev/api/my/bootstrap/config` возвращает конфигурацию
|
||||||
|
- [ ] ✅ `systemctl status my-network-bootstrap nginx docker` все сервисы active
|
||||||
|
- [ ] ✅ `ufw status` показывает только SSH и 443 порт
|
||||||
|
- [ ] ✅ `netstat -tlnp | grep :443` nginx слушает порт 443
|
||||||
|
- [ ] ✅ SSL сертификат действителен (проверить в браузере)
|
||||||
|
|
||||||
|
## 🎉 **Результат:**
|
||||||
|
|
||||||
|
После успешного развертывания у вас будет:
|
||||||
|
|
||||||
|
**🚀 Полностью функциональный MY Network Bootstrap Node**
|
||||||
|
- Доступен по HTTPS на my-public-node-3.projscale.dev
|
||||||
|
- Готов принимать подключения других узлов сети
|
||||||
|
- Защищен firewall + SSL + fail2ban
|
||||||
|
- Автоматический мониторинг и обслуживание
|
||||||
|
- Совместим с Cloudflare proxy
|
||||||
|
|
||||||
|
**🌐 Готов стать основным узлом распределенной сети MY Network!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Время развертывания: ~15-20 минут*
|
||||||
|
*Требования: Ubuntu 20.04+, root доступ, домен настроен*
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
# Исправление ошибки сборки Docker Compose
|
||||||
|
|
||||||
|
## Проблема
|
||||||
|
Система пыталась собрать и запустить сервис `web2-client`, который может отсутствовать на некоторых нодах, что приводило к ошибке:
|
||||||
|
```
|
||||||
|
target web2-client: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
Исправлены **ЧЕТЫРЕ** критические проблемы:
|
||||||
|
|
||||||
|
### 1. Docker Compose исправления
|
||||||
|
В `docker-compose.production.yml`:
|
||||||
|
- Добавлен профиль для web2-client: `profiles: ["main-node"]`
|
||||||
|
- Удалена зависимость nginx на web2-client (nginx теперь зависит только от app)
|
||||||
|
- Удалена устаревшая строка `version: '3.8'`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
web2-client:
|
||||||
|
profiles: ["main-node"] # Only build for main nodes
|
||||||
|
# ... остальная конфигурация
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
depends_on:
|
||||||
|
- app # Убрано: - web2-client
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Умная логика сборки и запуска
|
||||||
|
Обновлен `setup_production_server.sh` с graceful fallback логикой:
|
||||||
|
|
||||||
|
**Для основной ноды (main):**
|
||||||
|
- Сначала пытается собрать/запустить с профилем `main-node` (включая web2-client)
|
||||||
|
- Если не удается, fallback к основным сервисам: `app postgres redis`
|
||||||
|
|
||||||
|
**Для обычной ноды (regular):**
|
||||||
|
- Сразу собирает/запускает только основные сервисы без web2-client
|
||||||
|
|
||||||
|
### 3. Исправление Dockerfile зависимостей
|
||||||
|
**Проблема:** `ERROR: Cannot find command 'git' - do you have 'git' installed and in your PATH?`
|
||||||
|
|
||||||
|
В [`Dockerfile.simple`](my-uploader-bot/Dockerfile.simple:13) добавлен git:
|
||||||
|
```dockerfile
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
build-essential \
|
||||||
|
curl \
|
||||||
|
git \ # ✅ Добавлено для установки tonsdk из GitHub
|
||||||
|
ffmpeg \
|
||||||
|
libmagic1 \
|
||||||
|
libpq-dev \
|
||||||
|
pkg-config \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Исправление конфликта зависимостей Python
|
||||||
|
**Проблема:** `ERROR: Cannot install -r requirements.txt ... because these package versions have conflicting dependencies`
|
||||||
|
|
||||||
|
**Две проблемы:**
|
||||||
|
1. `aiogram 3.13.0` требует `aiofiles~=23.2.1`, а указана `aiofiles==24.1.0`
|
||||||
|
2. [`Dockerfile.simple`](my-uploader-bot/Dockerfile.simple:23) копировал неправильный файл
|
||||||
|
|
||||||
|
**✅ Решение:**
|
||||||
|
- В [`requirements.txt`](my-uploader-bot/requirements.txt:31) изменена версия aiofiles:
|
||||||
|
```txt
|
||||||
|
# Было: aiofiles==24.1.0
|
||||||
|
# Стало: aiofiles==23.2.1 # Совместимо с aiogram
|
||||||
|
```
|
||||||
|
|
||||||
|
- В [`Dockerfile.simple`](my-uploader-bot/Dockerfile.simple:23) исправлен копируемый файл:
|
||||||
|
```dockerfile
|
||||||
|
# Было: COPY requirements_new.txt ./requirements.txt
|
||||||
|
# Стало: COPY requirements.txt ./requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Обновленные управляющие скрипты
|
||||||
|
- `start.sh` - умный запуск с fallback логикой
|
||||||
|
- `rebuild.sh` - пересборка с учетом доступных модулей
|
||||||
|
- `systemd_start.sh` - обертка для systemd service
|
||||||
|
|
||||||
|
## Поведение системы
|
||||||
|
|
||||||
|
### Если web2-client модуль доступен:
|
||||||
|
```bash
|
||||||
|
✅ Запущены все сервисы основной ноды (включая web2-client)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Если web2-client модуль недоступен:
|
||||||
|
```bash
|
||||||
|
⚠️ Web2-client недоступен, запускаем основные сервисы...
|
||||||
|
✅ Запущены основные сервисы (web2-client пропущен)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Команды для проверки
|
||||||
|
|
||||||
|
### Проверка статуса:
|
||||||
|
```bash
|
||||||
|
sudo /home/myuploader/uploader-bot/status.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ручной запуск с профилем:
|
||||||
|
```bash
|
||||||
|
# Основная нода с web2-client
|
||||||
|
docker-compose -f docker-compose.production.yml --profile main-node up -d
|
||||||
|
|
||||||
|
# Только основные сервисы
|
||||||
|
docker-compose -f docker-compose.production.yml up -d app postgres redis
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка доступных сервисов:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.production.yml config --services
|
||||||
|
```
|
||||||
|
|
||||||
|
## Типы нод
|
||||||
|
|
||||||
|
### Main Node (основная)
|
||||||
|
- Полный стек: uploader-bot + converter-module + web2-client
|
||||||
|
- Web интерфейс доступен на главной странице
|
||||||
|
- API доступен через `/api/`
|
||||||
|
|
||||||
|
### Regular Node (обычная)
|
||||||
|
- Основной стек: uploader-bot + converter-module
|
||||||
|
- Только API интерфейс на главной странице
|
||||||
|
- Меньше ресурсов, быстрее развертывание
|
||||||
|
|
||||||
|
## Результат
|
||||||
|
Теперь система корректно работает независимо от наличия всех модулей и автоматически адаптируется к доступным компонентам.
|
||||||
|
|
@ -0,0 +1,617 @@
|
||||||
|
# 🚀 MY UPLOADER BOT - DOCKER SETUP
|
||||||
|
|
||||||
|
Полное руководство по развертыванию MY Uploader Bot с использованием Docker
|
||||||
|
|
||||||
|
## 📋 Содержание
|
||||||
|
|
||||||
|
1. [Локальное тестирование](#локальное-тестирование)
|
||||||
|
2. [Production развертывание](#production-развертывание)
|
||||||
|
3. [Архитектура системы](#архитектура-системы)
|
||||||
|
4. [On-Demand Converter](#on-demand-converter)
|
||||||
|
5. [Мониторинг и логи](#мониторинг-и-логи)
|
||||||
|
6. [Безопасность](#безопасность)
|
||||||
|
7. [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## 🔧 Локальное тестирование
|
||||||
|
|
||||||
|
### Быстрый старт
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Клонирование репозитория
|
||||||
|
git clone <repository-url>
|
||||||
|
cd my-uploader-bot
|
||||||
|
|
||||||
|
# 2. Создание .env файла
|
||||||
|
cp .env.example .env
|
||||||
|
# Отредактируйте .env файл с локальными настройками
|
||||||
|
|
||||||
|
# 3. Запуск с Docker Compose
|
||||||
|
docker-compose -f docker-compose.new.yml up -d
|
||||||
|
|
||||||
|
# 4. Проверка статуса
|
||||||
|
docker-compose -f docker-compose.new.yml ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Переменные окружения для локального тестирования
|
||||||
|
|
||||||
|
Создайте файл `.env` со следующими переменными:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# =============================================================================
|
||||||
|
# MY UPLOADER BOT - ЛОКАЛЬНЫЕ НАСТРОЙКИ
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
NODE_ENV=development
|
||||||
|
DEBUG=true
|
||||||
|
|
||||||
|
# Database (PostgreSQL)
|
||||||
|
DATABASE_URL=postgresql://my_user:my_secure_password_123@localhost:5432/my_uploader_db
|
||||||
|
POSTGRES_HOST=localhost
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_DB=my_uploader_db
|
||||||
|
POSTGRES_USER=my_user
|
||||||
|
POSTGRES_PASSWORD=my_secure_password_123
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
REDIS_URL=redis://localhost:6379/0
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# Security Keys (генерируйте новые для production!)
|
||||||
|
SECRET_KEY=dev_secret_key_change_in_production_123456789
|
||||||
|
JWT_SECRET=dev_jwt_secret_change_in_production_987654321
|
||||||
|
ENCRYPTION_KEY=dev_encryption_key_32_chars_long!
|
||||||
|
|
||||||
|
# MY Network Settings
|
||||||
|
MY_NETWORK_NODE_ID=local-dev-node-$(date +%s)
|
||||||
|
MY_NETWORK_PORT=15100
|
||||||
|
MY_NETWORK_HOST=0.0.0.0
|
||||||
|
MY_NETWORK_DOMAIN=localhost
|
||||||
|
MY_NETWORK_SSL_ENABLED=false
|
||||||
|
|
||||||
|
# API Settings
|
||||||
|
API_HOST=0.0.0.0
|
||||||
|
API_PORT=15100
|
||||||
|
API_WORKERS=2
|
||||||
|
MAX_UPLOAD_SIZE=50MB
|
||||||
|
|
||||||
|
# Converter Settings (On-Demand)
|
||||||
|
CONVERTER_DOCKER_IMAGE=my-converter:latest
|
||||||
|
CONVERTER_SHARED_PATH=/shared/converter
|
||||||
|
CONVERTER_MAX_PARALLEL=2
|
||||||
|
CONVERTER_TIMEOUT=300
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_LEVEL=DEBUG
|
||||||
|
LOG_FORMAT=text
|
||||||
|
|
||||||
|
# Monitoring (опционально)
|
||||||
|
GRAFANA_PASSWORD=admin123
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка локального развертывания
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка здоровья сервисов
|
||||||
|
curl http://localhost:15100/health
|
||||||
|
curl http://localhost:3000/health # web2-client
|
||||||
|
|
||||||
|
# Проверка MY Network API
|
||||||
|
curl http://localhost:15100/api/my/bootstrap/config
|
||||||
|
|
||||||
|
# Проверка converter image
|
||||||
|
docker images | grep my-converter
|
||||||
|
|
||||||
|
# Просмотр логов
|
||||||
|
docker-compose -f docker-compose.new.yml logs -f app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏭 Production развертывание
|
||||||
|
|
||||||
|
### Автоматическое развертывание на пустом сервере
|
||||||
|
|
||||||
|
**Требования:**
|
||||||
|
- Ubuntu 20.04+ / Debian 11+ / CentOS 8+
|
||||||
|
- Минимум 2GB RAM, 2 CPU cores, 20GB диска
|
||||||
|
- Root доступ или sudo права
|
||||||
|
- Доменное имя, указывающее на сервер
|
||||||
|
|
||||||
|
**Одной командой:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Скачайте и запустите мастер-скрипт
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/your-org/my-uploader-bot/main/setup_production_server.sh | sudo bash -s -- yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ручное развертывание (пошагово)
|
||||||
|
|
||||||
|
#### 1. Подготовка сервера
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Обновление системы
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# Установка базовых пакетов
|
||||||
|
sudo apt install -y curl wget git unzip htop nano ufw fail2ban
|
||||||
|
|
||||||
|
# Создание пользователя для сервиса
|
||||||
|
sudo useradd -m -s /bin/bash service
|
||||||
|
sudo usermod -aG sudo service
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Установка Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Установка Docker
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
|
||||||
|
# Установка Docker Compose
|
||||||
|
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||||
|
sudo chmod +x /usr/local/bin/docker-compose
|
||||||
|
|
||||||
|
# Добавление пользователя в группу docker
|
||||||
|
sudo usermod -aG docker service
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Клонирование проекта
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Переключение на пользователя service
|
||||||
|
sudo su - service
|
||||||
|
|
||||||
|
# Клонирование проекта
|
||||||
|
git clone <repository-url> /home/service/my-uploader-bot
|
||||||
|
cd /home/service/my-uploader-bot
|
||||||
|
|
||||||
|
# Установка прав доступа
|
||||||
|
chmod +x scripts/*.sh
|
||||||
|
chmod +x *.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Настройка окружения
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Генерация production конфигурации
|
||||||
|
./scripts/setup_production_env.sh /home/service/my-uploader-bot yourdomain.com
|
||||||
|
|
||||||
|
# Настройка дополнительных модулей
|
||||||
|
./scripts/setup_modules.sh /home/service/my-uploader-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Сборка Docker образов
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Сборка основного приложения и converter
|
||||||
|
docker-compose -f docker-compose.production.yml build
|
||||||
|
|
||||||
|
# Сборка только converter image (для on-demand использования)
|
||||||
|
docker-compose -f docker-compose.production.yml --profile build-only build converter-build
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6. Настройка Nginx и SSL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Возврат к root для настройки системных сервисов
|
||||||
|
exit # выход из пользователя service
|
||||||
|
|
||||||
|
# Установка Nginx и Certbot
|
||||||
|
sudo apt install -y nginx certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
# Настройка Nginx конфигурации
|
||||||
|
sudo ./scripts/create_nginx_config.sh /home/service/my-uploader-bot yourdomain.com service
|
||||||
|
|
||||||
|
# Получение SSL сертификата
|
||||||
|
sudo certbot --nginx -d yourdomain.com --non-interactive --agree-tos --email admin@yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7. Настройка Firewall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Базовая настройка UFW
|
||||||
|
sudo ufw default deny incoming
|
||||||
|
sudo ufw default allow outgoing
|
||||||
|
|
||||||
|
# Разрешение необходимых портов
|
||||||
|
sudo ufw allow ssh
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
|
||||||
|
# Включение firewall
|
||||||
|
sudo ufw --force enable
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8. Создание SystemD сервисов
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Создание сервисов
|
||||||
|
sudo ./scripts/create_systemd_services.sh /home/service/my-uploader-bot service
|
||||||
|
|
||||||
|
# Запуск сервисов
|
||||||
|
sudo systemctl start my-docker-compose
|
||||||
|
sudo systemctl start my-converter-builder
|
||||||
|
sudo systemctl start my-uploader-bot
|
||||||
|
sudo systemctl start my-network-bootstrap
|
||||||
|
sudo systemctl enable nginx
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка Production развертывания
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка HTTPS доступности
|
||||||
|
curl https://yourdomain.com/health
|
||||||
|
|
||||||
|
# Проверка MY Network
|
||||||
|
curl https://yourdomain.com/api/my/bootstrap/config
|
||||||
|
|
||||||
|
# Проверка web2-client
|
||||||
|
curl https://yourdomain.com/web/health
|
||||||
|
|
||||||
|
# Проверка converter image
|
||||||
|
docker images | grep my-converter
|
||||||
|
|
||||||
|
# Проверка SSL сертификата
|
||||||
|
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Архитектура системы
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TB
|
||||||
|
Client[👤 Client] --> LB[🌐 Nginx Load Balancer]
|
||||||
|
|
||||||
|
LB --> App[🚀 MY Uploader Bot<br/>Port: 15100]
|
||||||
|
LB --> Web[💻 Web2 Client<br/>Port: 3000]
|
||||||
|
|
||||||
|
App --> DB[(🗄️ PostgreSQL<br/>Port: 5432)]
|
||||||
|
App --> Redis[(⚡ Redis<br/>Port: 6379)]
|
||||||
|
|
||||||
|
App --> MyNet[🌍 MY Network<br/>Bootstrap Node]
|
||||||
|
|
||||||
|
subgraph "🐳 Docker Network"
|
||||||
|
App
|
||||||
|
Web
|
||||||
|
DB
|
||||||
|
Redis
|
||||||
|
MyNet
|
||||||
|
ConvImg[🖼️ Converter Image<br/>my-converter:latest]
|
||||||
|
end
|
||||||
|
|
||||||
|
App -.->|On-Demand| ConvContainer1[🔄 Converter Container 1]
|
||||||
|
App -.->|On-Demand| ConvContainer2[🔄 Converter Container 2]
|
||||||
|
App -.->|On-Demand| ConvContainer3[🔄 Converter Container N]
|
||||||
|
|
||||||
|
ConvImg -.->|Creates| ConvContainer1
|
||||||
|
ConvImg -.->|Creates| ConvContainer2
|
||||||
|
ConvImg -.->|Creates| ConvContainer3
|
||||||
|
|
||||||
|
ConvContainer1 -.->|Auto-Remove| X1[❌]
|
||||||
|
ConvContainer2 -.->|Auto-Remove| X2[❌]
|
||||||
|
ConvContainer3 -.->|Auto-Remove| X3[❌]
|
||||||
|
|
||||||
|
subgraph "📊 Monitoring Stack"
|
||||||
|
Prom[📈 Prometheus<br/>Port: 9090]
|
||||||
|
Graf[📊 Grafana<br/>Port: 3001]
|
||||||
|
Loki[📋 Loki<br/>Port: 3100]
|
||||||
|
PT[📝 Promtail]
|
||||||
|
end
|
||||||
|
|
||||||
|
App --> Prom
|
||||||
|
Web --> Prom
|
||||||
|
|
||||||
|
PT --> Loki
|
||||||
|
Graf --> Prom
|
||||||
|
Graf --> Loki
|
||||||
|
|
||||||
|
LB --> Graf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Компоненты системы
|
||||||
|
|
||||||
|
| Компонент | Порт | Режим работы | Описание |
|
||||||
|
|-----------|------|-------------|----------|
|
||||||
|
| **MY Uploader Bot** | 15100 | Постоянный | Основное API приложение |
|
||||||
|
| **Web2 Client** | 3000 | Постоянный | Веб интерфейс |
|
||||||
|
| **PostgreSQL** | 5432 | Постоянный | Основная база данных |
|
||||||
|
| **Redis** | 6379 | Постоянный | Кеширование и очереди |
|
||||||
|
| **Nginx** | 80/443 | Постоянный | Reverse proxy + SSL |
|
||||||
|
| **Converter Module** | - | **On-Demand** | 🔄 Конвертер медиа файлов |
|
||||||
|
| **Prometheus** | 9090 | Постоянный | Сбор метрик |
|
||||||
|
| **Grafana** | 3001 | Постоянный | Дашборды мониторинга |
|
||||||
|
| **Loki** | 3100 | Постоянный | Централизованные логи |
|
||||||
|
|
||||||
|
## 🔄 On-Demand Converter
|
||||||
|
|
||||||
|
### Принцип работы
|
||||||
|
|
||||||
|
Converter Module работает по принципу **on-demand контейнеров**:
|
||||||
|
|
||||||
|
1. **Image собирается один раз** при установке системы
|
||||||
|
2. **MY Uploader Bot создает контейнеры** по мере поступления задач конвертации
|
||||||
|
3. **Контейнеры автоматически удаляются** после завершения задач
|
||||||
|
4. **Параллельная обработка** до N задач одновременно (настраивается)
|
||||||
|
|
||||||
|
### Настройки converter в .env
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Converter Settings
|
||||||
|
CONVERTER_DOCKER_IMAGE=my-converter:latest # Имя образа
|
||||||
|
CONVERTER_SHARED_PATH=/shared/converter # Общая папка для файлов
|
||||||
|
CONVERTER_MAX_PARALLEL=3 # Максимум параллельных задач
|
||||||
|
CONVERTER_TIMEOUT=300 # Таймаут задачи (секунды)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Управление converter
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка готовности converter image
|
||||||
|
docker images | grep my-converter
|
||||||
|
|
||||||
|
# Пересборка converter image
|
||||||
|
./rebuild_converter.sh
|
||||||
|
|
||||||
|
# Просмотр активных converter контейнеров
|
||||||
|
docker ps | grep converter
|
||||||
|
|
||||||
|
# Мониторинг логов converter заданий
|
||||||
|
docker logs -f <converter_container_id>
|
||||||
|
|
||||||
|
# Принудительная очистка зависших контейнеров
|
||||||
|
docker container prune -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### API endpoints для converter
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запуск задачи конвертации
|
||||||
|
POST /api/convert/start
|
||||||
|
{
|
||||||
|
"file_id": "uuid",
|
||||||
|
"conversion_type": "video_to_mp4",
|
||||||
|
"options": {...}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Статус задачи конвертации
|
||||||
|
GET /api/convert/status/{task_id}
|
||||||
|
|
||||||
|
# Отмена задачи
|
||||||
|
DELETE /api/convert/cancel/{task_id}
|
||||||
|
|
||||||
|
# Список активных задач
|
||||||
|
GET /api/convert/active
|
||||||
|
```
|
||||||
|
|
||||||
|
### Преимущества on-demand архитектуры
|
||||||
|
|
||||||
|
✅ **Экономия ресурсов** - converter потребляет ресурсы только при работе
|
||||||
|
✅ **Масштабируемость** - автоматическое создание контейнеров по нагрузке
|
||||||
|
✅ **Изоляция** - каждая задача выполняется в отдельном контейнере
|
||||||
|
✅ **Отказоустойчивость** - сбой одного контейнера не влияет на другие
|
||||||
|
✅ **Легкое обновление** - пересборка image без остановки основной системы
|
||||||
|
|
||||||
|
## 📊 Мониторинг и логи
|
||||||
|
|
||||||
|
### Доступ к мониторингу
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Grafana Dashboard
|
||||||
|
https://yourdomain.com/grafana
|
||||||
|
# Логин: admin / пароль из .env
|
||||||
|
|
||||||
|
# Prometheus Metrics
|
||||||
|
https://yourdomain.com/prometheus
|
||||||
|
|
||||||
|
# Проверка логов
|
||||||
|
docker-compose -f docker-compose.production.yml logs -f app
|
||||||
|
journalctl -u my-uploader-bot -f
|
||||||
|
journalctl -u my-docker-compose -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ключевые метрики
|
||||||
|
|
||||||
|
- **Производительность**: Response time, throughput, error rate
|
||||||
|
- **Ресурсы**: CPU, Memory, Disk usage
|
||||||
|
- **MY Network**: Количество узлов, скорость репликации
|
||||||
|
- **База данных**: Подключения, запросы, производительность
|
||||||
|
- **Converter**: Активные задачи, время обработки, ошибки
|
||||||
|
|
||||||
|
### Алерты
|
||||||
|
|
||||||
|
Система автоматически создает алерты для:
|
||||||
|
- Высокая нагрузка на CPU (>80%)
|
||||||
|
- Недостаток памяти (<100MB свободно)
|
||||||
|
- Ошибки приложения (>5 за минуту)
|
||||||
|
- MY Network недоступен
|
||||||
|
- SSL сертификат истекает (<30 дней)
|
||||||
|
- Converter задачи зависают (>timeout)
|
||||||
|
|
||||||
|
## 🔒 Безопасность
|
||||||
|
|
||||||
|
### Безопасность сети
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка открытых портов
|
||||||
|
sudo netstat -tlnp | grep LISTEN
|
||||||
|
|
||||||
|
# Проверка правил firewall
|
||||||
|
sudo ufw status verbose
|
||||||
|
|
||||||
|
# Анализ попыток вторжения
|
||||||
|
sudo fail2ban-client status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Обновления безопасности
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Автоматические обновления безопасности
|
||||||
|
sudo apt install unattended-upgrades
|
||||||
|
sudo dpkg-reconfigure -plow unattended-upgrades
|
||||||
|
|
||||||
|
# Регулярная ротация SSL сертификатов
|
||||||
|
sudo crontab -e
|
||||||
|
# Добавить: 0 12 * * * /usr/bin/certbot renew --quiet
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup стратегия
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup базы данных
|
||||||
|
docker-compose -f docker-compose.production.yml exec postgres pg_dump -U my_user my_uploader_db > backup_$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Backup конфигурации
|
||||||
|
tar -czf config_backup_$(date +%Y%m%d).tar.gz .env nginx/ ssl/
|
||||||
|
|
||||||
|
# Backup converter image
|
||||||
|
docker save my-converter:latest | gzip > converter_image_$(date +%Y%m%d).tar.gz
|
||||||
|
|
||||||
|
# Автоматический backup (добавить в crontab)
|
||||||
|
0 2 * * * /home/service/my-uploader-bot/scripts/backup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Troubleshooting
|
||||||
|
|
||||||
|
### Частые проблемы
|
||||||
|
|
||||||
|
#### 1. Приложение не запускается
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка логов
|
||||||
|
docker-compose -f docker-compose.production.yml logs app
|
||||||
|
journalctl -u my-uploader-bot -f
|
||||||
|
|
||||||
|
# Проверка конфигурации
|
||||||
|
docker-compose -f docker-compose.production.yml config
|
||||||
|
|
||||||
|
# Проверка переменных окружения
|
||||||
|
cat .env
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. База данных недоступна
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка статуса PostgreSQL
|
||||||
|
docker-compose -f docker-compose.production.yml exec postgres pg_isready
|
||||||
|
|
||||||
|
# Подключение к БД
|
||||||
|
docker-compose -f docker-compose.production.yml exec postgres psql -U my_user -d my_uploader_db
|
||||||
|
|
||||||
|
# Проверка логов БД
|
||||||
|
docker-compose -f docker-compose.production.yml logs postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. SSL сертификат не работает
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка сертификата
|
||||||
|
sudo certbot certificates
|
||||||
|
|
||||||
|
# Обновление сертификата
|
||||||
|
sudo certbot renew --dry-run
|
||||||
|
|
||||||
|
# Проверка nginx конфигурации
|
||||||
|
sudo nginx -t
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. MY Network недоступна
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка bootstrap узла
|
||||||
|
curl https://yourdomain.com/api/my/bootstrap/config
|
||||||
|
|
||||||
|
# Проверка логов MY Network
|
||||||
|
docker-compose -f docker-compose.production.yml logs app | grep "MY Network"
|
||||||
|
|
||||||
|
# Проверка сетевых подключений
|
||||||
|
docker network ls
|
||||||
|
docker network inspect my-uploader-bot_uploader_network
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Converter не работает
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка наличия image
|
||||||
|
docker images | grep my-converter
|
||||||
|
|
||||||
|
# Пересборка converter image
|
||||||
|
./rebuild_converter.sh
|
||||||
|
|
||||||
|
# Проверка активных converter контейнеров
|
||||||
|
docker ps | grep converter
|
||||||
|
|
||||||
|
# Очистка зависших контейнеров
|
||||||
|
docker container prune -f
|
||||||
|
|
||||||
|
# Проверка логов последних converter задач
|
||||||
|
docker logs $(docker ps -a | grep converter | head -1 | cut -d' ' -f1)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Полезные команды
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Полная перезагрузка системы
|
||||||
|
./stop_all_services.sh && ./start_all_services.sh
|
||||||
|
|
||||||
|
# Обновление приложения
|
||||||
|
git pull
|
||||||
|
docker-compose -f docker-compose.production.yml pull
|
||||||
|
docker-compose -f docker-compose.production.yml up -d
|
||||||
|
|
||||||
|
# Очистка неиспользуемых ресурсов
|
||||||
|
docker system prune -a
|
||||||
|
|
||||||
|
# Мониторинг ресурсов в реальном времени
|
||||||
|
docker stats
|
||||||
|
|
||||||
|
# Мониторинг converter активности
|
||||||
|
watch 'docker ps | grep converter'
|
||||||
|
```
|
||||||
|
|
||||||
|
### SystemD сервисы
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запуск всех сервисов
|
||||||
|
./start_all_services.sh
|
||||||
|
|
||||||
|
# Остановка всех сервисов
|
||||||
|
./stop_all_services.sh
|
||||||
|
|
||||||
|
# Проверка статуса всех сервисов
|
||||||
|
./check_services.sh
|
||||||
|
|
||||||
|
# Пересборка converter image
|
||||||
|
./rebuild_converter.sh
|
||||||
|
|
||||||
|
# Просмотр логов отдельных сервисов
|
||||||
|
journalctl -u my-uploader-bot -f
|
||||||
|
journalctl -u my-docker-compose -f
|
||||||
|
journalctl -u my-converter-builder -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Контакты поддержки
|
||||||
|
|
||||||
|
- **GitHub Issues**: [repository-url]/issues
|
||||||
|
- **Documentation**: [repository-url]/wiki
|
||||||
|
- **MY Network**: https://my-network.dev
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Дополнительные ресурсы
|
||||||
|
|
||||||
|
- [Архитектура MY Network](docs/MY_NETWORK_ARCHITECTURE.md)
|
||||||
|
- [API Documentation](docs/API.md)
|
||||||
|
- [Development Guide](docs/DEVELOPMENT.md)
|
||||||
|
- [Security Guidelines](docs/SECURITY.md)
|
||||||
|
- [Converter Module Guide](docs/CONVERTER.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**🎉 Поздравляем! MY Uploader Bot успешно развернут в production!**
|
||||||
|
|
||||||
|
Система готова к работе с:
|
||||||
|
- ⚡ **On-demand конвертацией** медиа файлов
|
||||||
|
- 🔒 **Безопасностью корпоративного уровня**
|
||||||
|
- 📊 **Автоматическим мониторингом**
|
||||||
|
- 🚀 **Высокой производительностью**
|
||||||
|
- 🌍 **Распределенной MY Network**
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
# Ручная настройка SSL для MY Network Bootstrap Node
|
||||||
|
|
||||||
|
## Проблема
|
||||||
|
Пользователь `service` не имеет sudo прав для настройки nginx и SSL сертификатов.
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
Необходимо выполнить команды от имени root.
|
||||||
|
|
||||||
|
## Инструкция
|
||||||
|
|
||||||
|
### 1. Подключение к серверу как root
|
||||||
|
```bash
|
||||||
|
ssh root@2.58.65.188
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Копирование скрипта
|
||||||
|
```bash
|
||||||
|
cp /home/service/setup_nginx_ssl.sh /root/
|
||||||
|
chmod +x /root/setup_nginx_ssl.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Запуск настройки SSL
|
||||||
|
```bash
|
||||||
|
cd /root
|
||||||
|
./setup_nginx_ssl.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Альтернативный способ - добавить service в sudoers
|
||||||
|
|
||||||
|
### 1. Подключиться как root
|
||||||
|
```bash
|
||||||
|
ssh root@2.58.65.188
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Добавить service в sudoers
|
||||||
|
```bash
|
||||||
|
echo "service ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Запустить скрипт от service
|
||||||
|
```bash
|
||||||
|
su - service
|
||||||
|
cd /home/service
|
||||||
|
sudo ./setup_nginx_ssl.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Что делает скрипт setup_nginx_ssl.sh
|
||||||
|
|
||||||
|
1. **Обновляет систему** и устанавливает nginx, certbot, ufw
|
||||||
|
2. **Настраивает firewall** (UFW):
|
||||||
|
- Разрешает SSH (22), HTTP (80), HTTPS (443)
|
||||||
|
- Блокирует остальные порты
|
||||||
|
3. **Получает SSL сертификат** от Let's Encrypt для домена my-public-node-3.projscale.dev
|
||||||
|
4. **Настраивает nginx**:
|
||||||
|
- HTTP -> HTTPS redirect
|
||||||
|
- Proxy для MY Network сервиса (порт 15100)
|
||||||
|
- Security headers
|
||||||
|
- Rate limiting
|
||||||
|
- CORS headers
|
||||||
|
5. **Настраивает автообновление** SSL сертификатов через cron
|
||||||
|
6. **Проверяет работоспособность** всех компонентов
|
||||||
|
|
||||||
|
## Ожидаемый результат
|
||||||
|
|
||||||
|
После выполнения скрипта MY Network Bootstrap Node будет доступен по HTTPS:
|
||||||
|
|
||||||
|
- **https://my-public-node-3.projscale.dev** - основной сайт
|
||||||
|
- **https://my-public-node-3.projscale.dev/api/my/health** - health check
|
||||||
|
- **https://my-public-node-3.projscale.dev/api/my/bootstrap/config** - bootstrap конфигурация
|
||||||
|
- **https://my-public-node-3.projscale.dev/api/my/monitor/** - веб-мониторинг
|
||||||
|
|
||||||
|
## Безопасность
|
||||||
|
|
||||||
|
- ✅ SSL/TLS сертификат от Let's Encrypt
|
||||||
|
- ✅ HTTP -> HTTPS redirect
|
||||||
|
- ✅ Security headers (HSTS, X-Frame-Options, etc.)
|
||||||
|
- ✅ Rate limiting для API endpoints
|
||||||
|
- ✅ Firewall (UFW) с минимальными открытыми портами
|
||||||
|
- ✅ Автообновление SSL сертификатов
|
||||||
|
|
||||||
|
## Проверка после установки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка nginx
|
||||||
|
systemctl status nginx
|
||||||
|
|
||||||
|
# Проверка MY Network сервиса
|
||||||
|
systemctl status my-network
|
||||||
|
|
||||||
|
# Проверка SSL сертификата
|
||||||
|
curl -I https://my-public-node-3.projscale.dev
|
||||||
|
|
||||||
|
# Проверка API
|
||||||
|
curl https://my-public-node-3.projscale.dev/api/my/health
|
||||||
|
|
||||||
|
# Логи nginx
|
||||||
|
tail -f /var/log/nginx/access.log
|
||||||
|
tail -f /var/log/nginx/error.log
|
||||||
|
|
@ -0,0 +1,347 @@
|
||||||
|
# Руководство по миграции на асинхронную архитектуру с Redis
|
||||||
|
|
||||||
|
Это руководство поможет вам безопасно обновить существующую систему My Uploader Bot до новой асинхронной архитектуры с поддержкой Redis кэширования, сохранив полную совместимость с текущими данными и настройками.
|
||||||
|
|
||||||
|
## ⚠️ ВАЖНО: Резервное копирование
|
||||||
|
|
||||||
|
**Перед началом миграции обязательно создайте резервные копии:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Остановите существующие контейнеры
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# Создайте резервную копию базы данных
|
||||||
|
docker run --rm \
|
||||||
|
-v my-uploader-bot_sqlStorage:/var/lib/mysql \
|
||||||
|
-v $(pwd)/backup:/backup \
|
||||||
|
mariadb:11.2 \
|
||||||
|
mysqldump -h maria_db -u myuploader -p myuploader > /backup/database_backup_$(date +%Y%m%d_%H%M%S).sql
|
||||||
|
|
||||||
|
# Создайте резервную копию файлов
|
||||||
|
cp -r /Storage /Storage_backup_$(date +%Y%m%d_%H%M%S)
|
||||||
|
|
||||||
|
# Создайте резервную копию конфигурации
|
||||||
|
cp docker-compose.yml docker-compose.yml.backup
|
||||||
|
cp .env .env.backup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 1: Обновление конфигурационных файлов
|
||||||
|
|
||||||
|
### 1.1 Обновите docker-compose.yml
|
||||||
|
|
||||||
|
Замените ваш текущий `docker-compose.yml` на совместимую версию:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Переименуйте существующий файл
|
||||||
|
mv docker-compose.yml docker-compose.yml.old
|
||||||
|
|
||||||
|
# Скопируйте новую совместимую версию
|
||||||
|
cp docker-compose.compatible.yml docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Обновите .env файл
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Переименуйте существующий .env
|
||||||
|
mv .env .env.old
|
||||||
|
|
||||||
|
# Скопируйте новую совместимую версию
|
||||||
|
cp .env.compatible .env
|
||||||
|
|
||||||
|
# Перенесите ваши существующие настройки
|
||||||
|
# Отредактируйте .env и добавьте ваши текущие значения:
|
||||||
|
# - MYSQL_PASSWORD (ваш текущий пароль)
|
||||||
|
# - SECRET_KEY (ваш текущий ключ)
|
||||||
|
# - JWT_SECRET_KEY (ваш текущий JWT ключ)
|
||||||
|
# - Другие специфичные настройки
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 Обновите requirements.txt
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Переименуйте существующий файл
|
||||||
|
mv requirements.txt requirements.txt.old
|
||||||
|
|
||||||
|
# Скопируйте новую совместимую версию
|
||||||
|
cp requirements.compatible.txt requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 2: Добавление новых модулей
|
||||||
|
|
||||||
|
### 2.1 Обновите core модули
|
||||||
|
|
||||||
|
Замените существующие модули на совместимые версии:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Создайте резервные копии существующих модулей
|
||||||
|
mkdir -p app/core/backup
|
||||||
|
cp app/core/database.py app/core/backup/database.py.old
|
||||||
|
cp app/core/config.py app/core/backup/config.py.old
|
||||||
|
|
||||||
|
# Используйте новые совместимые модули
|
||||||
|
cp app/core/database_compatible.py app/core/database.py
|
||||||
|
cp app/core/config_compatible.py app/core/config.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 Добавьте систему кэширования
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Добавьте новый модуль кэширования
|
||||||
|
# Файл app/core/cache.py уже создан
|
||||||
|
|
||||||
|
# Добавьте совместимые модели
|
||||||
|
cp app/core/models/base_compatible.py app/core/models/base.py
|
||||||
|
cp app/core/models/user_compatible.py app/core/models/user.py
|
||||||
|
cp app/core/models/content_compatible.py app/core/models/content.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 3: Постепенное обновление
|
||||||
|
|
||||||
|
### 3.1 Запуск с Redis (рекомендуется)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запустите только Redis для тестирования
|
||||||
|
docker-compose up -d redis
|
||||||
|
|
||||||
|
# Проверьте, что Redis работает
|
||||||
|
docker-compose exec redis redis-cli ping
|
||||||
|
# Должно вернуть: PONG
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Запуск основных сервисов
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запустите MariaDB
|
||||||
|
docker-compose up -d maria_db
|
||||||
|
|
||||||
|
# Дождитесь готовности базы данных
|
||||||
|
docker-compose logs -f maria_db
|
||||||
|
# Ждите сообщения: "mysqld: ready for connections"
|
||||||
|
|
||||||
|
# Запустите основное приложение
|
||||||
|
docker-compose up -d app
|
||||||
|
|
||||||
|
# Проверьте логи
|
||||||
|
docker-compose logs -f app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Запуск дополнительных сервисов
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запустите остальные сервисы поочередно
|
||||||
|
docker-compose up -d indexer
|
||||||
|
docker-compose up -d ton_daemon
|
||||||
|
docker-compose up -d license_index
|
||||||
|
docker-compose up -d convert_process
|
||||||
|
|
||||||
|
# Проверьте статус всех сервисов
|
||||||
|
docker-compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 4: Проверка работоспособности
|
||||||
|
|
||||||
|
### 4.1 Проверка API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверьте основной API
|
||||||
|
curl http://localhost:15100/health
|
||||||
|
|
||||||
|
# Проверьте подключение к базе данных
|
||||||
|
curl http://localhost:15100/api/v1/health/database
|
||||||
|
|
||||||
|
# Проверьте Redis подключение
|
||||||
|
curl http://localhost:15100/api/v1/health/cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 Проверка существующих данных
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Войдите в контейнер приложения
|
||||||
|
docker-compose exec app python3 -c "
|
||||||
|
from app.core.database_compatible import init_database, get_async_session
|
||||||
|
from app.core.models.user_compatible import User
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
async def check_data():
|
||||||
|
await init_database()
|
||||||
|
async with get_async_session() as session:
|
||||||
|
from sqlalchemy import select
|
||||||
|
result = await session.execute(select(User))
|
||||||
|
users = result.scalars().all()
|
||||||
|
print(f'Found {len(users)} users in database')
|
||||||
|
|
||||||
|
asyncio.run(check_data())
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Проверка кэширования
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверьте работу Redis кэша
|
||||||
|
docker-compose exec app python3 -c "
|
||||||
|
from app.core.cache import init_cache, cache
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
async def test_cache():
|
||||||
|
await init_cache()
|
||||||
|
await cache.set('test_key', 'test_value', 60)
|
||||||
|
value = await cache.get('test_key')
|
||||||
|
print(f'Cache test: {value}')
|
||||||
|
|
||||||
|
asyncio.run(test_cache())
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 5: Настройка для продакшена
|
||||||
|
|
||||||
|
### 5.1 Обновите переменные окружения
|
||||||
|
|
||||||
|
В файле `.env` убедитесь, что настроены:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Безопасность
|
||||||
|
SECRET_KEY=your-production-secret-key
|
||||||
|
JWT_SECRET_KEY=your-production-jwt-key
|
||||||
|
|
||||||
|
# База данных
|
||||||
|
MYSQL_PASSWORD=your-secure-database-password
|
||||||
|
|
||||||
|
# Redis (если используете внешний Redis)
|
||||||
|
REDIS_HOST=redis
|
||||||
|
REDIS_PASSWORD=your-redis-password # Если нужен
|
||||||
|
|
||||||
|
# Кэширование
|
||||||
|
CACHE_ENABLED=true
|
||||||
|
REDIS_ENABLED=true
|
||||||
|
|
||||||
|
# Производительность
|
||||||
|
DATABASE_POOL_SIZE=20
|
||||||
|
DATABASE_MAX_OVERFLOW=30
|
||||||
|
REDIS_MAX_CONNECTIONS=50
|
||||||
|
|
||||||
|
# Логирование
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
LOG_FORMAT=json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Настройте мониторинг
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Добавьте мониторинг Redis
|
||||||
|
docker-compose exec redis redis-cli info memory
|
||||||
|
|
||||||
|
# Добавьте мониторинг MariaDB
|
||||||
|
docker-compose exec maria_db mysql -u root -p -e "SHOW PROCESSLIST;"
|
||||||
|
|
||||||
|
# Проверьте использование ресурсов
|
||||||
|
docker stats
|
||||||
|
```
|
||||||
|
|
||||||
|
## Откат изменений
|
||||||
|
|
||||||
|
Если что-то пошло не так, вы можете быстро откатиться:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Остановите новые контейнеры
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# Восстановите старые конфигурации
|
||||||
|
mv docker-compose.yml.old docker-compose.yml
|
||||||
|
mv .env.old .env
|
||||||
|
mv requirements.txt.old requirements.txt
|
||||||
|
|
||||||
|
# Восстановите старые модули
|
||||||
|
cp app/core/backup/database.py.old app/core/database.py
|
||||||
|
cp app/core/backup/config.py.old app/core/config.py
|
||||||
|
|
||||||
|
# Запустите старую версию
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Производительность и мониторинг
|
||||||
|
|
||||||
|
### Мониторинг Redis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Мониторинг использования памяти Redis
|
||||||
|
docker-compose exec redis redis-cli info memory
|
||||||
|
|
||||||
|
# Мониторинг команд Redis
|
||||||
|
docker-compose exec redis redis-cli monitor
|
||||||
|
|
||||||
|
# Статистика кэша
|
||||||
|
docker-compose exec redis redis-cli info stats
|
||||||
|
```
|
||||||
|
|
||||||
|
### Мониторинг MariaDB
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка подключений
|
||||||
|
docker-compose exec maria_db mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"
|
||||||
|
|
||||||
|
# Проверка производительности
|
||||||
|
docker-compose exec maria_db mysql -u root -p -e "SHOW STATUS LIKE 'Queries';"
|
||||||
|
|
||||||
|
# Размер базы данных
|
||||||
|
docker-compose exec maria_db mysql -u root -p -e "
|
||||||
|
SELECT
|
||||||
|
table_schema as 'Database',
|
||||||
|
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as 'Size (MB)'
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'myuploader'
|
||||||
|
GROUP BY table_schema;
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Возможные проблемы и решения
|
||||||
|
|
||||||
|
### Проблема: Redis не запускается
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверьте порты
|
||||||
|
netstat -tulpn | grep 6379
|
||||||
|
|
||||||
|
# Проверьте логи Redis
|
||||||
|
docker-compose logs redis
|
||||||
|
|
||||||
|
# Очистите данные Redis если нужно
|
||||||
|
docker volume rm my-uploader-bot_redis_data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проблема: Ошибки подключения к базе данных
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверьте статус MariaDB
|
||||||
|
docker-compose exec maria_db mysqladmin -u root -p status
|
||||||
|
|
||||||
|
# Проверьте переменные окружения
|
||||||
|
docker-compose exec app env | grep MYSQL
|
||||||
|
|
||||||
|
# Пересоздайте подключение
|
||||||
|
docker-compose restart app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проблема: Высокое использование памяти
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Настройте лимиты Redis в .env
|
||||||
|
REDIS_MAX_CONNECTIONS=30
|
||||||
|
DATABASE_POOL_SIZE=10
|
||||||
|
|
||||||
|
# Перезапустите сервисы
|
||||||
|
docker-compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
После успешной миграции ваша система получит:
|
||||||
|
|
||||||
|
1. ✅ **Асинхронную архитектуру** - лучшая производительность
|
||||||
|
2. ✅ **Redis кэширование** - быстрый доступ к данным
|
||||||
|
3. ✅ **Обратная совместимость** - все данные сохранены
|
||||||
|
4. ✅ **Улучшенный мониторинг** - больше метрик
|
||||||
|
5. ✅ **Масштабируемость** - готовность к росту нагрузки
|
||||||
|
|
||||||
|
Система остается полностью совместимой с существующими данными и конфигурациями, но получает современную асинхронную архитектуру и кэширование для лучшей производительности.
|
||||||
|
|
||||||
|
**Рекомендация**: Проводите миграцию в нерабочее время и тщательно тестируйте каждый шаг.
|
||||||
|
|
@ -0,0 +1,625 @@
|
||||||
|
# MY Network Architecture Specification
|
||||||
|
|
||||||
|
## Архитектурный Обзор
|
||||||
|
|
||||||
|
MY Network представляет собой многоуровневую архитектуру overlay протокола, интегрированную с существующей системой my-uploader-bot без нарушения её функциональности.
|
||||||
|
|
||||||
|
## Overlay Architecture Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ MY Network Layer │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ P2P Manager │ │ Consensus │ │ Replication │ │
|
||||||
|
│ │ │ │ Engine │ │ Manager │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ Integration Layer │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ Content API │ │ Storage API │ │ Auth API │ │
|
||||||
|
│ │ (Existing) │ │ (Existing) │ │ (Existing) │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ Core Data Layer │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │StoredContent│ │EncryptionKey│ │ UserContent │ │
|
||||||
|
│ │ Model │ │ Model │ │ Model │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Интеграция с Существующей StoredContent Моделью
|
||||||
|
|
||||||
|
### Расширение StoredContent для MY Network
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Новые поля для MY Network (добавляются через миграцию)
|
||||||
|
class StoredContentExtension:
|
||||||
|
# MY Network specific fields
|
||||||
|
my_network_enabled = Column(Boolean, default=False)
|
||||||
|
replica_count = Column(Integer, default=0)
|
||||||
|
replication_status = Column(String(32), default="none")
|
||||||
|
consensus_achieved = Column(Boolean, default=False)
|
||||||
|
|
||||||
|
# Peer information
|
||||||
|
replicated_on_peers = Column(ARRAY(String), default=list)
|
||||||
|
last_sync_timestamp = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
# Network metadata
|
||||||
|
network_metadata = Column(JSONB, default=dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Состояния Контента и Их Связи
|
||||||
|
|
||||||
|
#### 1. Encrypted Content State
|
||||||
|
```python
|
||||||
|
# Зашифрованный контент в MY Network
|
||||||
|
encrypted_content = StoredContent(
|
||||||
|
hash="sha256:abc123...",
|
||||||
|
encrypted=True,
|
||||||
|
encryption_key_id="uuid-key-id",
|
||||||
|
content_type="audio",
|
||||||
|
my_network_enabled=True
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Decrypted Content State (через decrypted_content_id)
|
||||||
|
```python
|
||||||
|
# Расшифрованная версия связана через специальное поле
|
||||||
|
decrypted_content = StoredContent(
|
||||||
|
hash="sha256:def456...",
|
||||||
|
encrypted=False,
|
||||||
|
original_encrypted_id=encrypted_content.id, # Обратная связь
|
||||||
|
content_type="audio",
|
||||||
|
my_network_enabled=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# В encrypted_content добавляется:
|
||||||
|
encrypted_content.decrypted_content_id = decrypted_content.id
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Preview Content State
|
||||||
|
```python
|
||||||
|
# Превью версия для публичного доступа
|
||||||
|
preview_content = StoredContent(
|
||||||
|
hash="sha256:ghi789...",
|
||||||
|
encrypted=False,
|
||||||
|
content_type="audio",
|
||||||
|
file_size=small_size, # Урезанная версия
|
||||||
|
tags=["preview"],
|
||||||
|
parent_content_id=encrypted_content.id, # Связь с оригиналом
|
||||||
|
my_network_enabled=True
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Content State Relationship Model
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Новая таблица для управления связями контента
|
||||||
|
CREATE TABLE content_relationships (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
parent_content_id UUID REFERENCES stored_content(id),
|
||||||
|
child_content_id UUID REFERENCES stored_content(id),
|
||||||
|
relationship_type VARCHAR(32) NOT NULL, -- 'encrypted', 'decrypted', 'preview'
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
|
||||||
|
UNIQUE(parent_content_id, child_content_id, relationship_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Индексы для производительности
|
||||||
|
CREATE INDEX idx_content_rel_parent ON content_relationships(parent_content_id);
|
||||||
|
CREATE INDEX idx_content_rel_child ON content_relationships(child_content_id);
|
||||||
|
CREATE INDEX idx_content_rel_type ON content_relationships(relationship_type);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Алгоритмы Репликации Всех Состояний
|
||||||
|
|
||||||
|
### 1. Multi-State Replication Algorithm
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ContentStateReplicator:
|
||||||
|
async def replicate_content_group(self, content_group: ContentGroup):
|
||||||
|
"""
|
||||||
|
Реплицирует группу связанных состояний контента
|
||||||
|
"""
|
||||||
|
# Шаг 1: Определить все связанные состояния
|
||||||
|
states = await self.discover_content_states(content_group.root_id)
|
||||||
|
|
||||||
|
# Шаг 2: Проверить целостность связей
|
||||||
|
await self.verify_state_relationships(states)
|
||||||
|
|
||||||
|
# Шаг 3: Создать план репликации
|
||||||
|
replication_plan = await self.create_replication_plan(states)
|
||||||
|
|
||||||
|
# Шаг 4: Выполнить репликацию по плану
|
||||||
|
for batch in replication_plan.batches:
|
||||||
|
await self.replicate_batch(batch)
|
||||||
|
await self.verify_batch_integrity(batch)
|
||||||
|
|
||||||
|
# Шаг 5: Обновить метаданные о репликации
|
||||||
|
await self.update_replication_metadata(content_group, states)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. State Discovery Algorithm
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def discover_content_states(root_content_id: str) -> List[ContentState]:
|
||||||
|
"""
|
||||||
|
Обнаруживает все связанные состояния контента
|
||||||
|
"""
|
||||||
|
states = []
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
# BFS поиск всех связанных состояний
|
||||||
|
queue = [root_content_id]
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
content_id = queue.pop(0)
|
||||||
|
if content_id in visited:
|
||||||
|
continue
|
||||||
|
|
||||||
|
visited.add(content_id)
|
||||||
|
content = await StoredContent.get_by_id(content_id)
|
||||||
|
|
||||||
|
if not content:
|
||||||
|
continue
|
||||||
|
|
||||||
|
states.append(ContentState(
|
||||||
|
content=content,
|
||||||
|
relationships=await self.get_relationships(content_id)
|
||||||
|
))
|
||||||
|
|
||||||
|
# Добавить связанные состояния в очередь
|
||||||
|
relationships = await self.get_relationships(content_id)
|
||||||
|
for rel in relationships:
|
||||||
|
if rel.child_content_id not in visited:
|
||||||
|
queue.append(rel.child_content_id)
|
||||||
|
|
||||||
|
return states
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Atomic State Replication
|
||||||
|
|
||||||
|
```python
|
||||||
|
class AtomicStateReplication:
|
||||||
|
async def replicate_state_group(self, states: List[ContentState],
|
||||||
|
target_peers: List[PeerNode]):
|
||||||
|
"""
|
||||||
|
Атомарная репликация группы состояний
|
||||||
|
"""
|
||||||
|
transaction_id = str(uuid4())
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Phase 1: Prepare - подготовка к репликации
|
||||||
|
await self.prepare_replication(transaction_id, states, target_peers)
|
||||||
|
|
||||||
|
# Phase 2: Transfer - передача данных
|
||||||
|
for state in states:
|
||||||
|
await self.transfer_state(state, target_peers, transaction_id)
|
||||||
|
|
||||||
|
# Phase 3: Verify - проверка целостности
|
||||||
|
verification_results = await self.verify_replicated_states(
|
||||||
|
states, target_peers, transaction_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Phase 4: Commit or Abort
|
||||||
|
if all(verification_results):
|
||||||
|
await self.commit_replication(transaction_id, target_peers)
|
||||||
|
else:
|
||||||
|
await self.abort_replication(transaction_id, target_peers)
|
||||||
|
raise ReplicationError("State verification failed")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await self.cleanup_failed_replication(transaction_id, target_peers)
|
||||||
|
raise e
|
||||||
|
```
|
||||||
|
|
||||||
|
## MY Network Service Layer
|
||||||
|
|
||||||
|
### Service Component Architecture
|
||||||
|
|
||||||
|
```python
|
||||||
|
# MY Network Service Manager
|
||||||
|
class MYNetworkService:
|
||||||
|
def __init__(self):
|
||||||
|
self.p2p_manager = P2PManager()
|
||||||
|
self.consensus_engine = ConsensusEngine()
|
||||||
|
self.replication_manager = ReplicationManager()
|
||||||
|
self.sync_coordinator = SyncCoordinator()
|
||||||
|
self.content_discovery = ContentDiscoveryService()
|
||||||
|
|
||||||
|
async def start_service(self):
|
||||||
|
"""Запуск MY Network сервиса"""
|
||||||
|
await self.p2p_manager.initialize()
|
||||||
|
await self.consensus_engine.start()
|
||||||
|
await self.replication_manager.start()
|
||||||
|
await self.sync_coordinator.start()
|
||||||
|
|
||||||
|
# Регистрация в сети
|
||||||
|
await self.register_node()
|
||||||
|
|
||||||
|
async def register_node(self):
|
||||||
|
"""Регистрация ноды в MY Network"""
|
||||||
|
node_info = {
|
||||||
|
"node_id": self.get_node_id(),
|
||||||
|
"address": self.get_public_address(),
|
||||||
|
"capabilities": self.get_node_capabilities(),
|
||||||
|
"content_stats": await self.get_content_statistics()
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.p2p_manager.announce_node(node_info)
|
||||||
|
```
|
||||||
|
|
||||||
|
### P2P Communication Layer
|
||||||
|
|
||||||
|
```python
|
||||||
|
class P2PManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.peers = {}
|
||||||
|
self.message_handlers = {}
|
||||||
|
self.connection_pool = ConnectionPool()
|
||||||
|
|
||||||
|
async def handle_peer_message(self, peer_id: str, message: dict):
|
||||||
|
"""Обработка сообщений от пиров"""
|
||||||
|
msg_type = message.get("type")
|
||||||
|
handler = self.message_handlers.get(msg_type)
|
||||||
|
|
||||||
|
if handler:
|
||||||
|
await handler(peer_id, message)
|
||||||
|
else:
|
||||||
|
logger.warning(f"Unknown message type: {msg_type}")
|
||||||
|
|
||||||
|
async def broadcast_content_announcement(self, content: StoredContent):
|
||||||
|
"""Анонс нового контента в сети"""
|
||||||
|
announcement = {
|
||||||
|
"type": "content_announcement",
|
||||||
|
"content_hash": content.hash,
|
||||||
|
"content_type": content.content_type,
|
||||||
|
"encrypted": content.encrypted,
|
||||||
|
"file_size": content.file_size,
|
||||||
|
"timestamp": datetime.utcnow().isoformat()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Отправка всем активным пирам
|
||||||
|
for peer_id in self.get_active_peers():
|
||||||
|
await self.send_message(peer_id, announcement)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Consensus Engine Implementation
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ConsensusEngine:
|
||||||
|
def __init__(self, min_quorum: int = 3):
|
||||||
|
self.min_quorum = min_quorum
|
||||||
|
self.pending_votes = {}
|
||||||
|
self.consensus_results = {}
|
||||||
|
|
||||||
|
async def propose_content(self, content_hash: str) -> bool:
|
||||||
|
"""Предложение контента для консенсуса"""
|
||||||
|
proposal_id = str(uuid4())
|
||||||
|
|
||||||
|
proposal = {
|
||||||
|
"id": proposal_id,
|
||||||
|
"content_hash": content_hash,
|
||||||
|
"proposer": self.node_id,
|
||||||
|
"timestamp": datetime.utcnow(),
|
||||||
|
"votes": {},
|
||||||
|
"status": "pending"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pending_votes[proposal_id] = proposal
|
||||||
|
|
||||||
|
# Отправка предложения пирам
|
||||||
|
await self.broadcast_proposal(proposal)
|
||||||
|
|
||||||
|
# Ожидание консенсуса с таймаутом
|
||||||
|
result = await self.wait_for_consensus(proposal_id, timeout=30)
|
||||||
|
return result
|
||||||
|
|
||||||
|
async def vote_on_proposal(self, proposal_id: str, vote: bool):
|
||||||
|
"""Голосование по предложению"""
|
||||||
|
if proposal_id not in self.pending_votes:
|
||||||
|
return False
|
||||||
|
|
||||||
|
proposal = self.pending_votes[proposal_id]
|
||||||
|
proposal["votes"][self.node_id] = {
|
||||||
|
"vote": vote,
|
||||||
|
"timestamp": datetime.utcnow(),
|
||||||
|
"signature": await self.sign_vote(proposal_id, vote)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Проверка достижения консенсуса
|
||||||
|
await self.check_consensus(proposal_id)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Content Discovery & Routing
|
||||||
|
|
||||||
|
### Distributed Hash Table (DHT) для Content Discovery
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ContentDHT:
|
||||||
|
def __init__(self, node_id: str):
|
||||||
|
self.node_id = node_id
|
||||||
|
self.routing_table = {}
|
||||||
|
self. content_index = {}
|
||||||
|
|
||||||
|
async def announce_content(self, content_hash: str, content_info: dict):
|
||||||
|
"""Анонс контента в DHT"""
|
||||||
|
key_hash = self.hash_key(content_hash)
|
||||||
|
responsible_nodes = await self.find_responsible_nodes(key_hash)
|
||||||
|
|
||||||
|
for node in responsible_nodes:
|
||||||
|
await self.store_content_info(node, content_hash, content_info)
|
||||||
|
|
||||||
|
async def find_content(self, content_hash: str) -> List[PeerInfo]:
|
||||||
|
"""Поиск нод с контентом"""
|
||||||
|
key_hash = self.hash_key(content_hash)
|
||||||
|
responsible_nodes = await self.find_responsible_nodes(key_hash)
|
||||||
|
|
||||||
|
peers_with_content = []
|
||||||
|
for node in responsible_nodes:
|
||||||
|
content_info = await self.get_content_info(node, content_hash)
|
||||||
|
if content_info:
|
||||||
|
peers_with_content.extend(content_info.get("peers", []))
|
||||||
|
|
||||||
|
return peers_with_content
|
||||||
|
```
|
||||||
|
|
||||||
|
### Smart Content Routing
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ContentRouter:
|
||||||
|
def __init__(self):
|
||||||
|
self.peer_metrics = {}
|
||||||
|
self.content_popularity = {}
|
||||||
|
|
||||||
|
async def find_optimal_peers(self, content_hash: str,
|
||||||
|
count: int = 3) -> List[PeerInfo]:
|
||||||
|
"""Поиск оптимальных пиров для загрузки"""
|
||||||
|
available_peers = await self.content_dht.find_content(content_hash)
|
||||||
|
|
||||||
|
# Сортировка по метрикам производительности
|
||||||
|
scored_peers = []
|
||||||
|
for peer in available_peers:
|
||||||
|
score = await self.calculate_peer_score(peer, content_hash)
|
||||||
|
scored_peers.append((peer, score))
|
||||||
|
|
||||||
|
# Возврат топ пиров
|
||||||
|
scored_peers.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
return [peer for peer, score in scored_peers[:count]]
|
||||||
|
|
||||||
|
async def calculate_peer_score(self, peer: PeerInfo,
|
||||||
|
content_hash: str) -> float:
|
||||||
|
"""Вычисление оценки пира"""
|
||||||
|
metrics = self.peer_metrics.get(peer.node_id, {})
|
||||||
|
|
||||||
|
# Факторы оценки
|
||||||
|
latency_score = 1.0 / max(metrics.get("avg_latency", 1), 0.01)
|
||||||
|
bandwidth_score = metrics.get("bandwidth", 1.0)
|
||||||
|
reliability_score = metrics.get("uptime", 0.5)
|
||||||
|
reputation_score = peer.reputation_score
|
||||||
|
|
||||||
|
# Взвешенная оценка
|
||||||
|
total_score = (
|
||||||
|
latency_score * 0.3 +
|
||||||
|
bandwidth_score * 0.3 +
|
||||||
|
reliability_score * 0.2 +
|
||||||
|
reputation_score * 0.2
|
||||||
|
)
|
||||||
|
|
||||||
|
return total_score
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring & Health System
|
||||||
|
|
||||||
|
### Node Health Monitoring
|
||||||
|
|
||||||
|
```python
|
||||||
|
class NodeHealthMonitor:
|
||||||
|
def __init__(self):
|
||||||
|
self.health_metrics = {}
|
||||||
|
self.alert_thresholds = {
|
||||||
|
"cpu_usage": 80.0,
|
||||||
|
"memory_usage": 85.0,
|
||||||
|
"disk_usage": 90.0,
|
||||||
|
"network_latency": 1000.0, # ms
|
||||||
|
"peer_count": 3 # minimum
|
||||||
|
}
|
||||||
|
|
||||||
|
async def collect_health_metrics(self) -> dict:
|
||||||
|
"""Сбор метрик здоровья ноды"""
|
||||||
|
return {
|
||||||
|
"cpu_usage": await self.get_cpu_usage(),
|
||||||
|
"memory_usage": await self.get_memory_usage(),
|
||||||
|
"disk_usage": await self.get_disk_usage(),
|
||||||
|
"network_latency": await self.measure_network_latency(),
|
||||||
|
"peer_count": len(await self.get_active_peers()),
|
||||||
|
"sync_status": await self.get_sync_status(),
|
||||||
|
"timestamp": datetime.utcnow().isoformat()
|
||||||
|
}
|
||||||
|
|
||||||
|
async def check_health_alerts(self, metrics: dict):
|
||||||
|
"""Проверка критических состояний"""
|
||||||
|
alerts = []
|
||||||
|
|
||||||
|
for metric, value in metrics.items():
|
||||||
|
threshold = self.alert_thresholds.get(metric)
|
||||||
|
if threshold and value > threshold:
|
||||||
|
alerts.append({
|
||||||
|
"metric": metric,
|
||||||
|
"value": value,
|
||||||
|
"threshold": threshold,
|
||||||
|
"severity": "critical" if value > threshold * 1.2 else "warning"
|
||||||
|
})
|
||||||
|
|
||||||
|
if alerts:
|
||||||
|
await self.send_health_alerts(alerts)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Analytics
|
||||||
|
|
||||||
|
```python
|
||||||
|
class PerformanceAnalyzer:
|
||||||
|
def __init__(self):
|
||||||
|
self.metrics_storage = MetricsStorage()
|
||||||
|
|
||||||
|
async def analyze_replication_performance(self) -> dict:
|
||||||
|
"""Анализ производительности репликации"""
|
||||||
|
recent_replications = await self.get_recent_replications(hours=24)
|
||||||
|
|
||||||
|
analysis = {
|
||||||
|
"total_replications": len(recent_replications),
|
||||||
|
"success_rate": self.calculate_success_rate(recent_replications),
|
||||||
|
"average_time": self.calculate_average_time(recent_replications),
|
||||||
|
"throughput": self.calculate_throughput(recent_replications),
|
||||||
|
"failed_replications": self.get_failed_replications(recent_replications)
|
||||||
|
}
|
||||||
|
|
||||||
|
return analysis
|
||||||
|
|
||||||
|
async def generate_performance_report(self) -> dict:
|
||||||
|
"""Генерация отчета о производительности"""
|
||||||
|
return {
|
||||||
|
"network_performance": await self.analyze_network_performance(),
|
||||||
|
"replication_performance": await self.analyze_replication_performance(),
|
||||||
|
"consensus_performance": await self.analyze_consensus_performance(),
|
||||||
|
"content_distribution": await self.analyze_content_distribution(),
|
||||||
|
"peer_performance": await self.analyze_peer_performance()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Architecture
|
||||||
|
|
||||||
|
### Multi-Layer Security Model
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Application Security │ <- Existing auth & validation
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ Network Security │ <- MY Network specific
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ Transport Security │ <- TLS/mTLS
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ Content Security │ <- Encryption & integrity
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Security Implementation
|
||||||
|
|
||||||
|
```python
|
||||||
|
class NetworkSecurity:
|
||||||
|
def __init__(self):
|
||||||
|
self.node_keypair = self.load_or_generate_keypair()
|
||||||
|
self.trusted_nodes = set()
|
||||||
|
self.blacklisted_nodes = set()
|
||||||
|
|
||||||
|
async def verify_peer_identity(self, peer_id: str,
|
||||||
|
signature: str, message: bytes) -> bool:
|
||||||
|
"""Проверка подлинности пира"""
|
||||||
|
public_key = await self.get_peer_public_key(peer_id)
|
||||||
|
if not public_key:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return await self.verify_signature(public_key, signature, message)
|
||||||
|
|
||||||
|
async def encrypt_message(self, message: bytes,
|
||||||
|
recipient_public_key: bytes) -> bytes:
|
||||||
|
"""Шифрование сообщения для получателя"""
|
||||||
|
# Используем ECIES для асимметричного шифрования
|
||||||
|
encrypted = await self.ecies_encrypt(message, recipient_public_key)
|
||||||
|
return encrypted
|
||||||
|
|
||||||
|
async def validate_content_integrity(self, content_hash: str,
|
||||||
|
content_data: bytes) -> bool:
|
||||||
|
"""Проверка целостности контента"""
|
||||||
|
calculated_hash = hashlib.sha256(content_data).hexdigest()
|
||||||
|
return calculated_hash == content_hash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scalability Considerations
|
||||||
|
|
||||||
|
### Horizontal Scaling Strategies
|
||||||
|
|
||||||
|
1. **Sharding по Content Hash**
|
||||||
|
- Контент распределяется по нодам на основе хеша
|
||||||
|
- Consistent hashing для равномерного распределения
|
||||||
|
- Автоматическое перебалансирование при изменении топологии
|
||||||
|
|
||||||
|
2. **Hierarchical Network Structure**
|
||||||
|
- Bootstrap ноды как суперноды
|
||||||
|
- Региональные кластеры
|
||||||
|
- Edge ноды для локального кеширования
|
||||||
|
|
||||||
|
3. **Adaptive Replication**
|
||||||
|
- Динамическое изменение количества реплик
|
||||||
|
- Репликация популярного контента на больше нод
|
||||||
|
- Удаление неиспользуемого контента
|
||||||
|
|
||||||
|
### Resource Management
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ResourceManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.storage_limits = {}
|
||||||
|
self.bandwidth_limits = {}
|
||||||
|
self.connection_limits = {}
|
||||||
|
|
||||||
|
async def allocate_resources(self, operation_type: str,
|
||||||
|
resource_requirements: dict) -> bool:
|
||||||
|
"""Выделение ресурсов для операции"""
|
||||||
|
if not await self.check_available_resources(resource_requirements):
|
||||||
|
return False
|
||||||
|
|
||||||
|
await self.reserve_resources(operation_type, resource_requirements)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def optimize_resource_usage(self):
|
||||||
|
"""Оптимизация использования ресурсов"""
|
||||||
|
# Анализ текущего использования
|
||||||
|
usage_stats = await self.get_resource_usage_stats()
|
||||||
|
|
||||||
|
# Определение возможностей для оптимизации
|
||||||
|
optimizations = await self.identify_optimizations(usage_stats)
|
||||||
|
|
||||||
|
# Применение оптимизаций
|
||||||
|
for optimization in optimizations:
|
||||||
|
await self.apply_optimization(optimization)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Disaster Recovery & Fault Tolerance
|
||||||
|
|
||||||
|
### Multi-Level Fault Tolerance
|
||||||
|
|
||||||
|
```python
|
||||||
|
class FaultToleranceManager:
|
||||||
|
async def handle_node_failure(self, failed_node_id: str):
|
||||||
|
"""Обработка отказа ноды"""
|
||||||
|
# 1. Обновление routing table
|
||||||
|
await self.remove_failed_node(failed_node_id)
|
||||||
|
|
||||||
|
# 2. Перенаправление трафика
|
||||||
|
await self.reroute_traffic_from_failed_node(failed_node_id)
|
||||||
|
|
||||||
|
# 3. Восстановление реплик
|
||||||
|
lost_content = await self.identify_lost_content(failed_node_id)
|
||||||
|
await self.restore_content_replicas(lost_content)
|
||||||
|
|
||||||
|
# 4. Уведомление сети об отказе
|
||||||
|
await self.broadcast_node_failure(failed_node_id)
|
||||||
|
|
||||||
|
async def restore_content_replicas(self, lost_content: List[str]):
|
||||||
|
"""Восстановление потерянных реплик контента"""
|
||||||
|
for content_hash in lost_content:
|
||||||
|
# Поиск существующих реплик
|
||||||
|
available_replicas = await self.find_content_replicas(content_hash)
|
||||||
|
|
||||||
|
if len(available_replicas) < self.min_replica_count:
|
||||||
|
# Создание дополнительных реплик
|
||||||
|
target_nodes = await self.select_replication_targets(content_hash)
|
||||||
|
await self.replicate_content(content_hash, target_nodes)
|
||||||
|
```
|
||||||
|
|
||||||
|
Эта архитектура обеспечивает надежную, масштабируемую и безопасную распределенную систему для репликации всех состояний контента с сохранением существующей функциональности системы.
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,422 @@
|
||||||
|
# MY Network v2.0 - Distributed Content Protocol
|
||||||
|
|
||||||
|
## 🌐 Обзор
|
||||||
|
|
||||||
|
MY Network - это распределенная система для управления и синхронизации контента между нодами. Протокол обеспечивает:
|
||||||
|
|
||||||
|
- **P2P сеть** для обмена данными между нодами
|
||||||
|
- **Автоматическую синхронизацию** контента
|
||||||
|
- **Load balancing** на основе метрик нагрузки
|
||||||
|
- **Веб-интерфейс мониторинга** в хакерском стиле
|
||||||
|
- **Совместимость** с существующей инфраструктурой
|
||||||
|
|
||||||
|
## 🚀 Быстрый запуск
|
||||||
|
|
||||||
|
### Минимальный запуск для тестирования:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Установить зависимости
|
||||||
|
pip install -r requirements_new.txt
|
||||||
|
|
||||||
|
# 2. Запустить минимальный сервер
|
||||||
|
python start_my_network.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Откройте http://localhost:8000/api/my/monitor/ для мониторинга.
|
||||||
|
|
||||||
|
### Запуск с существующей системой:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Использовать совместимые файлы
|
||||||
|
cp docker-compose.compatible.yml docker-compose.yml
|
||||||
|
cp .env.compatible .env
|
||||||
|
|
||||||
|
# 2. Запустить через Docker
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 3. MY Network автоматически интегрируется
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Продакшен развертывание
|
||||||
|
|
||||||
|
### Автоматическое развертывание:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Сохранить переменные окружения
|
||||||
|
export DOMAIN="your-domain.com"
|
||||||
|
export EMAIL="admin@your-domain.com"
|
||||||
|
|
||||||
|
# Запустить скрипт развертывания (требует root)
|
||||||
|
sudo bash deploy_my_network.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт автоматически установит:
|
||||||
|
- ✅ Nginx с SSL (Let's Encrypt)
|
||||||
|
- ✅ Docker и Docker Compose
|
||||||
|
- ✅ Firewall и безопасность
|
||||||
|
- ✅ Systemd сервисы
|
||||||
|
- ✅ Мониторинг и health checks
|
||||||
|
|
||||||
|
### Ручное развертывание:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Создать production .env
|
||||||
|
cp .env.example .env.production
|
||||||
|
# Отредактировать настройки
|
||||||
|
|
||||||
|
# 2. Запустить продакшен контейнеры
|
||||||
|
docker-compose -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
# 3. Настроить nginx
|
||||||
|
sudo cp nginx.conf /etc/nginx/sites-available/my-network
|
||||||
|
sudo ln -s /etc/nginx/sites-available/my-network /etc/nginx/sites-enabled/
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Мониторинг и управление
|
||||||
|
|
||||||
|
### Веб-интерфейс:
|
||||||
|
- **Основной мониторинг**: http://your-domain/api/my/monitor/
|
||||||
|
- **ASCII статус**: http://your-domain/api/my/monitor/ascii
|
||||||
|
- **API документация**: http://your-domain/api/docs
|
||||||
|
|
||||||
|
### API эндпоинты:
|
||||||
|
|
||||||
|
#### Информация о ноде:
|
||||||
|
```bash
|
||||||
|
# Статус ноды
|
||||||
|
curl http://localhost:8000/api/my/node/info
|
||||||
|
|
||||||
|
# Подключенные пиры
|
||||||
|
curl http://localhost:8000/api/my/node/peers
|
||||||
|
|
||||||
|
# Статус синхронизации
|
||||||
|
curl http://localhost:8000/api/my/sync/status
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Управление пирами:
|
||||||
|
```bash
|
||||||
|
# Подключиться к пиру
|
||||||
|
curl -X POST http://localhost:8000/api/my/node/peers/connect \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"address": "http://peer-node:8001"}'
|
||||||
|
|
||||||
|
# Отключиться от пира
|
||||||
|
curl -X DELETE http://localhost:8000/api/my/node/peers/PEER_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Синхронизация:
|
||||||
|
```bash
|
||||||
|
# Запустить синхронизацию
|
||||||
|
curl -X POST http://localhost:8000/api/my/sync/start
|
||||||
|
|
||||||
|
# Реплицировать контент
|
||||||
|
curl -X POST http://localhost:8000/api/my/content/HASH/replicate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"target_nodes": ["node1", "node2"]}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Системные команды:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Управление сервисом
|
||||||
|
sudo systemctl start my-network
|
||||||
|
sudo systemctl stop my-network
|
||||||
|
sudo systemctl restart my-network
|
||||||
|
sudo systemctl status my-network
|
||||||
|
|
||||||
|
# Просмотр логов
|
||||||
|
sudo journalctl -u my-network -f
|
||||||
|
tail -f /var/log/my-network/app.log
|
||||||
|
|
||||||
|
# Проверка здоровья
|
||||||
|
/opt/my-network/health_check.sh
|
||||||
|
|
||||||
|
# Docker команды
|
||||||
|
docker-compose logs -f my-network-app
|
||||||
|
docker-compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Конфигурация
|
||||||
|
|
||||||
|
### Основные настройки (.env):
|
||||||
|
|
||||||
|
```env
|
||||||
|
# MY Network Configuration
|
||||||
|
MY_NETWORK_ENABLED=True
|
||||||
|
MY_NETWORK_NODE_ID=unique-node-id
|
||||||
|
MY_NETWORK_P2P_PORT=8001
|
||||||
|
MY_NETWORK_API_PORT=8000
|
||||||
|
|
||||||
|
# Bootstrap ноды (JSON массив)
|
||||||
|
MY_NETWORK_BOOTSTRAP_NODES=["http://bootstrap1:8001", "http://bootstrap2:8001"]
|
||||||
|
|
||||||
|
# Настройки синхронизации
|
||||||
|
SYNC_MAX_CONCURRENT=5
|
||||||
|
SYNC_TIMEOUT=300
|
||||||
|
SYNC_RETRY_ATTEMPTS=3
|
||||||
|
|
||||||
|
# Настройки пиров
|
||||||
|
PEER_HEALTH_CHECK_INTERVAL=60
|
||||||
|
PEER_CONNECTION_TIMEOUT=30
|
||||||
|
MAX_PEER_CONNECTIONS=50
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bootstrap конфигурация (bootstrap.json):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "2.0",
|
||||||
|
"network_id": "my-network-main",
|
||||||
|
"bootstrap_nodes": [
|
||||||
|
{
|
||||||
|
"node_id": "bootstrap-1",
|
||||||
|
"address": "https://bootstrap1.my-network.com:8001",
|
||||||
|
"public_key": "...",
|
||||||
|
"trusted": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"consensus": {
|
||||||
|
"algorithm": "raft",
|
||||||
|
"election_timeout": 5000,
|
||||||
|
"heartbeat_interval": 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌍 Архитектура сети
|
||||||
|
|
||||||
|
### Компоненты:
|
||||||
|
|
||||||
|
1. **Node Service** - основной сервис ноды
|
||||||
|
2. **Peer Manager** - управление подключениями
|
||||||
|
3. **Sync Manager** - синхронизация контента
|
||||||
|
4. **Bootstrap Manager** - управление bootstrap конфигурацией
|
||||||
|
|
||||||
|
### Протокол взаимодействия:
|
||||||
|
|
||||||
|
```
|
||||||
|
Нода A Нода B
|
||||||
|
| |
|
||||||
|
|--- Handshake ---------> |
|
||||||
|
|<-- Auth Response ------- |
|
||||||
|
| |
|
||||||
|
|--- Content List ------> |
|
||||||
|
|<-- Missing Content ---- |
|
||||||
|
| |
|
||||||
|
|--- File Transfer -----> |
|
||||||
|
|<-- Confirmation ------- |
|
||||||
|
```
|
||||||
|
|
||||||
|
### Состояния контента:
|
||||||
|
|
||||||
|
- **Local** - только на текущей ноде
|
||||||
|
- **Syncing** - в процессе синхронизации
|
||||||
|
- **Replicated** - скопирован на другие ноды
|
||||||
|
- **Verified** - проверена целостность
|
||||||
|
|
||||||
|
## 🔒 Безопасность
|
||||||
|
|
||||||
|
### Встроенные механизмы:
|
||||||
|
|
||||||
|
- **TLS шифрование** для всех соединений
|
||||||
|
- **Проверка хешей** для целостности файлов
|
||||||
|
- **Аутентификация пиров** через public key
|
||||||
|
- **Rate limiting** для предотвращения DDoS
|
||||||
|
- **Firewall правила** для ограничения доступа
|
||||||
|
|
||||||
|
### Рекомендации:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Настроить firewall
|
||||||
|
sudo ufw allow 8000:8010/tcp
|
||||||
|
sudo ufw allow 8000:8010/udp
|
||||||
|
|
||||||
|
# Включить fail2ban
|
||||||
|
sudo systemctl enable fail2ban
|
||||||
|
|
||||||
|
# Регулярные бэкапы
|
||||||
|
0 2 * * * /opt/my-network/backup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 Мониторинг и алерты
|
||||||
|
|
||||||
|
### Метрики:
|
||||||
|
|
||||||
|
- **Количество подключенных пиров**
|
||||||
|
- **Статус синхронизации**
|
||||||
|
- **Использование ресурсов**
|
||||||
|
- **Время отклика**
|
||||||
|
- **Ошибки сети**
|
||||||
|
|
||||||
|
### Health checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# HTTP health check
|
||||||
|
curl -f http://localhost:8000/health
|
||||||
|
|
||||||
|
# MY Network specific
|
||||||
|
curl -f http://localhost:8000/api/my/health
|
||||||
|
|
||||||
|
# Detailed status
|
||||||
|
curl http://localhost:8000/api/my/network/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prometheus интеграция:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# prometheus.yml
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'my-network'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['localhost:9090']
|
||||||
|
metrics_path: '/metrics'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 Устранение неисправностей
|
||||||
|
|
||||||
|
### Частые проблемы:
|
||||||
|
|
||||||
|
#### 1. Нода не подключается к пирам:
|
||||||
|
```bash
|
||||||
|
# Проверить сетевые соединения
|
||||||
|
netstat -tulpn | grep 8001
|
||||||
|
|
||||||
|
# Проверить firewall
|
||||||
|
sudo ufw status
|
||||||
|
|
||||||
|
# Проверить логи
|
||||||
|
tail -f /var/log/my-network/app.log
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Синхронизация не работает:
|
||||||
|
```bash
|
||||||
|
# Проверить статус синхронизации
|
||||||
|
curl http://localhost:8000/api/my/sync/status
|
||||||
|
|
||||||
|
# Перезапустить синхронизацию
|
||||||
|
curl -X POST http://localhost:8000/api/my/sync/start
|
||||||
|
|
||||||
|
# Проверить доступность целевых нод
|
||||||
|
curl http://target-node:8001/api/my/health
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Высокое использование ресурсов:
|
||||||
|
```bash
|
||||||
|
# Проверить использование CPU/памяти
|
||||||
|
docker stats my-network-app
|
||||||
|
|
||||||
|
# Ограничить ресурсы
|
||||||
|
docker update --memory=2g --cpus=2 my-network-app
|
||||||
|
|
||||||
|
# Настроить параметры синхронизации
|
||||||
|
echo "SYNC_MAX_CONCURRENT=2" >> .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Диагностические команды:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить все компоненты
|
||||||
|
curl http://localhost:8000/api/my/health | jq
|
||||||
|
|
||||||
|
# Список активных соединений
|
||||||
|
curl http://localhost:8000/api/my/node/peers | jq
|
||||||
|
|
||||||
|
# Статистика сети
|
||||||
|
curl http://localhost:8000/api/my/network/stats | jq
|
||||||
|
|
||||||
|
# ASCII статус (для консоли)
|
||||||
|
curl http://localhost:8000/api/my/monitor/ascii
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Обновление системы
|
||||||
|
|
||||||
|
### Обновление без downtime:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Подготовить новую версию
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 2. Собрать новый образ
|
||||||
|
docker-compose build my-network-app
|
||||||
|
|
||||||
|
# 3. Rolling update
|
||||||
|
docker-compose up -d --no-deps my-network-app
|
||||||
|
|
||||||
|
# 4. Проверить статус
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Миграция данных:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Экспорт данных
|
||||||
|
docker exec my-network-db mysqldump -u root -p mymusic > backup.sql
|
||||||
|
|
||||||
|
# Миграция схемы (если нужно)
|
||||||
|
docker exec my-network-app python -m alembic upgrade head
|
||||||
|
|
||||||
|
# Импорт данных
|
||||||
|
docker exec -i my-network-db mysql -u root -p mymusic < backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Дополнительная документация
|
||||||
|
|
||||||
|
- **MY_ARCHITECTURE.md** - детальная архитектура системы
|
||||||
|
- **MY_PROTOCOL.md** - спецификация протокола
|
||||||
|
- **MY_NODE_SPEC.md** - технические характеристики нод
|
||||||
|
- **MY_MONITORING.md** - руководство по мониторингу
|
||||||
|
|
||||||
|
## 🤝 Вклад в проект
|
||||||
|
|
||||||
|
### Структура проекта:
|
||||||
|
|
||||||
|
```
|
||||||
|
my-uploader-bot/
|
||||||
|
├── app/
|
||||||
|
│ ├── core/
|
||||||
|
│ │ └── my_network/ # MY Network компоненты
|
||||||
|
│ │ ├── node_service.py
|
||||||
|
│ │ ├── peer_manager.py
|
||||||
|
│ │ ├── sync_manager.py
|
||||||
|
│ │ └── bootstrap_manager.py
|
||||||
|
│ ├── api/
|
||||||
|
│ │ └── routes/ # API маршруты
|
||||||
|
│ │ ├── my_network_routes.py
|
||||||
|
│ │ └── my_monitoring.py
|
||||||
|
│ └── templates/ # Web интерфейс
|
||||||
|
│ └── my_network_monitor.html
|
||||||
|
├── bootstrap.json # Bootstrap конфигурация
|
||||||
|
├── start_my_network.py # Быстрый запуск
|
||||||
|
└── deploy_my_network.sh # Продакшен деплой
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development workflow:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Создать ветку для фичи
|
||||||
|
git checkout -b feature/my-feature
|
||||||
|
|
||||||
|
# 2. Разработка с hot reload
|
||||||
|
python start_my_network.py --debug
|
||||||
|
|
||||||
|
# 3. Тестирование
|
||||||
|
pytest tests/test_my_network.py
|
||||||
|
|
||||||
|
# 4. Создать pull request
|
||||||
|
git push origin feature/my-feature
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 Поддержка
|
||||||
|
|
||||||
|
Если у вас возникли вопросы или проблемы:
|
||||||
|
|
||||||
|
1. Проверьте [Troubleshooting](#-устранение-неисправностей)
|
||||||
|
2. Посмотрите логи: `tail -f /var/log/my-network/app.log`
|
||||||
|
3. Проверьте health check: `curl http://localhost:8000/api/my/health`
|
||||||
|
4. Создайте issue с подробным описанием проблемы
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**MY Network v2.0** - Distributed Content Protocol
|
||||||
|
*Decentralized content distribution made simple*
|
||||||
|
|
@ -0,0 +1,791 @@
|
||||||
|
# MY Network Node Specification
|
||||||
|
|
||||||
|
## Обзор MY Network Node
|
||||||
|
|
||||||
|
MY Network Node представляет собой расширение существующего my-uploader-bot, добавляющее возможности участия в децентрализованной сети без нарушения текущей функциональности.
|
||||||
|
|
||||||
|
## Процесс Запуска и Инициализации Ноды
|
||||||
|
|
||||||
|
### 1. Startup Sequence
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MYNetworkNode:
|
||||||
|
async def initialize(self):
|
||||||
|
"""Полная инициализация MY Network ноды"""
|
||||||
|
|
||||||
|
# Phase 1: Core System Check
|
||||||
|
await self.verify_core_system()
|
||||||
|
|
||||||
|
# Phase 2: Load Configuration
|
||||||
|
await self.load_configuration()
|
||||||
|
|
||||||
|
# Phase 3: Initialize Cryptography
|
||||||
|
await self.initialize_crypto_system()
|
||||||
|
|
||||||
|
# Phase 4: Start Network Services
|
||||||
|
await self.start_network_services()
|
||||||
|
|
||||||
|
# Phase 5: Connect to Bootstrap Nodes
|
||||||
|
await self.connect_to_bootstrap_nodes()
|
||||||
|
|
||||||
|
# Phase 6: Discover Peers
|
||||||
|
await self.start_peer_discovery()
|
||||||
|
|
||||||
|
# Phase 7: Sync Content
|
||||||
|
await self.start_initial_sync()
|
||||||
|
|
||||||
|
# Phase 8: Start Background Services
|
||||||
|
await self.start_background_services()
|
||||||
|
|
||||||
|
logger.info("MY Network Node successfully initialized")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configuration Loading
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def load_configuration(self):
|
||||||
|
"""Загрузка конфигурации ноды"""
|
||||||
|
|
||||||
|
# Загрузка bootstrap.json
|
||||||
|
self.bootstrap_config = await self.load_bootstrap_config()
|
||||||
|
|
||||||
|
# Загрузка локальной конфигурации
|
||||||
|
self.node_config = await self.load_node_config()
|
||||||
|
|
||||||
|
# Объединение конфигураций
|
||||||
|
self.config = {
|
||||||
|
**self.bootstrap_config,
|
||||||
|
**self.node_config,
|
||||||
|
"node_id": self.generate_or_load_node_id(),
|
||||||
|
"startup_time": datetime.utcnow().isoformat()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Crypto System Initialization
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def initialize_crypto_system(self):
|
||||||
|
"""Инициализация криптографической системы"""
|
||||||
|
|
||||||
|
# Загрузка или генерация ключевой пары ноды
|
||||||
|
self.node_keypair = await self.load_or_generate_keypair()
|
||||||
|
|
||||||
|
# Создание подписывающего объекта
|
||||||
|
self.signer = Ed25519Signer(self.node_keypair.private_key)
|
||||||
|
|
||||||
|
# Инициализация шифрования транспорта
|
||||||
|
self.transport_crypto = TransportCrypto(self.node_keypair)
|
||||||
|
|
||||||
|
# Проверка криптографической системы
|
||||||
|
await self.verify_crypto_system()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Подключение к Bootstrap Нодам
|
||||||
|
|
||||||
|
### 1. Bootstrap Discovery Process
|
||||||
|
|
||||||
|
```python
|
||||||
|
class BootstrapConnector:
|
||||||
|
async def connect_to_bootstrap_nodes(self):
|
||||||
|
"""Подключение к bootstrap нодам"""
|
||||||
|
|
||||||
|
bootstrap_nodes = self.config["bootstrap_nodes"]
|
||||||
|
connected_nodes = []
|
||||||
|
|
||||||
|
for node_info in bootstrap_nodes:
|
||||||
|
try:
|
||||||
|
connection = await self.establish_connection(node_info)
|
||||||
|
if connection:
|
||||||
|
connected_nodes.append(connection)
|
||||||
|
logger.info(f"Connected to bootstrap node: {node_info['id']}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to connect to bootstrap node {node_info['id']}: {e}")
|
||||||
|
|
||||||
|
if len(connected_nodes) == 0:
|
||||||
|
raise BootstrapConnectionError("Failed to connect to any bootstrap nodes")
|
||||||
|
|
||||||
|
# Сохранение подключений
|
||||||
|
self.bootstrap_connections = connected_nodes
|
||||||
|
|
||||||
|
# Запрос информации о сети
|
||||||
|
await self.request_network_info()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Network Information Exchange
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def request_network_info(self):
|
||||||
|
"""Запрос информации о сети от bootstrap нод"""
|
||||||
|
|
||||||
|
network_info = {}
|
||||||
|
|
||||||
|
for connection in self.bootstrap_connections:
|
||||||
|
try:
|
||||||
|
# Запрос списка активных нод
|
||||||
|
peers_response = await connection.request("get_active_peers")
|
||||||
|
network_info["peers"] = peers_response.get("peers", [])
|
||||||
|
|
||||||
|
# Запрос статистики сети
|
||||||
|
stats_response = await connection.request("get_network_stats")
|
||||||
|
network_info["stats"] = stats_response.get("stats", {})
|
||||||
|
|
||||||
|
# Запрос популярного контента
|
||||||
|
content_response = await connection.request("get_popular_content")
|
||||||
|
network_info["popular_content"] = content_response.get("content", [])
|
||||||
|
|
||||||
|
break # Достаточно получить от одной ноды
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to get network info from bootstrap: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.network_info = network_info
|
||||||
|
```
|
||||||
|
|
||||||
|
## Механизм Обнаружения Других Нод
|
||||||
|
|
||||||
|
### 1. Peer Discovery Algorithm
|
||||||
|
|
||||||
|
```python
|
||||||
|
class PeerDiscovery:
|
||||||
|
def __init__(self, node: MYNetworkNode):
|
||||||
|
self.node = node
|
||||||
|
self.discovered_peers = {}
|
||||||
|
self.discovery_interval = 60 # секунды
|
||||||
|
|
||||||
|
async def start_discovery(self):
|
||||||
|
"""Запуск процесса обнаружения пиров"""
|
||||||
|
|
||||||
|
# Обнаружение через bootstrap ноды
|
||||||
|
await self.discover_through_bootstrap()
|
||||||
|
|
||||||
|
# DHT-based discovery
|
||||||
|
await self.discover_through_dht()
|
||||||
|
|
||||||
|
# Multicast discovery (для локальной сети)
|
||||||
|
await self.discover_through_multicast()
|
||||||
|
|
||||||
|
# Запуск периодического обнаружения
|
||||||
|
asyncio.create_task(self.periodic_discovery())
|
||||||
|
|
||||||
|
async def discover_through_bootstrap(self):
|
||||||
|
"""Обнаружение через bootstrap ноды"""
|
||||||
|
|
||||||
|
for connection in self.node.bootstrap_connections:
|
||||||
|
try:
|
||||||
|
# Запрос списка пиров
|
||||||
|
response = await connection.request("discover_peers", {
|
||||||
|
"requesting_node": self.node.node_id,
|
||||||
|
"max_peers": 50,
|
||||||
|
"exclude_nodes": list(self.discovered_peers.keys())
|
||||||
|
})
|
||||||
|
|
||||||
|
# Обработка найденных пиров
|
||||||
|
for peer_info in response.get("peers", []):
|
||||||
|
await self.process_discovered_peer(peer_info)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Peer discovery through bootstrap failed: {e}")
|
||||||
|
|
||||||
|
async def discover_through_dht(self):
|
||||||
|
"""Обнаружение через DHT"""
|
||||||
|
|
||||||
|
# Поиск нод ответственных за наш ключ
|
||||||
|
our_key_hash = self.node.calculate_key_hash(self.node.node_id)
|
||||||
|
responsible_nodes = await self.find_responsible_nodes(our_key_hash)
|
||||||
|
|
||||||
|
for node_info in responsible_nodes:
|
||||||
|
await self.process_discovered_peer(node_info)
|
||||||
|
|
||||||
|
async def process_discovered_peer(self, peer_info: dict):
|
||||||
|
"""Обработка обнаруженного пира"""
|
||||||
|
|
||||||
|
peer_id = peer_info["node_id"]
|
||||||
|
|
||||||
|
# Проверка, что это не мы сами
|
||||||
|
if peer_id == self.node.node_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Проверка, что пир не в черном списке
|
||||||
|
if peer_id in self.node.blacklisted_peers:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Попытка подключения
|
||||||
|
try:
|
||||||
|
connection = await self.establish_peer_connection(peer_info)
|
||||||
|
if connection:
|
||||||
|
self.discovered_peers[peer_id] = {
|
||||||
|
"info": peer_info,
|
||||||
|
"connection": connection,
|
||||||
|
"discovered_at": datetime.utcnow(),
|
||||||
|
"status": "connected"
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(f"Successfully connected to peer: {peer_id}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to connect to peer {peer_id}: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Peer Connection Management
|
||||||
|
|
||||||
|
```python
|
||||||
|
class PeerConnectionManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.connections = {}
|
||||||
|
self.connection_limits = {
|
||||||
|
"max_outbound": 50,
|
||||||
|
"max_inbound": 100,
|
||||||
|
"max_per_ip": 3
|
||||||
|
}
|
||||||
|
|
||||||
|
async def establish_peer_connection(self, peer_info: dict) -> Optional[PeerConnection]:
|
||||||
|
"""Установка соединения с пиром"""
|
||||||
|
|
||||||
|
peer_id = peer_info["node_id"]
|
||||||
|
peer_address = peer_info["address"]
|
||||||
|
|
||||||
|
# Проверка лимитов соединений
|
||||||
|
if not await self.check_connection_limits(peer_info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Создание TCP соединения
|
||||||
|
connection = await self.create_tcp_connection(peer_address)
|
||||||
|
|
||||||
|
# MY Network handshake
|
||||||
|
handshake_success = await self.perform_handshake(connection, peer_info)
|
||||||
|
if not handshake_success:
|
||||||
|
await connection.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Создание MY Network peer connection
|
||||||
|
peer_connection = PeerConnection(
|
||||||
|
peer_id=peer_id,
|
||||||
|
connection=connection,
|
||||||
|
peer_info=peer_info
|
||||||
|
)
|
||||||
|
|
||||||
|
# Регистрация соединения
|
||||||
|
self.connections[peer_id] = peer_connection
|
||||||
|
|
||||||
|
# Запуск обработчика сообщений
|
||||||
|
asyncio.create_task(self.handle_peer_messages(peer_connection))
|
||||||
|
|
||||||
|
return peer_connection
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to establish connection to {peer_id}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def perform_handshake(self, connection: Connection, peer_info: dict) -> bool:
|
||||||
|
"""Выполнение MY Network handshake"""
|
||||||
|
|
||||||
|
# Отправка handshake сообщения
|
||||||
|
handshake_msg = {
|
||||||
|
"type": "handshake",
|
||||||
|
"node_id": self.node.node_id,
|
||||||
|
"public_key": self.node.public_key_hex,
|
||||||
|
"network_version": "1.0.0",
|
||||||
|
"supported_features": ["content_sync", "consensus", "dht"],
|
||||||
|
"timestamp": datetime.utcnow().isoformat()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Подписание сообщения
|
||||||
|
handshake_msg["signature"] = await self.node.sign_message(handshake_msg)
|
||||||
|
|
||||||
|
# Отправка handshake
|
||||||
|
await connection.send_message(handshake_msg)
|
||||||
|
|
||||||
|
# Ожидание ответа
|
||||||
|
response = await connection.receive_message(timeout=10)
|
||||||
|
|
||||||
|
# Проверка ответа
|
||||||
|
if response.get("type") != "handshake_response":
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Проверка подписи пира
|
||||||
|
peer_signature = response.get("signature")
|
||||||
|
if not await self.verify_peer_signature(peer_info, response, peer_signature):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
```
|
||||||
|
|
||||||
|
## Протокол Синхронизации Контента
|
||||||
|
|
||||||
|
### 1. Content Sync Protocol
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ContentSyncProtocol:
|
||||||
|
def __init__(self, node: MYNetworkNode):
|
||||||
|
self.node = node
|
||||||
|
self.sync_queue = asyncio.Queue()
|
||||||
|
self.sync_stats = {
|
||||||
|
"synced_content": 0,
|
||||||
|
"failed_syncs": 0,
|
||||||
|
"bytes_synced": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
async def start_initial_sync(self):
|
||||||
|
"""Начальная синхронизация контента"""
|
||||||
|
|
||||||
|
logger.info("Starting initial content synchronization")
|
||||||
|
|
||||||
|
# Получение списка доступного контента от пиров
|
||||||
|
available_content = await self.discover_available_content()
|
||||||
|
|
||||||
|
# Определение контента для синхронизации
|
||||||
|
content_to_sync = await self.select_content_for_sync(available_content)
|
||||||
|
|
||||||
|
# Добавление в очередь синхронизации
|
||||||
|
for content_hash in content_to_sync:
|
||||||
|
await self.sync_queue.put(content_hash)
|
||||||
|
|
||||||
|
# Запуск worker'ов синхронизации
|
||||||
|
workers = []
|
||||||
|
for i in range(3): # 3 параллельных worker'а
|
||||||
|
worker = asyncio.create_task(self.sync_worker(f"worker-{i}"))
|
||||||
|
workers.append(worker)
|
||||||
|
|
||||||
|
# Ожидание завершения начальной синхронизации
|
||||||
|
await self.sync_queue.join()
|
||||||
|
|
||||||
|
# Остановка worker'ов
|
||||||
|
for worker in workers:
|
||||||
|
worker.cancel()
|
||||||
|
|
||||||
|
logger.info(f"Initial sync completed. Synced {self.sync_stats['synced_content']} items")
|
||||||
|
|
||||||
|
async def sync_worker(self, worker_id: str):
|
||||||
|
"""Worker для синхронизации контента"""
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Получение контента для синхронизации
|
||||||
|
content_hash = await self.sync_queue.get()
|
||||||
|
|
||||||
|
# Синхронизация контента
|
||||||
|
success = await self.sync_single_content(content_hash)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
self.sync_stats["synced_content"] += 1
|
||||||
|
else:
|
||||||
|
self.sync_stats["failed_syncs"] += 1
|
||||||
|
|
||||||
|
# Отметка о завершении задачи
|
||||||
|
self.sync_queue.task_done()
|
||||||
|
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Sync worker {worker_id} error: {e}")
|
||||||
|
self.sync_queue.task_done()
|
||||||
|
|
||||||
|
async def sync_single_content(self, content_hash: str) -> bool:
|
||||||
|
"""Синхронизация одного элемента контента"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Проверка, есть ли уже этот контент локально
|
||||||
|
local_content = await StoredContent.get_by_hash(self.node.db_session, content_hash)
|
||||||
|
if local_content:
|
||||||
|
return True # Уже есть
|
||||||
|
|
||||||
|
# Поиск пиров с этим контентом
|
||||||
|
peers_with_content = await self.find_peers_with_content(content_hash)
|
||||||
|
if not peers_with_content:
|
||||||
|
logger.warning(f"No peers found with content: {content_hash}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Выбор оптимального пира для загрузки
|
||||||
|
selected_peer = await self.select_optimal_peer(peers_with_content)
|
||||||
|
|
||||||
|
# Загрузка метаданных контента
|
||||||
|
content_metadata = await self.download_content_metadata(selected_peer, content_hash)
|
||||||
|
if not content_metadata:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Загрузка данных контента
|
||||||
|
content_data = await self.download_content_data(selected_peer, content_hash)
|
||||||
|
if not content_data:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Проверка целостности
|
||||||
|
if not await self.verify_content_integrity(content_hash, content_data):
|
||||||
|
logger.error(f"Content integrity check failed: {content_hash}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Сохранение контента локально
|
||||||
|
await self.store_content_locally(content_metadata, content_data)
|
||||||
|
|
||||||
|
# Обновление статистики
|
||||||
|
self.sync_stats["bytes_synced"] += len(content_data)
|
||||||
|
|
||||||
|
logger.info(f"Successfully synced content: {content_hash}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to sync content {content_hash}: {e}")
|
||||||
|
return False
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Differential Sync Algorithm
|
||||||
|
|
||||||
|
```python
|
||||||
|
class DifferentialSync:
|
||||||
|
async def perform_differential_sync(self, peer_id: str):
|
||||||
|
"""Дифференциальная синхронизация с пиром"""
|
||||||
|
|
||||||
|
# Получение локального state
|
||||||
|
local_state = await self.get_local_content_state()
|
||||||
|
|
||||||
|
# Запрос state от пира
|
||||||
|
peer_state = await self.request_peer_content_state(peer_id)
|
||||||
|
|
||||||
|
# Вычисление различий
|
||||||
|
diff = await self.calculate_state_diff(local_state, peer_state)
|
||||||
|
|
||||||
|
# Синхронизация различий
|
||||||
|
if diff["missing_locally"]:
|
||||||
|
await self.sync_missing_content(peer_id, diff["missing_locally"])
|
||||||
|
|
||||||
|
if diff["missing_on_peer"]:
|
||||||
|
await self.send_missing_content(peer_id, diff["missing_on_peer"])
|
||||||
|
|
||||||
|
# Разрешение конфликтов
|
||||||
|
if diff["conflicts"]:
|
||||||
|
await self.resolve_content_conflicts(peer_id, diff["conflicts"])
|
||||||
|
|
||||||
|
async def calculate_state_diff(self, local_state: dict, peer_state: dict) -> dict:
|
||||||
|
"""Вычисление различий между состояниями"""
|
||||||
|
|
||||||
|
local_hashes = set(local_state.keys())
|
||||||
|
peer_hashes = set(peer_state.keys())
|
||||||
|
|
||||||
|
missing_locally = peer_hashes - local_hashes
|
||||||
|
missing_on_peer = local_hashes - peer_hashes
|
||||||
|
common_content = local_hashes & peer_hashes
|
||||||
|
|
||||||
|
# Проверка конфликтов в общем контенте
|
||||||
|
conflicts = []
|
||||||
|
for content_hash in common_content:
|
||||||
|
local_meta = local_state[content_hash]
|
||||||
|
peer_meta = peer_state[content_hash]
|
||||||
|
|
||||||
|
if local_meta["version"] != peer_meta["version"]:
|
||||||
|
conflicts.append({
|
||||||
|
"content_hash": content_hash,
|
||||||
|
"local_version": local_meta["version"],
|
||||||
|
"peer_version": peer_meta["version"]
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"missing_locally": list(missing_locally),
|
||||||
|
"missing_on_peer": list(missing_on_peer),
|
||||||
|
"conflicts": conflicts
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Обработка Всех Состояний Контента
|
||||||
|
|
||||||
|
### 1. Multi-State Content Handler
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MultiStateContentHandler:
|
||||||
|
def __init__(self, node: MYNetworkNode):
|
||||||
|
self.node = node
|
||||||
|
self.state_processors = {
|
||||||
|
"encrypted": EncryptedContentProcessor(),
|
||||||
|
"decrypted": DecryptedContentProcessor(),
|
||||||
|
"preview": PreviewContentProcessor()
|
||||||
|
}
|
||||||
|
|
||||||
|
async def process_content_group(self, content_group_id: str):
|
||||||
|
"""Обработка группы связанных состояний контента"""
|
||||||
|
|
||||||
|
# Обнаружение всех состояний в группе
|
||||||
|
content_states = await self.discover_content_states(content_group_id)
|
||||||
|
|
||||||
|
# Обработка каждого состояния
|
||||||
|
for state in content_states:
|
||||||
|
processor = self.state_processors.get(state.type)
|
||||||
|
if processor:
|
||||||
|
await processor.process_state(state)
|
||||||
|
|
||||||
|
# Проверка целостности связей между состояниями
|
||||||
|
await self.verify_state_relationships(content_states)
|
||||||
|
|
||||||
|
# Репликация всех состояний
|
||||||
|
await self.replicate_content_group(content_states)
|
||||||
|
|
||||||
|
async def discover_content_states(self, content_group_id: str) -> List[ContentState]:
|
||||||
|
"""Обнаружение всех состояний контента в группе"""
|
||||||
|
|
||||||
|
# Поиск корневого контента
|
||||||
|
root_content = await StoredContent.get_by_id(
|
||||||
|
self.node.db_session, content_group_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if not root_content:
|
||||||
|
return []
|
||||||
|
|
||||||
|
states = [ContentState(
|
||||||
|
content=root_content,
|
||||||
|
type=self.determine_content_state_type(root_content)
|
||||||
|
)]
|
||||||
|
|
||||||
|
# Поиск связанных состояний через relationships
|
||||||
|
relationships = await self.get_content_relationships(content_group_id)
|
||||||
|
|
||||||
|
for rel in relationships:
|
||||||
|
related_content = await StoredContent.get_by_id(
|
||||||
|
self.node.db_session, rel.child_content_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if related_content:
|
||||||
|
states.append(ContentState(
|
||||||
|
content=related_content,
|
||||||
|
type=rel.relationship_type,
|
||||||
|
parent_id=content_group_id
|
||||||
|
))
|
||||||
|
|
||||||
|
return states
|
||||||
|
|
||||||
|
def determine_content_state_type(self, content: StoredContent) -> str:
|
||||||
|
"""Определение типа состояния контента"""
|
||||||
|
|
||||||
|
if content.encrypted:
|
||||||
|
return "encrypted"
|
||||||
|
elif "preview" in content.tags:
|
||||||
|
return "preview"
|
||||||
|
else:
|
||||||
|
return "decrypted"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. State-Specific Processors
|
||||||
|
|
||||||
|
```python
|
||||||
|
class EncryptedContentProcessor:
|
||||||
|
async def process_state(self, state: ContentState):
|
||||||
|
"""Обработка зашифрованного состояния"""
|
||||||
|
|
||||||
|
content = state.content
|
||||||
|
|
||||||
|
# Проверка наличия ключа шифрования
|
||||||
|
if not content.encryption_key_id:
|
||||||
|
logger.warning(f"Encrypted content without key: {content.id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Проверка доступности ключа
|
||||||
|
encryption_key = await EncryptionKey.get_by_id(
|
||||||
|
self.node.db_session, content.encryption_key_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if not encryption_key or not encryption_key.is_valid:
|
||||||
|
logger.warning(f"Invalid encryption key for content: {content.id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Обработка зашифрованного контента
|
||||||
|
await self.process_encrypted_content(content, encryption_key)
|
||||||
|
|
||||||
|
class DecryptedContentProcessor:
|
||||||
|
async def process_state(self, state: ContentState):
|
||||||
|
"""Обработка расшифрованного состояния"""
|
||||||
|
|
||||||
|
content = state.content
|
||||||
|
|
||||||
|
# Проверка связи с зашифрованной версией
|
||||||
|
if state.parent_id:
|
||||||
|
encrypted_content = await StoredContent.get_by_id(
|
||||||
|
self.node.db_session, state.parent_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if encrypted_content and encrypted_content.encrypted:
|
||||||
|
# Проверка соответствия с зашифрованной версией
|
||||||
|
await self.verify_encrypted_decrypted_relationship(
|
||||||
|
encrypted_content, content
|
||||||
|
)
|
||||||
|
|
||||||
|
# Обработка расшифрованного контента
|
||||||
|
await self.process_decrypted_content(content)
|
||||||
|
|
||||||
|
class PreviewContentProcessor:
|
||||||
|
async def process_state(self, state: ContentState):
|
||||||
|
"""Обработка preview состояния"""
|
||||||
|
|
||||||
|
content = state.content
|
||||||
|
|
||||||
|
# Проверка, что это действительно preview
|
||||||
|
if "preview" not in content.tags:
|
||||||
|
content.add_tag("preview")
|
||||||
|
|
||||||
|
# Проверка размера (preview должен быть меньше оригинала)
|
||||||
|
if state.parent_id:
|
||||||
|
original_content = await StoredContent.get_by_id(
|
||||||
|
self.node.db_session, state.parent_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if original_content and content.file_size >= original_content.file_size:
|
||||||
|
logger.warning(f"Preview size is not smaller than original: {content.id}")
|
||||||
|
|
||||||
|
# Обработка preview контента
|
||||||
|
await self.process_preview_content(content)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Node Status Monitoring
|
||||||
|
|
||||||
|
### 1. Real-time Status Monitoring
|
||||||
|
|
||||||
|
```python
|
||||||
|
class NodeStatusMonitor:
|
||||||
|
def __init__(self, node: MYNetworkNode):
|
||||||
|
self.node = node
|
||||||
|
self.status_data = {}
|
||||||
|
self.monitoring_interval = 30 # секунды
|
||||||
|
|
||||||
|
async def start_monitoring(self):
|
||||||
|
"""Запуск мониторинга статуса ноды"""
|
||||||
|
|
||||||
|
# Запуск периодического сбора метрик
|
||||||
|
asyncio.create_task(self.collect_metrics_loop())
|
||||||
|
|
||||||
|
# Запуск health check'ов
|
||||||
|
asyncio.create_task(self.health_check_loop())
|
||||||
|
|
||||||
|
# Запуск отправки статуса в сеть
|
||||||
|
asyncio.create_task(self.broadcast_status_loop())
|
||||||
|
|
||||||
|
async def collect_current_status(self) -> dict:
|
||||||
|
"""Сбор текущего статуса ноды"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"node_id": self.node.node_id,
|
||||||
|
"uptime": self.get_uptime_seconds(),
|
||||||
|
"peer_count": len(self.node.peer_connections),
|
||||||
|
"content_count": await self.get_local_content_count(),
|
||||||
|
"storage_usage": await self.get_storage_usage(),
|
||||||
|
"network_stats": await self.get_network_stats(),
|
||||||
|
"sync_status": await self.get_sync_status(),
|
||||||
|
"resource_usage": await self.get_resource_usage(),
|
||||||
|
"timestamp": datetime.utcnow().isoformat()
|
||||||
|
}
|
||||||
|
|
||||||
|
async def get_sync_status(self) -> dict:
|
||||||
|
"""Получение статуса синхронизации"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"is_syncing": self.node.sync_manager.is_syncing,
|
||||||
|
"sync_progress": self.node.sync_manager.get_progress(),
|
||||||
|
"last_sync": self.node.sync_manager.last_sync_time,
|
||||||
|
"pending_sync_items": self.node.sync_manager.get_pending_count(),
|
||||||
|
"sync_errors": self.node.sync_manager.get_error_count()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Node Performance Metrics
|
||||||
|
|
||||||
|
```python
|
||||||
|
class NodePerformanceMetrics:
|
||||||
|
def __init__(self):
|
||||||
|
self.metrics_history = []
|
||||||
|
self.max_history_size = 1000
|
||||||
|
|
||||||
|
async def collect_performance_metrics(self) -> dict:
|
||||||
|
"""Сбор метрик производительности"""
|
||||||
|
|
||||||
|
metrics = {
|
||||||
|
"cpu_usage": psutil.cpu_percent(),
|
||||||
|
"memory_usage": psutil.virtual_memory().percent,
|
||||||
|
"disk_usage": psutil.disk_usage('/').percent,
|
||||||
|
"network_io": await self.get_network_io_stats(),
|
||||||
|
"content_operations": await self.get_content_operations_stats(),
|
||||||
|
"p2p_performance": await self.get_p2p_performance_stats(),
|
||||||
|
"consensus_performance": await self.get_consensus_performance_stats()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Сохранение в историю
|
||||||
|
self.metrics_history.append({
|
||||||
|
"timestamp": datetime.utcnow(),
|
||||||
|
"metrics": metrics
|
||||||
|
})
|
||||||
|
|
||||||
|
# Ограничение размера истории
|
||||||
|
if len(self.metrics_history) > self.max_history_size:
|
||||||
|
self.metrics_history.pop(0)
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
async def get_p2p_performance_stats(self) -> dict:
|
||||||
|
"""Статистика производительности P2P"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"avg_latency": await self.calculate_avg_peer_latency(),
|
||||||
|
"message_throughput": await self.get_message_throughput(),
|
||||||
|
"connection_success_rate": await self.get_connection_success_rate(),
|
||||||
|
"bandwidth_usage": await self.get_bandwidth_usage()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Management
|
||||||
|
|
||||||
|
### 1. Dynamic Configuration
|
||||||
|
|
||||||
|
```python
|
||||||
|
class NodeConfigManager:
|
||||||
|
def __init__(self, node: MYNetworkNode):
|
||||||
|
self.node = node
|
||||||
|
self.config_file = "node_config.json"
|
||||||
|
self.config_watchers = []
|
||||||
|
|
||||||
|
async def load_configuration(self) -> dict:
|
||||||
|
"""Загрузка конфигурации ноды"""
|
||||||
|
|
||||||
|
# Загрузка базовой конфигурации
|
||||||
|
base_config = await self.load_base_config()
|
||||||
|
|
||||||
|
# Загрузка bootstrap конфигурации
|
||||||
|
bootstrap_config = await self.load_bootstrap_config()
|
||||||
|
|
||||||
|
# Загрузка локальных настроек
|
||||||
|
local_config = await self.load_local_config()
|
||||||
|
|
||||||
|
# Объединение конфигураций
|
||||||
|
merged_config = {
|
||||||
|
**base_config,
|
||||||
|
**bootstrap_config,
|
||||||
|
**local_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Валидация конфигурации
|
||||||
|
await self.validate_configuration(merged_config)
|
||||||
|
|
||||||
|
return merged_config
|
||||||
|
|
||||||
|
async def update_configuration(self, new_config: dict):
|
||||||
|
"""Обновление конфигурации на лету"""
|
||||||
|
|
||||||
|
# Валидация новой конфигурации
|
||||||
|
await self.validate_configuration(new_config)
|
||||||
|
|
||||||
|
# Создание backup старой конфигурации
|
||||||
|
old_config = self.node.config.copy()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Применение новой конфигурации
|
||||||
|
self.node.config.update(new_config)
|
||||||
|
|
||||||
|
# Уведомление watchers об изменениях
|
||||||
|
for watcher in self.config_watchers:
|
||||||
|
await watcher.on_config_changed(old_config, new_config)
|
||||||
|
|
||||||
|
# Сохранение конфигурации
|
||||||
|
await self.save_configuration(new_config)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# Откат к старой конфигурации в случае ошибки
|
||||||
|
self.node.config = old_config
|
||||||
|
raise ConfigurationError(f"Failed to update configuration: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
Эта спецификация определяет полный жизненный цикл MY Network ноды от инициализации до мониторинга производительности, обеспечивая надежную работу в децентрализованной сети.
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
# MY Network Protocol Specification
|
||||||
|
|
||||||
|
## Обзор
|
||||||
|
|
||||||
|
MY Network представляет собой децентрализованный overlay протокол для распределенной репликации и синхронизации контента поверх существующей системы my-uploader-bot. Протокол сохраняет все существующие состояния и функциональность, добавляя P2P синхронизацию с кворумным консенсусом.
|
||||||
|
|
||||||
|
## Принципы Overlay Protocol
|
||||||
|
|
||||||
|
### 1. Совместимость с Существующей Системой
|
||||||
|
- **Полное сохранение** всех состояний [`StoredContent`](app/core/models/content.py:61)
|
||||||
|
- **Неизменность** существующих API endpoints
|
||||||
|
- **Прозрачная интеграция** без нарушения работы текущих клиентов
|
||||||
|
- **Обратная совместимость** со всеми версиями API
|
||||||
|
|
||||||
|
### 2. Состояния Контента в MY Network
|
||||||
|
|
||||||
|
#### Поддерживаемые Состояния
|
||||||
|
```
|
||||||
|
encrypted: Boolean - Статус шифрования контента
|
||||||
|
decrypted: Virtual - Расшифрованная версия (через decrypted_content_id)
|
||||||
|
preview: Virtual - Превью-версия для публичного доступа
|
||||||
|
```
|
||||||
|
|
||||||
|
MY Network реплицирует **все состояния** контента:
|
||||||
|
- **Encrypted Content** - зашифрованные данные с [`encryption_key_id`](app/core/models/content.py:157)
|
||||||
|
- **Decrypted Content** - расшифрованные версии через связи
|
||||||
|
- **Preview Content** - публичные превью для демонстрации
|
||||||
|
- **Metadata** - все метаданные включая теги, описание, медиа-информацию
|
||||||
|
|
||||||
|
#### Связи Между Состояниями
|
||||||
|
```sql
|
||||||
|
-- Существующая структура StoredContent поддерживает связи
|
||||||
|
SELECT * FROM stored_content sc1
|
||||||
|
LEFT JOIN stored_content sc2 ON sc1.decrypted_content_id = sc2.id;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. P2P Синхронизация Architecture
|
||||||
|
|
||||||
|
#### Кворумный Консенсус
|
||||||
|
```
|
||||||
|
Минимальный кворум: 3 ноды
|
||||||
|
Консенсус требует: 2/3 + 1 подтверждений
|
||||||
|
Timeout для консенсуса: 30 секунд
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Алгоритм Репликации
|
||||||
|
1. **Content Discovery** - обнаружение нового контента
|
||||||
|
2. **Integrity Check** - проверка целостности через хеш
|
||||||
|
3. **Quorum Voting** - голосование за принятие контента
|
||||||
|
4. **Replication** - репликация на кворум нод
|
||||||
|
5. **Confirmation** - подтверждение успешной репликации
|
||||||
|
|
||||||
|
### 4. Bootstrap Configuration
|
||||||
|
|
||||||
|
#### Структура bootstrap.json
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"network_id": "my-network-mainnet",
|
||||||
|
"bootstrap_nodes": [
|
||||||
|
{
|
||||||
|
"id": "node-001",
|
||||||
|
"address": "my://192.168.1.100:8080",
|
||||||
|
"public_key": "ed25519:AAAA...",
|
||||||
|
"region": "eu-west-1",
|
||||||
|
"weight": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"consensus": {
|
||||||
|
"min_quorum": 3,
|
||||||
|
"consensus_threshold": 0.67,
|
||||||
|
"timeout_seconds": 30,
|
||||||
|
"retry_attempts": 3
|
||||||
|
},
|
||||||
|
"sync_settings": {
|
||||||
|
"sync_interval": 60,
|
||||||
|
"max_batch_size": 100,
|
||||||
|
"compression": "gzip",
|
||||||
|
"encryption": "aes-256-gcm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints для MY Network
|
||||||
|
|
||||||
|
### Core MY Protocol Endpoints
|
||||||
|
|
||||||
|
#### Node Management
|
||||||
|
```
|
||||||
|
GET /api/my/node/status - Статус текущей ноды
|
||||||
|
GET /api/my/node/peers - Список подключенных пиров
|
||||||
|
POST /api/my/node/connect - Подключение к новому пиру
|
||||||
|
POST /api/my/node/disconnect - Отключение от пира
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Content Synchronization
|
||||||
|
```
|
||||||
|
GET /api/my/sync/status - Статус синхронизации
|
||||||
|
POST /api/my/sync/request - Запрос синхронизации контента
|
||||||
|
GET /api/my/sync/conflicts - Список конфликтов синхронизации
|
||||||
|
POST /api/my/sync/resolve - Разрешение конфликтов
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Quorum & Consensus
|
||||||
|
```
|
||||||
|
GET /api/my/quorum/status - Статус кворума
|
||||||
|
POST /api/my/quorum/vote - Голосование за контент
|
||||||
|
GET /api/my/quorum/results - Результаты голосования
|
||||||
|
POST /api/my/consensus/propose - Предложение изменений
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Content Distribution
|
||||||
|
```
|
||||||
|
GET /api/my/content/{hash} - Получение контента через MY Network
|
||||||
|
GET /api/my/content/{hash}/peers - Список пиров с контентом
|
||||||
|
POST /api/my/content/announce - Анонс нового контента
|
||||||
|
GET /api/my/content/search - Поиск контента в сети
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration API Endpoints
|
||||||
|
|
||||||
|
#### Health Check & Discovery
|
||||||
|
```
|
||||||
|
GET /api/my/health - Проверка здоровья MY ноды
|
||||||
|
GET /api/my/discovery/nodes - Обнаружение новых нод
|
||||||
|
POST /api/my/discovery/announce - Анонс собственной ноды
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Metrics & Analytics
|
||||||
|
```
|
||||||
|
GET /api/my/metrics/network - Метрики сети
|
||||||
|
GET /api/my/metrics/content - Метрики контента
|
||||||
|
GET /api/my/metrics/performance - Метрики производительности
|
||||||
|
```
|
||||||
|
|
||||||
|
## Protocol Messages
|
||||||
|
|
||||||
|
### MY Network Message Types
|
||||||
|
|
||||||
|
#### Node Communication
|
||||||
|
```protobuf
|
||||||
|
message NodeHandshake {
|
||||||
|
string node_id = 1;
|
||||||
|
string public_key = 2;
|
||||||
|
string network_version = 3;
|
||||||
|
repeated string supported_features = 4;
|
||||||
|
int64 timestamp = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PeerInfo {
|
||||||
|
string node_id = 1;
|
||||||
|
string address = 2;
|
||||||
|
int32 connection_count = 3;
|
||||||
|
int64 last_seen = 4;
|
||||||
|
float reputation_score = 5;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Content Sync Messages
|
||||||
|
```protobuf
|
||||||
|
message ContentAnnouncement {
|
||||||
|
string content_hash = 1;
|
||||||
|
int64 file_size = 2;
|
||||||
|
string content_type = 3;
|
||||||
|
bool encrypted = 4;
|
||||||
|
string encryption_key_id = 5;
|
||||||
|
repeated string tags = 6;
|
||||||
|
int64 timestamp = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SyncRequest {
|
||||||
|
repeated string content_hashes = 1;
|
||||||
|
string requesting_node = 2;
|
||||||
|
int32 priority = 3;
|
||||||
|
int64 timestamp = 4;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Consensus Messages
|
||||||
|
```protobuf
|
||||||
|
message QuorumVote {
|
||||||
|
string content_hash = 1;
|
||||||
|
string voter_node_id = 2;
|
||||||
|
bool vote = 3; // true = accept, false = reject
|
||||||
|
string signature = 4;
|
||||||
|
int64 timestamp = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsensusResult {
|
||||||
|
string content_hash = 1;
|
||||||
|
int32 votes_for = 2;
|
||||||
|
int32 votes_against = 3;
|
||||||
|
bool consensus_reached = 4;
|
||||||
|
repeated string participating_nodes = 5;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Model
|
||||||
|
|
||||||
|
### Cryptographic Security
|
||||||
|
- **Node Identity**: Ed25519 ключи для идентификации нод
|
||||||
|
- **Message Signing**: Все сообщения подписываются отправителем
|
||||||
|
- **Content Integrity**: SHA-256 хеши для проверки целостности
|
||||||
|
- **Transport Security**: TLS 1.3 для всех сетевых соединений
|
||||||
|
|
||||||
|
### Access Control
|
||||||
|
- **Content Access**: Сохранение существующих прав доступа
|
||||||
|
- **Network Participation**: Whitelist/blacklist механизмы
|
||||||
|
- **Rate Limiting**: Защита от спама и DoS атак
|
||||||
|
- **Reputation System**: Система репутации для узлов
|
||||||
|
|
||||||
|
## MY Network Service Layer
|
||||||
|
|
||||||
|
### Service Architecture
|
||||||
|
```
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ Existing API │ <- Без изменений
|
||||||
|
├─────────────────────┤
|
||||||
|
│ MY Network Layer │ <- Новый overlay слой
|
||||||
|
├─────────────────────┤
|
||||||
|
│ StoredContent │ <- Существующая модель
|
||||||
|
└─────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Components
|
||||||
|
- **MY Node Manager** - управление статусом ноды
|
||||||
|
- **P2P Communication** - межузловое взаимодействие
|
||||||
|
- **Content Replicator** - репликация контента
|
||||||
|
- **Consensus Engine** - механизм консенсуса
|
||||||
|
- **Sync Coordinator** - координация синхронизации
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Scalability Targets
|
||||||
|
- **Network Size**: До 1000 активных нод
|
||||||
|
- **Content Volume**: До 10TB на ноду
|
||||||
|
- **Sync Throughput**: 100 MB/s между нодами
|
||||||
|
- **Consensus Latency**: < 5 секунд для кворума
|
||||||
|
|
||||||
|
### Optimization Strategies
|
||||||
|
- **Content Chunking** - разбиение больших файлов
|
||||||
|
- **Delta Sync** - синхронизация только изменений
|
||||||
|
- **Compression** - сжатие передаваемых данных
|
||||||
|
- **Caching** - кеширование популярного контента
|
||||||
|
- **Load Balancing** - балансировка нагрузки между нодами
|
||||||
|
|
||||||
|
## Future Roadmap
|
||||||
|
|
||||||
|
### Phase 1: Core Protocol (Q1 2025)
|
||||||
|
- [x] Protocol specification
|
||||||
|
- [ ] Basic P2P communication
|
||||||
|
- [ ] Simple consensus mechanism
|
||||||
|
- [ ] Bootstrap node implementation
|
||||||
|
|
||||||
|
### Phase 2: Advanced Features (Q2 2025)
|
||||||
|
- [ ] Content deduplication
|
||||||
|
- [ ] Advanced routing algorithms
|
||||||
|
- [ ] Performance optimizations
|
||||||
|
- [ ] Monitoring and analytics
|
||||||
|
|
||||||
|
### Phase 3: Enterprise Features (Q3 2025)
|
||||||
|
- [ ] Multi-region replication
|
||||||
|
- [ ] Enterprise security features
|
||||||
|
- [ ] SLA guarantees
|
||||||
|
- [ ] Professional support tools
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
# 🚀 MY Network - Быстрый старт
|
||||||
|
|
||||||
|
## ⚡ Установка в две команды
|
||||||
|
|
||||||
|
### 📋 Требования
|
||||||
|
- **Сервер:** Ubuntu 20.04+ / Debian 11+
|
||||||
|
- **Права:** Root доступ
|
||||||
|
- **Домен:** Настроенный A-запись
|
||||||
|
- **Email:** Для SSL сертификата
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🥇 Команда 1: Установка сервиса
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -O https://raw.githubusercontent.com/your-repo/my-uploader-bot/main/install_service.sh
|
||||||
|
sudo bash install_service.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Что происходит:**
|
||||||
|
- ✅ Обновление системы
|
||||||
|
- ✅ Установка Docker, Python, зависимостей
|
||||||
|
- ✅ Настройка MY Network сервиса
|
||||||
|
- ✅ Запуск на порту 15100
|
||||||
|
- ✅ Создание systemd сервиса
|
||||||
|
|
||||||
|
**Результат:** Базовый сервис работает на `http://your-server:15100`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🥈 Команда 2: Защита и SSL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash secure_service.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Что происходит:**
|
||||||
|
- 🔒 SSL сертификат (Let's Encrypt)
|
||||||
|
- 🌐 Настройка Nginx с proxy
|
||||||
|
- 🔥 Настройка UFW firewall
|
||||||
|
- 🚫 Установка Fail2ban
|
||||||
|
- 📊 Система мониторинга
|
||||||
|
|
||||||
|
**Результат:** Защищенный сервис на `https://your-domain.com`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Проверка работы
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверка API
|
||||||
|
curl https://your-domain.com/api/my/health
|
||||||
|
|
||||||
|
# Веб-мониторинг
|
||||||
|
https://your-domain.com/api/my/monitor/
|
||||||
|
|
||||||
|
# Статус сервисов
|
||||||
|
systemctl status my-network nginx fail2ban
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Полная документация
|
||||||
|
|
||||||
|
- **[DOCS_RU.md](DOCS_RU.md)** - Полная документация с архитектурой
|
||||||
|
- **[MY_NETWORK_README.md](MY_NETWORK_README.md)** - Техническое описание
|
||||||
|
- **[bootstrap.json](bootstrap.json)** - Конфигурация сети
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Поддержка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Логи
|
||||||
|
journalctl -u my-network -f
|
||||||
|
|
||||||
|
# Конфигурация
|
||||||
|
cat /opt/my-network-config.txt
|
||||||
|
|
||||||
|
# Перезапуск
|
||||||
|
systemctl restart my-network nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
**Готово!** 🎉 Ваша MY Network работает и защищена!
|
||||||
|
|
@ -0,0 +1,504 @@
|
||||||
|
# My Uploader Bot - Comprehensive File Upload & Blockchain Integration System
|
||||||
|
|
||||||
|
A modern, scalable file upload and management system with blockchain integration, built with async Python and enterprise-grade security.
|
||||||
|
|
||||||
|
## 🚀 Features
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
- **Chunked File Upload**: Support for large files with resume capability
|
||||||
|
- **Multi-Storage Backend**: Local, S3-compatible storage with automatic failover
|
||||||
|
- **File Processing**: Automatic image optimization, thumbnail generation, media conversion
|
||||||
|
- **Content Management**: Version control, metadata management, search functionality
|
||||||
|
- **User Management**: JWT authentication, API keys, session management
|
||||||
|
|
||||||
|
### Blockchain Integration
|
||||||
|
- **TON Blockchain**: Wallet creation, transaction management, balance tracking
|
||||||
|
- **Smart Contracts**: Interaction with TON smart contracts
|
||||||
|
- **NFT Support**: NFT collection indexing and management
|
||||||
|
- **DeFi Integration**: Staking positions, token balances, yield farming
|
||||||
|
|
||||||
|
### Enterprise Features
|
||||||
|
- **Security**: Rate limiting, CORS, CSP, input validation, file encryption
|
||||||
|
- **Monitoring**: Prometheus metrics, Grafana dashboards, health checks
|
||||||
|
- **Caching**: Redis integration with intelligent cache management
|
||||||
|
- **Background Services**: Async task processing, blockchain indexing
|
||||||
|
- **API Documentation**: OpenAPI/Swagger with interactive interface
|
||||||
|
|
||||||
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
### Technology Stack
|
||||||
|
- **Backend**: Python 3.11+, Sanic (async web framework)
|
||||||
|
- **Database**: PostgreSQL 15+ with async SQLAlchemy 2.0
|
||||||
|
- **Cache**: Redis 7+ with connection pooling
|
||||||
|
- **Blockchain**: TON SDK for blockchain operations
|
||||||
|
- **Storage**: Local filesystem with S3-compatible support
|
||||||
|
- **Monitoring**: Prometheus, Grafana, structured logging
|
||||||
|
- **Deployment**: Docker Compose with multi-stage builds
|
||||||
|
|
||||||
|
### System Architecture
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ Load Balancer │ │ Grafana │ │ Prometheus │
|
||||||
|
│ (Nginx) │ │ (Monitoring) │ │ (Metrics) │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
│ │ │
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ Sanic App │◄──►│ Redis │ │ PostgreSQL │
|
||||||
|
│ (API Server) │ │ (Cache) │ │ (Database) │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
│ │ │
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ Background │ │ File Storage │ │ TON Blockchain │
|
||||||
|
│ Services │ │ (Local/S3/CDN) │ │ Integration │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Installation & Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- Python 3.11+
|
||||||
|
- PostgreSQL 15+
|
||||||
|
- Redis 7+
|
||||||
|
- Docker & Docker Compose (recommended)
|
||||||
|
|
||||||
|
### Quick Start with Docker
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/your-org/my-uploader-bot.git
|
||||||
|
cd my-uploader-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create environment file**:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit .env with your configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start services**:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.new.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Initialize database**:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.new.yml exec app alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Create admin user**:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.new.yml exec app python -m app.scripts.create_admin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
1. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
# Using Poetry (recommended)
|
||||||
|
poetry install
|
||||||
|
|
||||||
|
# Or using pip
|
||||||
|
pip install -r requirements_new.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Set up database**:
|
||||||
|
```bash
|
||||||
|
# Create database
|
||||||
|
createdb myuploader
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Configure Redis**:
|
||||||
|
```bash
|
||||||
|
# Start Redis with custom config
|
||||||
|
redis-server config/redis.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Start application**:
|
||||||
|
```bash
|
||||||
|
# Development mode
|
||||||
|
python -m app
|
||||||
|
|
||||||
|
# Production mode
|
||||||
|
gunicorn app:create_app --bind 0.0.0.0:8000 --worker-class sanic.worker.GunicornWorker
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
**Database Configuration**:
|
||||||
|
```bash
|
||||||
|
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/myuploader
|
||||||
|
DB_POOL_SIZE=20
|
||||||
|
DB_MAX_OVERFLOW=30
|
||||||
|
```
|
||||||
|
|
||||||
|
**Redis Configuration**:
|
||||||
|
```bash
|
||||||
|
REDIS_URL=redis://localhost:6379/0
|
||||||
|
REDIS_POOL_SIZE=20
|
||||||
|
REDIS_POOL_MAX_CONNECTIONS=100
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security Configuration**:
|
||||||
|
```bash
|
||||||
|
SECRET_KEY=your-super-secret-key-here
|
||||||
|
JWT_SECRET_KEY=your-jwt-secret-key
|
||||||
|
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||||
|
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||||
|
```
|
||||||
|
|
||||||
|
**Storage Configuration**:
|
||||||
|
```bash
|
||||||
|
STORAGE_BACKEND=local # or s3, gcs, azure
|
||||||
|
STORAGE_PATH=/app/uploads
|
||||||
|
MAX_FILE_SIZE=104857600 # 100MB
|
||||||
|
ALLOWED_FILE_TYPES=image,video,audio,document
|
||||||
|
```
|
||||||
|
|
||||||
|
**Blockchain Configuration**:
|
||||||
|
```bash
|
||||||
|
TON_NETWORK=mainnet # or testnet
|
||||||
|
TON_API_KEY=your-ton-api-key
|
||||||
|
TON_WALLET_VERSION=v4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
|
||||||
|
**Redis Configuration** (`config/redis.conf`):
|
||||||
|
- Optimized for caching workload
|
||||||
|
- Memory management and persistence settings
|
||||||
|
- Security and performance tuning
|
||||||
|
|
||||||
|
**Prometheus Configuration** (`monitoring/prometheus.yml`):
|
||||||
|
- Scraping configuration for all services
|
||||||
|
- Alert rules and metric collection
|
||||||
|
- Storage and retention settings
|
||||||
|
|
||||||
|
## 📊 API Documentation
|
||||||
|
|
||||||
|
### Interactive Documentation
|
||||||
|
- **Swagger UI**: http://localhost:8000/docs
|
||||||
|
- **ReDoc**: http://localhost:8000/redoc
|
||||||
|
- **OpenAPI JSON**: http://localhost:8000/openapi.json
|
||||||
|
|
||||||
|
### Authentication Methods
|
||||||
|
|
||||||
|
1. **JWT Bearer Token**:
|
||||||
|
```bash
|
||||||
|
curl -H "Authorization: Bearer <token>" \
|
||||||
|
https://api.myuploader.com/api/v1/content/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **API Key**:
|
||||||
|
```bash
|
||||||
|
curl -H "X-API-Key: <api_key>" \
|
||||||
|
https://api.myuploader.com/api/v1/content/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Session Cookie**:
|
||||||
|
```bash
|
||||||
|
curl -b "session=<cookie>" \
|
||||||
|
https://api.myuploader.com/api/v1/content/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Endpoints
|
||||||
|
|
||||||
|
**Authentication**:
|
||||||
|
- `POST /api/v1/auth/register` - User registration
|
||||||
|
- `POST /api/v1/auth/login` - User login
|
||||||
|
- `POST /api/v1/auth/refresh` - Token refresh
|
||||||
|
- `DELETE /api/v1/auth/logout` - User logout
|
||||||
|
|
||||||
|
**Content Management**:
|
||||||
|
- `GET /api/v1/content/` - List content
|
||||||
|
- `POST /api/v1/content/` - Create content
|
||||||
|
- `GET /api/v1/content/{id}` - Get content details
|
||||||
|
- `PUT /api/v1/content/{id}` - Update content
|
||||||
|
- `DELETE /api/v1/content/{id}` - Delete content
|
||||||
|
|
||||||
|
**File Upload**:
|
||||||
|
- `POST /api/v1/storage/upload/initiate` - Start upload
|
||||||
|
- `POST /api/v1/storage/upload/chunk` - Upload chunk
|
||||||
|
- `POST /api/v1/storage/upload/complete` - Complete upload
|
||||||
|
- `GET /api/v1/storage/download/{id}` - Download file
|
||||||
|
|
||||||
|
**Blockchain**:
|
||||||
|
- `POST /api/v1/blockchain/wallet/create` - Create wallet
|
||||||
|
- `GET /api/v1/blockchain/wallet/{id}` - Get wallet info
|
||||||
|
- `POST /api/v1/blockchain/transaction/send` - Send transaction
|
||||||
|
- `GET /api/v1/blockchain/transaction/{hash}` - Get transaction status
|
||||||
|
|
||||||
|
## 🛡️ Security
|
||||||
|
|
||||||
|
### Security Features
|
||||||
|
- **Authentication**: Multi-factor authentication support
|
||||||
|
- **Authorization**: Role-based access control (RBAC)
|
||||||
|
- **Input Validation**: Comprehensive request validation
|
||||||
|
- **Rate Limiting**: Per-user and per-endpoint limits
|
||||||
|
- **File Security**: Virus scanning, type validation, encryption
|
||||||
|
- **Network Security**: CORS, CSP, HTTPS enforcement
|
||||||
|
|
||||||
|
### Security Best Practices
|
||||||
|
|
||||||
|
1. **Environment Variables**: Store sensitive data in environment variables
|
||||||
|
2. **Database Security**: Use connection pooling, parameterized queries
|
||||||
|
3. **File Upload Security**: Validate file types, scan for malware
|
||||||
|
4. **API Security**: Implement rate limiting, request validation
|
||||||
|
5. **Monitoring**: Track security events and anomalies
|
||||||
|
|
||||||
|
### Audit Logging
|
||||||
|
All security-relevant events are logged:
|
||||||
|
- Authentication attempts
|
||||||
|
- Authorization failures
|
||||||
|
- File upload/download events
|
||||||
|
- API key usage
|
||||||
|
- Blockchain transactions
|
||||||
|
|
||||||
|
## 📈 Monitoring & Observability
|
||||||
|
|
||||||
|
### Metrics Collection
|
||||||
|
- **Application Metrics**: Request counts, response times, error rates
|
||||||
|
- **System Metrics**: CPU, memory, disk usage
|
||||||
|
- **Database Metrics**: Connection pool, query performance
|
||||||
|
- **Cache Metrics**: Hit rates, memory usage
|
||||||
|
- **Blockchain Metrics**: Transaction status, wallet balances
|
||||||
|
|
||||||
|
### Dashboards
|
||||||
|
- **Application Dashboard**: Request metrics, error rates
|
||||||
|
- **Infrastructure Dashboard**: System resources, service health
|
||||||
|
- **Database Dashboard**: Query performance, connection pools
|
||||||
|
- **Security Dashboard**: Failed logins, rate limits
|
||||||
|
|
||||||
|
### Alerting Rules
|
||||||
|
- High error rates (>5% for 5 minutes)
|
||||||
|
- High response times (>2s for 95th percentile)
|
||||||
|
- Database connection issues
|
||||||
|
- High memory usage (>90%)
|
||||||
|
- Failed blockchain transactions
|
||||||
|
|
||||||
|
## 🔄 Background Services
|
||||||
|
|
||||||
|
### File Conversion Service
|
||||||
|
- **Image Processing**: Resize, optimize, generate thumbnails
|
||||||
|
- **Video Processing**: Transcode, extract thumbnails
|
||||||
|
- **Document Processing**: Extract metadata, generate previews
|
||||||
|
- **Retry Logic**: Automatic retry for failed conversions
|
||||||
|
|
||||||
|
### Blockchain Indexer Service
|
||||||
|
- **Transaction Monitoring**: Track pending transactions
|
||||||
|
- **Wallet Balance Updates**: Sync wallet balances
|
||||||
|
- **NFT Indexing**: Track NFT collections and transfers
|
||||||
|
- **Event Processing**: Process blockchain events
|
||||||
|
|
||||||
|
## 🚀 Deployment
|
||||||
|
|
||||||
|
### Docker Deployment
|
||||||
|
|
||||||
|
1. **Production Build**:
|
||||||
|
```bash
|
||||||
|
docker build -f Dockerfile.new --target production -t my-uploader-bot:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy with Compose**:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.new.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Health Checks**:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kubernetes Deployment
|
||||||
|
|
||||||
|
1. **Create ConfigMaps**:
|
||||||
|
```bash
|
||||||
|
kubectl create configmap app-config --from-env-file=.env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy Application**:
|
||||||
|
```bash
|
||||||
|
kubectl apply -f k8s/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check Status**:
|
||||||
|
```bash
|
||||||
|
kubectl get pods -l app=my-uploader-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Considerations
|
||||||
|
|
||||||
|
1. **Database**: Use managed PostgreSQL service
|
||||||
|
2. **Cache**: Use managed Redis service
|
||||||
|
3. **Storage**: Use S3-compatible object storage
|
||||||
|
4. **Load Balancer**: Use cloud load balancer
|
||||||
|
5. **SSL/TLS**: Use Let's Encrypt or cloud SSL
|
||||||
|
6. **Monitoring**: Use managed monitoring service
|
||||||
|
|
||||||
|
## 🧪 Testing
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
pytest
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
pytest --cov=app
|
||||||
|
|
||||||
|
# Run specific test file
|
||||||
|
pytest tests/test_auth.py
|
||||||
|
|
||||||
|
# Run integration tests
|
||||||
|
pytest tests/integration/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Categories
|
||||||
|
- **Unit Tests**: Individual function/method tests
|
||||||
|
- **Integration Tests**: Service integration tests
|
||||||
|
- **API Tests**: HTTP endpoint tests
|
||||||
|
- **Database Tests**: Database operation tests
|
||||||
|
- **Security Tests**: Security vulnerability tests
|
||||||
|
|
||||||
|
## 🔍 Development
|
||||||
|
|
||||||
|
### Development Setup
|
||||||
|
```bash
|
||||||
|
# Install dev dependencies
|
||||||
|
poetry install --dev
|
||||||
|
|
||||||
|
# Pre-commit hooks
|
||||||
|
pre-commit install
|
||||||
|
|
||||||
|
# Run linting
|
||||||
|
black app/
|
||||||
|
isort app/
|
||||||
|
mypy app/
|
||||||
|
|
||||||
|
# Database migrations
|
||||||
|
alembic revision --autogenerate -m "Description"
|
||||||
|
alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Quality Tools
|
||||||
|
- **Black**: Code formatting
|
||||||
|
- **isort**: Import sorting
|
||||||
|
- **mypy**: Type checking
|
||||||
|
- **bandit**: Security scanning
|
||||||
|
- **pytest**: Testing framework
|
||||||
|
|
||||||
|
### Contributing Guidelines
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create feature branch
|
||||||
|
3. Write tests for new features
|
||||||
|
4. Ensure all tests pass
|
||||||
|
5. Run security scans
|
||||||
|
6. Submit pull request
|
||||||
|
|
||||||
|
## 📝 Migration Guide
|
||||||
|
|
||||||
|
### From v1.x to v2.x
|
||||||
|
|
||||||
|
1. **Database Migration**:
|
||||||
|
```bash
|
||||||
|
# Backup existing database
|
||||||
|
pg_dump myuploader > backup.sql
|
||||||
|
|
||||||
|
# Run new migrations
|
||||||
|
alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configuration Updates**:
|
||||||
|
- Update environment variables
|
||||||
|
- Migrate Redis configuration
|
||||||
|
- Update storage configuration
|
||||||
|
|
||||||
|
3. **API Changes**:
|
||||||
|
- Authentication endpoints changed
|
||||||
|
- New blockchain endpoints added
|
||||||
|
- Response format updates
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**Database Connection Issues**:
|
||||||
|
```bash
|
||||||
|
# Check database connectivity
|
||||||
|
psql -h localhost -U postgres -d myuploader
|
||||||
|
|
||||||
|
# Check connection pool
|
||||||
|
docker-compose logs db
|
||||||
|
```
|
||||||
|
|
||||||
|
**Redis Connection Issues**:
|
||||||
|
```bash
|
||||||
|
# Test Redis connection
|
||||||
|
redis-cli ping
|
||||||
|
|
||||||
|
# Check Redis logs
|
||||||
|
docker-compose logs redis
|
||||||
|
```
|
||||||
|
|
||||||
|
**File Upload Issues**:
|
||||||
|
```bash
|
||||||
|
# Check storage permissions
|
||||||
|
ls -la /app/uploads
|
||||||
|
|
||||||
|
# Check disk space
|
||||||
|
df -h
|
||||||
|
```
|
||||||
|
|
||||||
|
**Blockchain Issues**:
|
||||||
|
```bash
|
||||||
|
# Check TON network status
|
||||||
|
curl https://toncenter.com/api/v2/getAddressInformation
|
||||||
|
|
||||||
|
# Check wallet balance
|
||||||
|
curl -X GET /api/v1/blockchain/wallet/{wallet_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Optimization
|
||||||
|
|
||||||
|
1. **Database Optimization**:
|
||||||
|
- Add indexes for frequently queried columns
|
||||||
|
- Optimize query patterns
|
||||||
|
- Use connection pooling
|
||||||
|
|
||||||
|
2. **Cache Optimization**:
|
||||||
|
- Implement cache warming
|
||||||
|
- Use appropriate TTL values
|
||||||
|
- Monitor cache hit rates
|
||||||
|
|
||||||
|
3. **File Storage Optimization**:
|
||||||
|
- Use CDN for static files
|
||||||
|
- Implement file compression
|
||||||
|
- Use efficient storage backends
|
||||||
|
|
||||||
|
## 📚 Additional Resources
|
||||||
|
|
||||||
|
- **API Documentation**: https://docs.myuploader.com
|
||||||
|
- **SDK Documentation**: https://sdk.myuploader.com
|
||||||
|
- **Community Forum**: https://community.myuploader.com
|
||||||
|
- **GitHub Repository**: https://github.com/your-org/my-uploader-bot
|
||||||
|
- **Docker Images**: https://hub.docker.com/r/myuploader/app
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## 🤝 Support
|
||||||
|
|
||||||
|
- **Email**: support@myuploader.com
|
||||||
|
- **Discord**: https://discord.gg/myuploader
|
||||||
|
- **GitHub Issues**: https://github.com/your-org/my-uploader-bot/issues
|
||||||
|
- **Documentation**: https://docs.myuploader.com
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Built with ❤️ by the My Uploader Bot Team**
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
# Руководство по удаленной диагностике MY Network сервера
|
||||||
|
|
||||||
|
## Проблема
|
||||||
|
- SSH недоступен на порту 22 (Connection refused)
|
||||||
|
- Nginx работает на порту 80, но возвращает 404 для всех запросов
|
||||||
|
- Приложения на портах 3000, 5000, 8080 недоступны
|
||||||
|
|
||||||
|
## Диагностика на сервере (выполнить локально)
|
||||||
|
|
||||||
|
### 1. Проверить статус служб
|
||||||
|
```bash
|
||||||
|
# Проверить статус Docker
|
||||||
|
sudo systemctl status docker
|
||||||
|
|
||||||
|
# Проверить статус MyUploader service
|
||||||
|
sudo systemctl status myuploader
|
||||||
|
|
||||||
|
# Проверить запущенные контейнеры
|
||||||
|
sudo docker ps -a
|
||||||
|
|
||||||
|
# Проверить логи контейнеров
|
||||||
|
sudo docker logs uploader-bot-app-1
|
||||||
|
sudo docker logs uploader-bot-postgres-1
|
||||||
|
sudo docker logs uploader-bot-nginx-1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Проверить сетевые соединения
|
||||||
|
```bash
|
||||||
|
# Проверить какие порты слушает система
|
||||||
|
sudo netstat -tulpn | grep LISTEN
|
||||||
|
|
||||||
|
# Проверить статус nginx
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl status nginx
|
||||||
|
|
||||||
|
# Проверить конфигурацию nginx
|
||||||
|
sudo cat /etc/nginx/sites-enabled/default
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Проверить Docker Compose
|
||||||
|
```bash
|
||||||
|
# Перейти в директорию проекта
|
||||||
|
cd /home/myuploader/my-uploader-bot
|
||||||
|
|
||||||
|
# Проверить статус compose
|
||||||
|
sudo docker-compose -f docker-compose.production.yml ps
|
||||||
|
|
||||||
|
# Посмотреть логи всех сервисов
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs --tail=50
|
||||||
|
|
||||||
|
# Перезапустить сервисы
|
||||||
|
sudo docker-compose -f docker-compose.production.yml down
|
||||||
|
sudo docker-compose -f docker-compose.production.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Проверить SSH
|
||||||
|
```bash
|
||||||
|
# Проверить статус SSH
|
||||||
|
sudo systemctl status ssh
|
||||||
|
|
||||||
|
# Проверить конфигурацию SSH
|
||||||
|
sudo cat /etc/ssh/sshd_config | grep -E "Port|PasswordAuthentication|PubkeyAuthentication"
|
||||||
|
|
||||||
|
# Перезапустить SSH если нужно
|
||||||
|
sudo systemctl restart ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Проверить брандмауэр
|
||||||
|
```bash
|
||||||
|
# Проверить статус UFW
|
||||||
|
sudo ufw status
|
||||||
|
|
||||||
|
# Если UFW активен, проверить правила
|
||||||
|
sudo ufw status numbered
|
||||||
|
|
||||||
|
# Разрешить SSH (если заблокирован)
|
||||||
|
sudo ufw allow 22/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Быстрое восстановление
|
||||||
|
```bash
|
||||||
|
# Если сервисы не работают, запустить быстрое восстановление
|
||||||
|
cd /home/myuploader/my-uploader-bot
|
||||||
|
sudo ./diagnose.sh
|
||||||
|
|
||||||
|
# Проверить health API приложения
|
||||||
|
curl -I http://localhost:3000/api/health
|
||||||
|
curl -I http://localhost:5000/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Возможные решения
|
||||||
|
|
||||||
|
### Проблема с nginx proxy
|
||||||
|
Если nginx возвращает 404, проверить файл `/etc/nginx/sites-enabled/default`:
|
||||||
|
```bash
|
||||||
|
sudo cat /etc/nginx/sites-enabled/default
|
||||||
|
```
|
||||||
|
|
||||||
|
Должен содержать:
|
||||||
|
```nginx
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://localhost:3000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проблема с Docker
|
||||||
|
Если контейнеры не запущены:
|
||||||
|
```bash
|
||||||
|
cd /home/myuploader/my-uploader-bot
|
||||||
|
sudo docker-compose -f docker-compose.production.yml up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проблема с SSH
|
||||||
|
Если SSH заблокирован файрволлом:
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 22/tcp
|
||||||
|
sudo systemctl restart ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Команды для отправки результатов
|
||||||
|
После выполнения диагностики, отправьте результаты:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Сохранить всю диагностику в файл
|
||||||
|
echo "=== DOCKER STATUS ===" > diagnosis.txt
|
||||||
|
sudo docker ps -a >> diagnosis.txt
|
||||||
|
echo "=== DOCKER LOGS ===" >> diagnosis.txt
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs --tail=20 >> diagnosis.txt
|
||||||
|
echo "=== NGINX STATUS ===" >> diagnosis.txt
|
||||||
|
sudo systemctl status nginx >> diagnosis.txt
|
||||||
|
echo "=== SSH STATUS ===" >> diagnosis.txt
|
||||||
|
sudo systemctl status ssh >> diagnosis.txt
|
||||||
|
echo "=== NETWORK PORTS ===" >> diagnosis.txt
|
||||||
|
sudo netstat -tulpn | grep LISTEN >> diagnosis.txt
|
||||||
|
|
||||||
|
# Просмотреть файл
|
||||||
|
cat diagnosis.txt
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
# Устранение 502 ошибки MY Uploader Bot
|
||||||
|
|
||||||
|
## 🚨 Если получаете 502 Bad Gateway
|
||||||
|
|
||||||
|
Ошибка 502 означает, что nginx работает, но не может подключиться к backend приложению.
|
||||||
|
|
||||||
|
## 🔍 Быстрая диагностика
|
||||||
|
|
||||||
|
### 1. Запустите диагностический скрипт:
|
||||||
|
```bash
|
||||||
|
sudo /home/myuploader/uploader-bot/diagnose.sh my-public-node-3.projscale.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Проверьте статус контейнеров:
|
||||||
|
```bash
|
||||||
|
cd /home/myuploader/uploader-bot
|
||||||
|
sudo docker-compose -f docker-compose.production.yml ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Проверьте логи приложения:
|
||||||
|
```bash
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs -f app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Частые решения
|
||||||
|
|
||||||
|
### Решение 1: Приложение еще запускается
|
||||||
|
```bash
|
||||||
|
# Подождите 2-3 минуты и проверьте снова
|
||||||
|
sleep 180
|
||||||
|
curl -v https://your-domain.com/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Решение 2: Перезапуск сервисов
|
||||||
|
```bash
|
||||||
|
cd /home/myuploader/uploader-bot
|
||||||
|
sudo docker-compose -f docker-compose.production.yml restart app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Решение 3: Полная перезагрузка
|
||||||
|
```bash
|
||||||
|
cd /home/myuploader/uploader-bot
|
||||||
|
sudo docker-compose -f docker-compose.production.yml down
|
||||||
|
sudo docker-compose -f docker-compose.production.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Решение 4: Проверка базы данных
|
||||||
|
```bash
|
||||||
|
# Проверка PostgreSQL
|
||||||
|
sudo docker-compose -f docker-compose.production.yml exec postgres pg_isready -U my_user -d my_uploader_db
|
||||||
|
|
||||||
|
# Перезапуск базы данных если нужно
|
||||||
|
sudo docker-compose -f docker-compose.production.yml restart postgres redis
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Детальная диагностика
|
||||||
|
|
||||||
|
### Проверка локальных портов:
|
||||||
|
```bash
|
||||||
|
# API приложения (должен отвечать)
|
||||||
|
curl http://localhost:15100/health
|
||||||
|
|
||||||
|
# Nginx (должен перенаправлять)
|
||||||
|
curl -I http://localhost
|
||||||
|
|
||||||
|
# Проверка подключения к базе
|
||||||
|
sudo docker-compose -f docker-compose.production.yml exec app python -c "
|
||||||
|
import asyncpg
|
||||||
|
import asyncio
|
||||||
|
async def test():
|
||||||
|
try:
|
||||||
|
conn = await asyncpg.connect('postgresql://my_user:PASSWORD@postgres:5432/my_uploader_db')
|
||||||
|
await conn.close()
|
||||||
|
print('✅ База данных доступна')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'❌ Ошибка подключения к БД: {e}')
|
||||||
|
asyncio.run(test())
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка конфигурации nginx:
|
||||||
|
```bash
|
||||||
|
sudo docker-compose -f docker-compose.production.yml exec nginx nginx -t
|
||||||
|
```
|
||||||
|
|
||||||
|
### Просмотр логов в реальном времени:
|
||||||
|
```bash
|
||||||
|
# Все сервисы
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs -f
|
||||||
|
|
||||||
|
# Только основное приложение
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs -f app
|
||||||
|
|
||||||
|
# Только nginx
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs -f nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Тестирование после исправления
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Проверьте статус всех контейнеров
|
||||||
|
sudo docker-compose -f docker-compose.production.yml ps
|
||||||
|
|
||||||
|
# 2. Проверьте health endpoints
|
||||||
|
curl http://localhost:15100/health
|
||||||
|
curl https://your-domain.com/health
|
||||||
|
|
||||||
|
# 3. Проверьте основные endpoints
|
||||||
|
curl -I https://your-domain.com/
|
||||||
|
curl https://your-domain.com/api/my/bootstrap/config
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 Если проблема не решается
|
||||||
|
|
||||||
|
1. **Соберите диагностическую информацию:**
|
||||||
|
```bash
|
||||||
|
sudo /home/myuploader/uploader-bot/diagnose.sh your-domain.com > diagnostic_report.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Сохраните логи:**
|
||||||
|
```bash
|
||||||
|
sudo docker-compose -f docker-compose.production.yml logs --tail=100 > all_logs.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Проверьте ресурсы системы:**
|
||||||
|
```bash
|
||||||
|
docker stats --no-stream
|
||||||
|
df -h
|
||||||
|
free -h
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚡ Экстренное восстановление
|
||||||
|
|
||||||
|
Если ничего не помогает:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Полная остановка
|
||||||
|
sudo systemctl stop my-uploader-bot
|
||||||
|
sudo docker-compose -f docker-compose.production.yml down -v
|
||||||
|
|
||||||
|
# 2. Очистка и перезапуск
|
||||||
|
sudo docker system prune -f
|
||||||
|
sudo docker-compose -f docker-compose.production.yml pull
|
||||||
|
sudo docker-compose -f docker-compose.production.yml up -d --build
|
||||||
|
|
||||||
|
# 3. Проверка через 5 минут
|
||||||
|
sleep 300
|
||||||
|
curl -v https://your-domain.com/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Ожидаемый результат
|
||||||
|
|
||||||
|
После успешного исправления:
|
||||||
|
- `curl http://localhost:15100/health` возвращает 200 OK
|
||||||
|
- `curl https://your-domain.com/health` возвращает 200 OK
|
||||||
|
- Все контейнеры в статусе "Up"
|
||||||
|
- В логах нет критических ошибок
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from tonsdk.boc import Cell\n",
|
||||||
|
"from base64 import b64decode"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"s = Cell.one_from_boc(b64decode(\n",
|
||||||
|
" \"te6cckECCwEAAWcAAotUkdCMcWNw723qPXgUdCcgt8COtmF/zIqTQpNUO7Hx3cFkE6SAHuuAXC2ImbR2RbW6eaLmYTaiOFzd06Q3v6GEw1xpHOswAQUCAaACAwALAECPDRgIAQHRBABHgB7rgFwtiJm0dkW1unmi5mE2ojhc3dOkN7+hhMNcaRzrJOIQAgAGBwD6aHR0cHM6Ly9teS1wdWJsaWMtbm9kZS0xLnByb2pzY2FsZS5kZXYvYXBpL3YxLjUvc3RvcmFnZS85S0h5RHAyYUppRTRuaG1uOExxazd4dmZxeWpwQXdXR1dYU2ozMkNVQW04V3NLdVFLSkJlTktIV0prZzhyZFloTm82MzcDAAgJCgBYajZGa3ZtREN1RUJhOHhrTDlpV1NSem1peXAxSGhYMlJkUFNFWWZpb1JRMWgAAABYblJUVW96dGJBcXF0Z25EWEN1cFU4UXRZWmFtY1dxdjlSTDQ0UURYbVpvQVbtCcTY\"\n",
|
||||||
|
"))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"s = s.begin_parse()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'AddressEQD3XALhbETNo7ItrdPNFzMJtRHC5u6dIb39DCYa40jnWcql'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"s.read_uint(32)\n",
|
||||||
|
"s.read_uint(256)\n",
|
||||||
|
"'Address' + s.read_msg_addr().to_string(1, 1, 1)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"ename": "ValueError",
|
||||||
|
"evalue": "invalid literal for int() with base 10: 'b'",
|
||||||
|
"output_type": "error",
|
||||||
|
"traceback": [
|
||||||
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||||
|
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
|
||||||
|
"Cell \u001b[0;32mIn[7], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mAddress\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m+\u001b[39m s\u001b[38;5;241m.\u001b[39mread_msg_addr()\u001b[38;5;241m.\u001b[39mto_string(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m1\u001b[39m)\n",
|
||||||
|
"File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/tonsdk/boc/_slice.py:93\u001b[0m, in \u001b[0;36mSlice.read_msg_addr\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 91\u001b[0m workchain_id \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mhex\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mread_int(\u001b[38;5;241m8\u001b[39m))\u001b[38;5;241m.\u001b[39mreplace(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m0x\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 92\u001b[0m hashpart \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mread_bytes(\u001b[38;5;241m32\u001b[39m)\u001b[38;5;241m.\u001b[39mhex()\n\u001b[0;32m---> 93\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Address(workchain_id \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m:\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m hashpart)\n",
|
||||||
|
"File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/tonsdk/utils/_address.py:87\u001b[0m, in \u001b[0;36mAddress.__init__\u001b[0;34m(self, any_form)\u001b[0m\n\u001b[1;32m 84\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(arr) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m2\u001b[39m:\n\u001b[1;32m 85\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidAddressError(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid address \u001b[39m\u001b[38;5;132;01m{\u001b[39;00many_form\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m---> 87\u001b[0m wc \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(arr[\u001b[38;5;241m0\u001b[39m])\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m wc \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m wc \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 89\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidAddressError(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid address wc \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mwc\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
|
||||||
|
"\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'b'"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"'Address' + s.read_msg_addr().to_string(1, 1, 1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"s = Cell.one_from_boc('b5ee9c7201020b0100016700028b5491d08c716370ef6dea3d7814742720b7c08eb6617fcc8a934293543bb1f1ddc16413a4801eeb805c2d8899b47645b5ba79a2e66136a2385cddd3a437bfa184c35c691ceb3001020201a0030402000607000b00408f0d18080101d1050047801eeb805c2d8899b47645b5ba79a2e66136a2385cddd3a437bfa184c35c691ceb24e21000fa68747470733a2f2f6d792d7075626c69632d6e6f64652d312e70726f6a7363616c652e6465762f6170692f76312e352f73746f726167652f394b4879447032614a6945346e686d6e384c716b3778766671796a70417757475758536a33324355416d3857734b75514b4a42654e4b48574a6b6738726459684e6f363337030008090a00586a36466b766d44437545426138786b4c39695753527a6d697970314868583252645053455966696f52513168000000586e5254556f7a746241717174676e445843757055385174595a616d6357717639524c34345144586d5a6f4156')\n",
|
||||||
|
"s = s.begin_parse()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 9,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"s.read_uint(256)\n",
|
||||||
|
"s.read_uint(2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'0b11'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"bin(3)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "base",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.12.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,433 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# MY NETWORK UNIVERSAL INSTALLER
|
||||||
|
# Универсальный установщик для любого сервера с автопоиском проекта и полной настройкой
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=================================================="
|
||||||
|
echo "🚀 MY NETWORK UNIVERSAL INSTALLER"
|
||||||
|
echo "Универсальная установка и восстановление сервера"
|
||||||
|
echo "=================================================="
|
||||||
|
|
||||||
|
# Определение системы
|
||||||
|
OS_ID=$(lsb_release -i 2>/dev/null | cut -f2 || echo "unknown")
|
||||||
|
OS_VERSION=$(lsb_release -r 2>/dev/null | cut -f2 || echo "unknown")
|
||||||
|
|
||||||
|
echo "🖥️ Система: $OS_ID $OS_VERSION"
|
||||||
|
echo "👤 Пользователь: $(whoami)"
|
||||||
|
echo "📁 Текущая директория: $(pwd)"
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# ПОИСК ПРОЕКТА
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 1. ПОИСК ПРОЕКТА ==="
|
||||||
|
|
||||||
|
PROJECT_LOCATIONS=(
|
||||||
|
"/home/myuploader/uploader-bot"
|
||||||
|
"/home/uploader-bot"
|
||||||
|
"/home/myuploader/my-uploader-bot"
|
||||||
|
"/root/uploader-bot"
|
||||||
|
"/root/my-uploader-bot"
|
||||||
|
"/opt/uploader-bot"
|
||||||
|
"/opt/my-uploader-bot"
|
||||||
|
"/var/www/uploader-bot"
|
||||||
|
"/var/www/my-uploader-bot"
|
||||||
|
"$(pwd)"
|
||||||
|
"$(pwd)/../uploader-bot"
|
||||||
|
"$(pwd)/../my-uploader-bot"
|
||||||
|
)
|
||||||
|
|
||||||
|
PROJECT_DIR=""
|
||||||
|
COMPOSE_FILE=""
|
||||||
|
|
||||||
|
echo "🔍 Поиск проекта в стандартных местах..."
|
||||||
|
for dir in "${PROJECT_LOCATIONS[@]}"; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
for compose in "docker-compose.production.yml" "docker-compose.yml" "docker-compose.new.yml"; do
|
||||||
|
if [ -f "$dir/$compose" ]; then
|
||||||
|
PROJECT_DIR="$dir"
|
||||||
|
COMPOSE_FILE="$compose"
|
||||||
|
echo "✅ Проект найден: $PROJECT_DIR"
|
||||||
|
echo "✅ Compose файл: $COMPOSE_FILE"
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$PROJECT_DIR" ]; then
|
||||||
|
echo "🔍 Глобальный поиск проекта..."
|
||||||
|
FOUND_PROJECTS=$(find / -name "docker-compose*.yml" -path "*/uploader-bot*" 2>/dev/null | head -3)
|
||||||
|
if [ -n "$FOUND_PROJECTS" ]; then
|
||||||
|
echo "Найдены проекты:"
|
||||||
|
echo "$FOUND_PROJECTS"
|
||||||
|
FIRST_FOUND=$(echo "$FOUND_PROJECTS" | head -1)
|
||||||
|
PROJECT_DIR=$(dirname "$FIRST_FOUND")
|
||||||
|
COMPOSE_FILE=$(basename "$FIRST_FOUND")
|
||||||
|
echo "✅ Выбран: $PROJECT_DIR"
|
||||||
|
else
|
||||||
|
echo "❌ Проект не найден автоматически!"
|
||||||
|
read -p "📝 Введите полный путь к директории проекта: " PROJECT_DIR
|
||||||
|
if [ ! -d "$PROJECT_DIR" ]; then
|
||||||
|
echo "❌ Директория не существует: $PROJECT_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Найти compose файл
|
||||||
|
for compose in "docker-compose.production.yml" "docker-compose.yml" "docker-compose.new.yml"; do
|
||||||
|
if [ -f "$PROJECT_DIR/$compose" ]; then
|
||||||
|
COMPOSE_FILE="$compose"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$COMPOSE_FILE" ]; then
|
||||||
|
echo "❌ Docker compose файл не найден в $PROJECT_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
echo "📁 Работаю в: $(pwd)"
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# УСТАНОВКА ЗАВИСИМОСТЕЙ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 2. УСТАНОВКА СИСТЕМНЫХ ЗАВИСИМОСТЕЙ ==="
|
||||||
|
|
||||||
|
# Обновление системы
|
||||||
|
echo "📦 Обновление системы..."
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# Установка основных пакетов
|
||||||
|
echo "📦 Установка базовых пакетов..."
|
||||||
|
sudo apt install -y curl wget git nginx ufw fail2ban htop nano net-tools
|
||||||
|
|
||||||
|
# Установка Docker
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo "🐳 Установка Docker..."
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
rm get-docker.sh
|
||||||
|
else
|
||||||
|
echo "✅ Docker уже установлен: $(docker --version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Установка Docker Compose
|
||||||
|
if ! command -v docker-compose &> /dev/null; then
|
||||||
|
echo "🐳 Установка Docker Compose..."
|
||||||
|
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||||
|
sudo chmod +x /usr/local/bin/docker-compose
|
||||||
|
else
|
||||||
|
echo "✅ Docker Compose уже установлен: $(docker-compose --version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# НАСТРОЙКА БЕЗОПАСНОСТИ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 3. НАСТРОЙКА БЕЗОПАСНОСТИ ==="
|
||||||
|
|
||||||
|
# Настройка UFW
|
||||||
|
echo "🔥 Настройка файрвола..."
|
||||||
|
sudo ufw --force reset
|
||||||
|
sudo ufw default deny incoming
|
||||||
|
sudo ufw default allow outgoing
|
||||||
|
sudo ufw allow 22/tcp
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
sudo ufw --force enable
|
||||||
|
|
||||||
|
# Настройка fail2ban
|
||||||
|
echo "🛡️ Настройка fail2ban..."
|
||||||
|
sudo systemctl enable fail2ban
|
||||||
|
sudo systemctl start fail2ban
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# ОЧИСТКА И ПОДГОТОВКА
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 4. ОЧИСТКА СТАРЫХ КОНТЕЙНЕРОВ ==="
|
||||||
|
|
||||||
|
echo "🛑 Останавливаю все контейнеры..."
|
||||||
|
docker stop $(docker ps -aq) 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "🗑️ Удаляю старые контейнеры..."
|
||||||
|
docker rm $(docker ps -aq) 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "🧹 Очистка системы Docker..."
|
||||||
|
docker system prune -af --volumes
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# ПОДГОТОВКА ФАЙЛОВ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 5. ПОДГОТОВКА КОНФИГУРАЦИИ ==="
|
||||||
|
|
||||||
|
# Создание .env файла если нет
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
echo "📝 Создание .env файла..."
|
||||||
|
if [ -f "env.example" ]; then
|
||||||
|
cp env.example .env
|
||||||
|
else
|
||||||
|
cat > .env << 'EOF'
|
||||||
|
# Database Configuration
|
||||||
|
DATABASE_URL=postgresql://myuser:mypassword@postgres:5432/mydb
|
||||||
|
POSTGRES_USER=myuser
|
||||||
|
POSTGRES_PASSWORD=mypassword
|
||||||
|
POSTGRES_DB=mydb
|
||||||
|
|
||||||
|
# Redis Configuration
|
||||||
|
REDIS_URL=redis://redis:6379
|
||||||
|
|
||||||
|
# Application Configuration
|
||||||
|
API_HOST=0.0.0.0
|
||||||
|
API_PORT=3000
|
||||||
|
DEBUG=false
|
||||||
|
|
||||||
|
# Security
|
||||||
|
SECRET_KEY=your-secret-key-here
|
||||||
|
|
||||||
|
# Telegram Bot (if needed)
|
||||||
|
BOT_TOKEN=your-bot-token
|
||||||
|
WEBHOOK_URL=https://your-domain.com
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
echo "✅ .env файл создан"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверка requirements.txt
|
||||||
|
REQUIREMENTS_FILE="requirements.txt"
|
||||||
|
if [ ! -f "$REQUIREMENTS_FILE" ]; then
|
||||||
|
if [ -f "requirements_new.txt" ]; then
|
||||||
|
REQUIREMENTS_FILE="requirements_new.txt"
|
||||||
|
elif [ -f "requirements.compatible.txt" ]; then
|
||||||
|
REQUIREMENTS_FILE="requirements.compatible.txt"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "✅ Используется файл зависимостей: $REQUIREMENTS_FILE"
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# NGINX КОНФИГУРАЦИЯ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 6. НАСТРОЙКА NGINX ==="
|
||||||
|
|
||||||
|
cat > /tmp/nginx_universal.conf << 'EOF'
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
# Максимальный размер загружаемых файлов
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# API проксирование
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://localhost:3000/api/;
|
||||||
|
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_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://localhost:3000/api/health;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Альтернативные порты
|
||||||
|
location /api5000/ {
|
||||||
|
proxy_pass http://localhost:5000/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# WebSocket поддержка (если нужна)
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://localhost:3000/ws/;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Статические файлы (если есть web2-client)
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ @app;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fallback на приложение
|
||||||
|
location @app {
|
||||||
|
proxy_pass http://localhost:3000/;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gzip сжатие
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo mv /tmp/nginx_universal.conf /etc/nginx/sites-available/default
|
||||||
|
sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
|
# Удаление дефолтной страницы nginx
|
||||||
|
sudo rm -f /var/www/html/index.nginx-debian.html
|
||||||
|
|
||||||
|
echo "✅ Nginx конфигурация создана"
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# ЗАПУСК ПРИЛОЖЕНИЯ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 7. ЗАПУСК ПРИЛОЖЕНИЯ ==="
|
||||||
|
|
||||||
|
echo "🚀 Запуск Docker Compose..."
|
||||||
|
|
||||||
|
# Стратегия запуска: сначала базовые сервисы, потом приложение
|
||||||
|
echo "📊 Запуск базы данных и Redis..."
|
||||||
|
if docker-compose -f "$COMPOSE_FILE" up -d postgres redis 2>/dev/null; then
|
||||||
|
echo "✅ База данных запущена"
|
||||||
|
else
|
||||||
|
echo "⚠️ Ошибка запуска БД, пробую альтернативные имена сервисов..."
|
||||||
|
docker-compose -f "$COMPOSE_FILE" up -d db database mysql mariadb redis 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "⏳ Ждем запуска БД (15 секунд)..."
|
||||||
|
sleep 15
|
||||||
|
|
||||||
|
echo "🚀 Запуск основного приложения..."
|
||||||
|
if docker-compose -f "$COMPOSE_FILE" --profile main-node up -d 2>/dev/null; then
|
||||||
|
echo "✅ Main-node профиль запущен"
|
||||||
|
elif docker-compose -f "$COMPOSE_FILE" up -d app 2>/dev/null; then
|
||||||
|
echo "✅ Приложение запущено"
|
||||||
|
else
|
||||||
|
echo "⚠️ Пробую запустить все сервисы..."
|
||||||
|
docker-compose -f "$COMPOSE_FILE" up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "⏳ Ждем запуска приложения (30 секунд)..."
|
||||||
|
sleep 30
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# СОЗДАНИЕ SYSTEMD SERVICE
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 8. СОЗДАНИЕ SYSTEMD SERVICE ==="
|
||||||
|
|
||||||
|
cat > /tmp/mynetwork.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=MY Network Service
|
||||||
|
After=docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
WorkingDirectory=$PROJECT_DIR
|
||||||
|
ExecStart=/usr/bin/docker-compose -f $COMPOSE_FILE up -d
|
||||||
|
ExecStop=/usr/bin/docker-compose -f $COMPOSE_FILE down
|
||||||
|
TimeoutStartSec=300
|
||||||
|
User=root
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo mv /tmp/mynetwork.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable mynetwork
|
||||||
|
|
||||||
|
echo "✅ SystemD service создан и активирован"
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# ФИНАЛЬНАЯ ПРОВЕРКА
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=== 9. ФИНАЛЬНАЯ ПРОВЕРКА ==="
|
||||||
|
|
||||||
|
# Перезапуск nginx
|
||||||
|
sudo nginx -t && sudo systemctl restart nginx
|
||||||
|
echo "✅ Nginx перезапущен"
|
||||||
|
|
||||||
|
# Проверка статуса
|
||||||
|
echo "📊 Статус контейнеров:"
|
||||||
|
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔍 Тестирование соединений:"
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Тест локальных портов
|
||||||
|
for port in 3000 5000 8080; do
|
||||||
|
if timeout 5 curl -s http://localhost:$port/api/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ localhost:$port/api/health - РАБОТАЕТ"
|
||||||
|
else
|
||||||
|
echo "❌ localhost:$port/api/health - НЕ РАБОТАЕТ"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Тест nginx proxy
|
||||||
|
if timeout 5 curl -s http://localhost/api/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ nginx proxy (/api/health) - РАБОТАЕТ"
|
||||||
|
else
|
||||||
|
echo "❌ nginx proxy (/api/health) - НЕ РАБОТАЕТ"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if timeout 5 curl -s http://localhost/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ nginx proxy (/health) - РАБОТАЕТ"
|
||||||
|
else
|
||||||
|
echo "❌ nginx proxy (/health) - НЕ РАБОТАЕТ"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# РЕЗУЛЬТАТ
|
||||||
|
# ===========================
|
||||||
|
echo ""
|
||||||
|
echo "=================================================="
|
||||||
|
echo "🎉 УСТАНОВКА ЗАВЕРШЕНА!"
|
||||||
|
echo "=================================================="
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 ИНФОРМАЦИЯ О СИСТЕМЕ:"
|
||||||
|
echo "Проект: $PROJECT_DIR"
|
||||||
|
echo "Compose: $COMPOSE_FILE"
|
||||||
|
echo "Внешний IP: $(curl -s ifconfig.me 2>/dev/null || echo "неизвестно")"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🌐 ТЕСТИРОВАНИЕ:"
|
||||||
|
EXTERNAL_IP=$(curl -s ifconfig.me 2>/dev/null || echo "YOUR_SERVER_IP")
|
||||||
|
echo "curl -I http://$EXTERNAL_IP/api/health"
|
||||||
|
echo "curl -I http://$EXTERNAL_IP/health"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔍 ДИАГНОСТИКА (если нужна):"
|
||||||
|
echo "docker ps"
|
||||||
|
echo "docker logs \$(docker ps --format \"{{.Names}}\" | grep app | head -1)"
|
||||||
|
echo "sudo systemctl status mynetwork"
|
||||||
|
echo "sudo journalctl -u nginx -f"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🛠️ УПРАВЛЕНИЕ:"
|
||||||
|
echo "Запуск: sudo systemctl start mynetwork"
|
||||||
|
echo "Остановка: sudo systemctl stop mynetwork"
|
||||||
|
echo "Перезапуск: sudo systemctl restart mynetwork"
|
||||||
|
echo "Статус: sudo systemctl status mynetwork"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ MY Network готов к работе!"
|
||||||
Loading…
Reference in New Issue