#!/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