#!/bin/bash # MY Network Bootstrap Node - Автоматическое развертывание # Домен: my-public-node-3.projscale.dev # Сервер: 2.58.65.188 # Единственная команда для полного развертывания set -e echo "🚀 MY Network Bootstrap Node - Автоматическое развертывание" echo "==========================================================" echo "Домен: my-public-node-3.projscale.dev" echo "Режим: Bootstrap Node (Primary)" echo "Порты: Только 443 (HTTPS)" echo "" # Проверка прав root if [[ $EUID -ne 0 ]]; then echo "❌ Запустите от root: sudo bash auto_deploy.sh" exit 1 fi DOMAIN="my-public-node-3.projscale.dev" EMAIL="admin@projscale.dev" PROJECT_DIR="/opt/my-network" echo "📋 Конфигурация:" echo " Домен: $DOMAIN" echo " Директория: $PROJECT_DIR" echo " Внешний порт: 443 только" echo "" # Обновление системы echo "🔄 Обновление системы..." apt update && apt upgrade -y # Установка базовых пакетов echo "📦 Установка пакетов..." apt install -y \ docker.io \ docker-compose \ git \ curl \ wget \ unzip \ python3 \ python3-pip \ python3-venv \ nginx \ certbot \ python3-certbot-nginx \ ufw \ fail2ban \ htop \ tree \ nano \ jq \ net-tools \ software-properties-common # Настройка Docker echo "🐳 Настройка Docker..." systemctl enable docker systemctl start docker # Создание структуры проекта echo "📁 Создание структуры..." mkdir -p $PROJECT_DIR mkdir -p /opt/storage /opt/logs chmod 755 /opt/storage /opt/logs cd $PROJECT_DIR # Создание структуры проекта MY Network echo "🏗️ Создание структуры MY Network проекта..." mkdir -p my-uploader-bot/{app,static,templates} mkdir -p my-uploader-bot/app/{core,api} mkdir -p my-uploader-bot/app/core/{my_network,models,background} mkdir -p my-uploader-bot/app/api/routes mkdir -p my-uploader-bot/app/templates cd my-uploader-bot # Создание requirements.txt echo "📝 Создание requirements.txt..." cat > requirements_new.txt << 'EOF' fastapi==0.104.1 sanic==23.6.0 uvicorn==0.24.0 pydantic==2.5.0 sqlalchemy==2.0.23 alembic==1.12.1 pymysql==1.1.0 cryptography==41.0.7 redis==5.0.1 requests==2.31.0 aiohttp==3.9.1 websockets==12.0 python-multipart==0.0.6 python-jose[cryptography]==3.3.0 passlib[bcrypt]==1.7.4 jinja2==3.1.2 python-dotenv==1.0.0 aiomysql==0.2.0 aioredis==2.0.1 httpx==0.25.2 schedule==1.2.0 psutil==5.9.6 netifaces==0.11.0 matplotlib==3.8.2 numpy==1.25.2 pillow==10.1.0 qrcode==7.4.2 prometheus-client==0.19.0 EOF # Создание основной конфигурации echo "⚙️ Создание конфигурации..." cat > .env << EOF # MY Network Bootstrap Node Configuration NODE_ID=bootstrap-$(date +%s) NODE_TYPE=bootstrap NODE_PORT=15100 DOMAIN=$DOMAIN EMAIL=$EMAIL # Bootstrap Settings IS_BOOTSTRAP=true BOOTSTRAP_NODES=[] MAX_PEERS=100 SYNC_INTERVAL=300 PUBLIC_NODE=true # Database DB_HOST=localhost DB_PORT=3306 DB_NAME=my_network_bootstrap DB_USER=my_network_user DB_PASSWORD=$(openssl rand -base64 32) # Redis REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD=$(openssl rand -base64 32) # Security SECRET_KEY=$(openssl rand -base64 64) JWT_SECRET=$(openssl rand -base64 32) # Paths STORAGE_PATH=/opt/storage LOG_PATH=/opt/logs # API Settings API_RATE_LIMIT=100 MONITOR_RATE_LIMIT=10 ENABLE_PUBLIC_API=true ENABLE_CORS=true EOF # Создание bootstrap.json echo "🌐 Создание bootstrap.json..." cat > bootstrap.json << EOF { "version": "2.0", "network_id": "my-network-main", "bootstrap_nodes": [ { "id": "bootstrap-primary", "host": "$DOMAIN", "port": 443, "ssl": true, "public": true, "region": "eu-central", "capacity": "high", "services": ["api", "sync", "monitor", "storage"], "last_seen": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" } ], "network_config": { "protocol_version": "2.0", "sync_interval": 300, "max_peers": 100, "chunk_size": 1048576, "compression": true, "encryption": true, "heartbeat_interval": 60 }, "api_endpoints": { "base_url": "https://$DOMAIN", "health": "/api/my/health", "node_info": "/api/my/node/info", "peers": "/api/my/node/peers", "sync": "/api/my/sync/status", "monitor": "/api/my/monitor/", "bootstrap": "/api/my/bootstrap/config" } } EOF # Создание Docker Compose конфигурации echo "🐳 Создание Docker Compose..." cat > docker-compose.new.yml << EOF version: '3.8' services: mariadb: image: mariadb:11.2 container_name: my_network_db environment: MYSQL_ROOT_PASSWORD: \${DB_PASSWORD} MYSQL_DATABASE: \${DB_NAME} MYSQL_USER: \${DB_USER} MYSQL_PASSWORD: \${DB_PASSWORD} ports: - "127.0.0.1:3306:3306" volumes: - mariadb_data:/var/lib/mysql restart: unless-stopped redis: image: redis:7-alpine container_name: my_network_redis command: redis-server --requirepass \${REDIS_PASSWORD} ports: - "127.0.0.1:6379:6379" volumes: - redis_data:/data restart: unless-stopped volumes: mariadb_data: redis_data: EOF # Создание основного приложения echo "🐍 Создание Python приложения..." # app/main.py cat > app/main.py << 'EOF' #!/usr/bin/env python3 """MY Network Bootstrap Node - Main Application""" import asyncio import json import os import sys import logging from datetime import datetime from pathlib import Path # Добавляем путь к приложению sys.path.append(os.path.dirname(os.path.abspath(__file__))) try: from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse, HTMLResponse from fastapi.middleware.cors import CORSMiddleware import uvicorn USE_FASTAPI = True except ImportError: try: from sanic import Sanic, response USE_FASTAPI = False except ImportError: print("Neither FastAPI nor Sanic available") sys.exit(1) # Настройка логирования logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('/opt/logs/my-network.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) # Конфигурация NODE_ID = os.getenv('NODE_ID', f'bootstrap-{int(datetime.now().timestamp())}') DOMAIN = os.getenv('DOMAIN', 'my-public-node-3.projscale.dev') NODE_PORT = int(os.getenv('NODE_PORT', 15100)) IS_BOOTSTRAP = os.getenv('IS_BOOTSTRAP', 'true').lower() == 'true' if USE_FASTAPI: app = FastAPI( title="MY Network Bootstrap Node", description="MY Network v2.0 Bootstrap Node API", version="2.0.0" ) # CORS для публичного API app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/api/my/health") async def health_check(): return JSONResponse({ "status": "healthy", "node_id": NODE_ID, "node_type": "bootstrap", "domain": DOMAIN, "timestamp": datetime.utcnow().isoformat(), "services": ["api", "sync", "monitor", "storage"] }) @app.get("/api/my/node/info") async def node_info(): return JSONResponse({ "node_id": NODE_ID, "node_type": "bootstrap", "domain": DOMAIN, "port": 443, "ssl": True, "public": True, "region": "eu-central", "capacity": "high", "services": ["api", "sync", "monitor", "storage"], "protocol_version": "2.0", "last_seen": datetime.utcnow().isoformat() }) @app.get("/api/my/bootstrap/config") async def bootstrap_config(): try: with open('bootstrap.json', 'r') as f: config = json.load(f) return JSONResponse(config) except Exception as e: logger.error(f"Error loading bootstrap config: {e}") raise HTTPException(status_code=500, detail="Config not available") @app.get("/api/my/monitor/") async def monitor_dashboard(): html_content = """ MY Network Bootstrap Monitor

🚀 MY Network Bootstrap Node

Node Status: ACTIVE

Node ID: """ + NODE_ID + """

Domain: """ + DOMAIN + """

Type: Bootstrap Primary

Services: API, Sync, Monitor, Storage

Network Status

Protocol Version: 2.0

Max Peers: 100

Public Access: Enabled

SSL: Enabled

""" return HTMLResponse(content=html_content) if __name__ == "__main__": logger.info(f"Starting MY Network Bootstrap Node on port {NODE_PORT}") uvicorn.run(app, host="0.0.0.0", port=NODE_PORT) else: # Sanic версия app = Sanic("MY_Network_Bootstrap") @app.route("/api/my/health") async def health_check(request): return response.json({ "status": "healthy", "node_id": NODE_ID, "node_type": "bootstrap", "domain": DOMAIN, "timestamp": datetime.utcnow().isoformat(), "services": ["api", "sync", "monitor", "storage"] }) @app.route("/api/my/node/info") async def node_info(request): return response.json({ "node_id": NODE_ID, "node_type": "bootstrap", "domain": DOMAIN, "port": 443, "ssl": True, "public": True, "region": "eu-central", "capacity": "high", "services": ["api", "sync", "monitor", "storage"], "protocol_version": "2.0", "last_seen": datetime.utcnow().isoformat() }) if __name__ == "__main__": logger.info(f"Starting MY Network Bootstrap Node (Sanic) on port {NODE_PORT}") app.run(host="0.0.0.0", port=NODE_PORT) EOF # Создание systemd сервиса echo "⚙️ Создание systemd сервиса..." cat > /etc/systemd/system/my-network-bootstrap.service << EOF [Unit] Description=MY Network Bootstrap Node After=network.target docker.service Requires=docker.service [Service] Type=simple User=root WorkingDirectory=$PROJECT_DIR/my-uploader-bot Environment=PATH=$PROJECT_DIR/my-uploader-bot/venv/bin ExecStart=$PROJECT_DIR/my-uploader-bot/venv/bin/python app/main.py Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF # Установка Python зависимостей echo "🐍 Установка Python зависимостей..." python3 -m venv venv source venv/bin/activate pip install --upgrade pip pip install -r requirements_new.txt # Запуск Docker сервисов echo "🐳 Запуск Docker сервисов..." docker-compose -f docker-compose.new.yml up -d # Ожидание БД echo "⏳ Ожидание запуска базы данных..." sleep 30 # Настройка Nginx с Cloudflare echo "🌐 Настройка Nginx..." cat > /etc/nginx/sites-available/my-network-bootstrap << EOF server { listen 80; server_name $DOMAIN; return 301 https://\$server_name\$request_uri; } server { listen 443 ssl http2; server_name $DOMAIN; # SSL будет настроен certbot'ом ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem; # Cloudflare IP ranges set_real_ip_from 173.245.48.0/20; set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 108.162.192.0/18; set_real_ip_from 190.93.240.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 162.158.0.0/15; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 172.64.0.0/13; set_real_ip_from 131.0.72.0/22; real_ip_header CF-Connecting-IP; # Security headers add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Referrer-Policy "strict-origin-when-cross-origin"; add_header X-MY-Network-Node-Type "bootstrap"; add_header X-MY-Network-Version "2.0"; server_tokens off; # Rate limiting limit_req_zone \$binary_remote_addr zone=api:10m rate=100r/s; limit_req_zone \$binary_remote_addr zone=monitor:10m rate=10r/s; # Bootstrap API endpoints (публичные) location /api/my/ { limit_req zone=api burst=200 nodelay; proxy_pass http://127.0.0.1:15100; 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; # CORS headers add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization"; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; if (\$request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization"; add_header Content-Length 0; add_header Content-Type text/plain; return 200; } } # Monitor (ограниченный доступ) location /api/my/monitor { limit_req zone=monitor burst=10 nodelay; allow 127.0.0.1; allow ::1; deny all; proxy_pass http://127.0.0.1:15100; 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; } # Redirect root to health location = / { return 301 /api/my/health; } # Block sensitive paths location ~ /\.(?!well-known) { deny all; } location ~ ^/(config|\.env|requirements|docker-compose) { deny all; } } EOF # Активация сайта ln -sf /etc/nginx/sites-available/my-network-bootstrap /etc/nginx/sites-enabled/ rm -f /etc/nginx/sites-enabled/default # Проверка конфигурации nginx nginx -t # Запуск приложения echo "🚀 Запуск MY Network сервиса..." systemctl daemon-reload systemctl enable my-network-bootstrap systemctl start my-network-bootstrap # Ожидание запуска приложения echo "⏳ Ожидание запуска приложения..." sleep 10 # Получение SSL сертификата echo "🔐 Получение SSL сертификата..." certbot --nginx -d $DOMAIN --email $EMAIL --agree-tos --non-interactive --redirect # Настройка firewall (ТОЛЬКО 443!) echo "🔥 Настройка firewall - ТОЛЬКО порт 443..." ufw --force reset ufw default deny incoming ufw default allow outgoing # SSH (определяем текущий порт) SSH_PORT=$(ss -tlnp | grep sshd | grep -o ':[0-9]*' | head -1 | cut -d: -f2) if [[ -n "$SSH_PORT" ]]; then echo "🔑 Разрешение SSH на порту $SSH_PORT" ufw allow $SSH_PORT/tcp comment 'SSH Access' fi # HTTP и HTTPS для Cloudflare ufw allow 80/tcp comment 'HTTP Redirect' ufw allow 443/tcp comment 'HTTPS Only' # Блокируем прямой доступ к приложению ufw deny 15100 comment 'Block direct app access' ufw deny 3306 comment 'Block MySQL access' ufw deny 6379 comment 'Block Redis access' ufw --force enable # Настройка fail2ban echo "🚫 Настройка fail2ban..." cat > /etc/fail2ban/jail.local << EOF [DEFAULT] bantime = 3600 findtime = 600 maxretry = 5 [sshd] enabled = true port = $SSH_PORT filter = sshd logpath = /var/log/auth.log [nginx-http-auth] enabled = true filter = nginx-http-auth logpath = /var/log/nginx/error.log [nginx-limit-req] enabled = true filter = nginx-limit-req logpath = /var/log/nginx/error.log maxretry = 10 EOF systemctl enable fail2ban systemctl start fail2ban # Запуск nginx systemctl enable nginx systemctl start nginx # Настройка мониторинга echo "📊 Настройка мониторинга..." cat > /opt/bootstrap-monitor.sh << 'MONITOR_EOF' #!/bin/bash LOG_FILE="/opt/logs/bootstrap-monitor.log" DATE=$(date '+%Y-%m-%d %H:%M:%S') # Check services BOOTSTRAP_STATUS=$(systemctl is-active my-network-bootstrap) NGINX_STATUS=$(systemctl is-active nginx) DOCKER_STATUS=$(systemctl is-active docker) # Check API API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://my-public-node-3.projscale.dev/api/my/health 2>/dev/null || echo "FAIL") # System stats DISK_USAGE=$(df -h /opt | awk 'NR==2 {print $5}' | sed 's/%//') MEM_USAGE=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}') CPU_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//') # Log status echo "[$DATE] Bootstrap: $BOOTSTRAP_STATUS, Nginx: $NGINX_STATUS, Docker: $DOCKER_STATUS, API: $API_STATUS, Disk: ${DISK_USAGE}%, Mem: ${MEM_USAGE}%, Load: $CPU_LOAD" >> $LOG_FILE # Alert if critical if [[ "$BOOTSTRAP_STATUS" != "active" || "$NGINX_STATUS" != "active" || "$DOCKER_STATUS" != "active" || "$API_STATUS" != "200" ]]; then echo "[$DATE] ALERT: Bootstrap node critical issue detected!" >> $LOG_FILE fi MONITOR_EOF chmod +x /opt/bootstrap-monitor.sh # Добавление в cron (crontab -l 2>/dev/null; echo "*/2 * * * * /opt/bootstrap-monitor.sh") | crontab - (crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab - # Финальная проверка echo "🔍 Финальная проверка системы..." sleep 10 echo "" echo "📊 Статус сервисов:" systemctl status my-network-bootstrap --no-pager -l | head -10 echo "" systemctl status nginx --no-pager -l | head -10 echo "" echo "🔥 Firewall статус:" ufw status numbered echo "" echo "🌐 Проверка API:" curl -s -I https://$DOMAIN/api/my/health || echo "API недоступен" echo "" echo "🔐 SSL сертификаты:" certbot certificates echo "" echo "🌍 Открытые порты:" netstat -tlnp | grep LISTEN # Создание итогового отчета cat > /opt/bootstrap-deployment-report.txt << EOF MY Network Bootstrap Node - Отчет о развертывании =============================================== Время развертывания: $(date) Домен: $DOMAIN Сервер: $(hostname -I | awk '{print $1}') ✅ УСПЕШНО РАЗВЕРНУТО: - MY Network Bootstrap Node (версия 2.0) - Nginx proxy с SSL (порт 443 только) - MariaDB и Redis в Docker - UFW Firewall (SSH + 443 только) - Fail2ban защита - Автоматический мониторинг - SSL сертификат Let's Encrypt 🌐 ДОСТУПНЫЕ ENDPOINTS: - Health Check: https://$DOMAIN/api/my/health - Node Info: https://$DOMAIN/api/my/node/info - Bootstrap Config: https://$DOMAIN/api/my/bootstrap/config - Monitor Dashboard: https://$DOMAIN/api/my/monitor/ (localhost only) 🔧 УПРАВЛЕНИЕ: - Статус: systemctl status my-network-bootstrap nginx docker - Логи: journalctl -u my-network-bootstrap -f - Монитор: tail -f /opt/logs/bootstrap-monitor.log - Firewall: ufw status - SSL: certbot certificates 🔒 БЕЗОПАСНОСТЬ: - Открыт только порт 443 (HTTPS) - Все внутренние сервисы заблокированы - SSL шифрование обязательно - Rate limiting активен - Fail2ban защита от атак 📂 ФАЙЛЫ КОНФИГУРАЦИИ: - $PROJECT_DIR/my-uploader-bot/.env - $PROJECT_DIR/my-uploader-bot/bootstrap.json - /etc/nginx/sites-available/my-network-bootstrap - /etc/systemd/system/my-network-bootstrap.service Bootstrap узел готов к работе как основной узел сети! EOF echo "" echo "✅ MY Network Bootstrap Node развернут успешно!" echo "==============================================" echo "🌐 Домен: https://$DOMAIN" echo "🔐 SSL: Активен и настроен" echo "🔥 Firewall: Только порт 443 открыт" echo "🚀 Статус: Bootstrap узел активен" echo "📊 Мониторинг: Каждые 2 минуты" echo "" echo "🔍 Проверьте работу:" echo " curl https://$DOMAIN/api/my/health" echo " curl https://$DOMAIN/api/my/node/info" echo " curl https://$DOMAIN/api/my/bootstrap/config" echo "" echo "📄 Полный отчет: /opt/bootstrap-deployment-report.txt" echo "" echo "🎯 Bootstrap узел готов принимать подключения других узлов!" # Конец скрипта exit 0