REFACTORING DIRECTORIES

This commit is contained in:
user committed 2025-07-05 20:02:00 +03:00
1 parent c645019380
commit c8e1d5046c
54 files changed
+6193 -747

No files matched your search

+772
View File
@@ -0,0 +1,772 @@
#!/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 = """
<!DOCTYPE html>
<html>
<head>
<title>MY Network Bootstrap Monitor</title>
<style>
body { font-family: monospace; background: #000; color: #0f0; margin: 20px; }
h1 { color: #ff0; text-align: center; }
.status { margin: 10px 0; padding: 10px; border: 1px solid #0f0; }
.healthy { border-color: #0f0; }
.error { border-color: #f00; color: #f00; }
</style>
</head>
<body>
<h1>🚀 MY Network Bootstrap Node</h1>
<div class="status healthy">
<h3>Node Status: ACTIVE</h3>
<p>Node ID: """ + NODE_ID + """</p>
<p>Domain: """ + DOMAIN + """</p>
<p>Type: Bootstrap Primary</p>
<p>Services: API, Sync, Monitor, Storage</p>
</div>
<div class="status healthy">
<h3>Network Status</h3>
<p>Protocol Version: 2.0</p>
<p>Max Peers: 100</p>
<p>Public Access: Enabled</p>
<p>SSL: Enabled</p>
</div>
<script>
setInterval(() => location.reload(), 30000);
</script>
</body>
</html>
"""
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
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/expect -f
set timeout 1800
set password "DMUEjmnh6mDs/qlzhpjDzQ"
set server "2.58.65.188"
log_user 1
spawn ssh -o StrictHostKeyChecking=no service@$server
expect {
"password:" {
send "$password\r"
exp_continue
}
"$ " {
# Переход в root
send "sudo su -\r"
expect {
"password:" {
send "$password\r"
expect "# "
}
"# " {
# Уже root
}
}
# Проверка и запуск скрипта
send "ls -la /tmp/auto_deploy.sh\r"
expect "# "
send "chmod +x /tmp/auto_deploy.sh\r"
expect "# "
send "echo 'Starting MY Network Bootstrap deployment...'\r"
expect "# "
# Запуск скрипта развертывания
send "/tmp/auto_deploy.sh\r"
# Ожидаем завершения установки (до 30 минут)
expect {
"Bootstrap узел готов к работе!" {
send "echo 'Deployment completed successfully!'\r"
expect "# "
# Проверка результата
send "systemctl status my-network-bootstrap --no-pager\r"
expect "# "
send "curl -s https://my-public-node-3.projscale.dev/api/my/health || echo 'API check failed'\r"
expect "# "
send "ufw status numbered\r"
expect "# "
send "echo 'MY Network Bootstrap Node deployed successfully!'\r"
expect "# "
interact
}
"error" {
send "echo 'Deployment error occurred'\r"
interact
}
timeout {
send "echo 'Deployment timeout - checking status...'\r"
send "systemctl status my-network-bootstrap nginx docker\r"
interact
}
}
}
timeout {
puts "Connection timeout"
exit 1
}
eof {
puts "Connection closed"
exit 1
}
}
+546
View File
@@ -0,0 +1,546 @@
#!/bin/bash
# MY Network Bootstrap Node Deployment Script
# Домен: my-public-node-3.projscale.dev
# Сервер: 2.58.65.188
# Только порт 443 наружу через nginx proxy
set -e
echo "🚀 MY Network Bootstrap Node Deployment"
echo "======================================="
echo "Домен: my-public-node-3.projscale.dev"
echo "Сервер: 2.58.65.188"
echo "Режим: Bootstrap Node (Primary)"
echo ""
# Проверка прав root
if [[ $EUID -ne 0 ]]; then
echo "❌ Этот скрипт должен запускаться от root"
echo "Используйте: sudo bash deploy_bootstrap_node.sh"
exit 1
fi
DOMAIN="my-public-node-3.projscale.dev"
EMAIL="admin@projscale.dev"
NODE_TYPE="bootstrap"
echo "📋 Конфигурация Bootstrap узла:"
echo " Домен: $DOMAIN"
echo " Email: $EMAIL"
echo " Тип: $NODE_TYPE"
echo " Внешний порт: 443 (HTTPS только)"
echo " Внутренний порт: 15100"
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
# Настройка Docker
echo "🐳 Настройка Docker..."
systemctl enable docker
systemctl start docker
usermod -aG docker service
# Создание структуры проекта
echo "📁 Создание структуры проекта..."
PROJECT_DIR="/opt/my-network"
mkdir -p $PROJECT_DIR
cd $PROJECT_DIR
# Создание директорий
mkdir -p /opt/storage /opt/logs
chmod 755 /opt/storage /opt/logs
chown service:service /opt/storage /opt/logs
# Клонирование проекта (тут будет запрос git pull)
echo "📥 Настройка проекта..."
echo "ТРЕБУЕТСЯ: Выполните команду git clone или скопируйте проект в $PROJECT_DIR/my-uploader-bot/"
echo "После этого продолжите выполнение скрипта"
read -p "Нажмите Enter когда проект будет готов..."
cd my-uploader-bot
# Создание конфигурации
echo "📝 Создание конфигурации bootstrap узла..."
cat > .env << EOF
# MY Network Bootstrap Node Configuration
NODE_ID=bootstrap-node-$(date +%s)
NODE_TYPE=bootstrap
NODE_PORT=15100
DOMAIN=$DOMAIN
EMAIL=$EMAIL
# Network Configuration
IS_BOOTSTRAP=true
BOOTSTRAP_NODES=[]
MAX_PEERS=50
SYNC_INTERVAL=300
# 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)
# Storage
STORAGE_PATH=/opt/storage
LOG_PATH=/opt/logs
# API Settings
API_RATE_LIMIT=100
MONITOR_RATE_LIMIT=10
ENABLE_PUBLIC_API=true
EOF
# Создание bootstrap.json конфигурации
echo "🌐 Создание bootstrap конфигурации..."
cat > bootstrap.json << EOF
{
"version": "2.0",
"network_id": "my-network-main",
"bootstrap_nodes": [
{
"id": "bootstrap-node-primary",
"host": "$DOMAIN",
"port": 443,
"ssl": true,
"public": true,
"region": "eu-central",
"capacity": "high",
"services": ["api", "sync", "monitor", "storage"]
}
],
"network_config": {
"protocol_version": "2.0",
"sync_interval": 300,
"max_peers": 50,
"chunk_size": 1048576,
"compression": true,
"encryption": true
},
"api_endpoints": {
"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
# Установка Python зависимостей
echo "🐍 Установка Python зависимостей..."
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements_new.txt
# Настройка базы данных
echo "🗄️ Запуск Docker сервисов..."
docker-compose -f docker-compose.new.yml up -d
# Ожидание запуска БД
echo "⏳ Ожидание запуска базы данных..."
sleep 30
# Создание 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=service
Group=service
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
# Настройка Nginx для Cloudflare
echo "🌐 Настройка Nginx для Cloudflare..."
cat > /etc/nginx/sites-available/my-network-bootstrap << EOF
# MY Network Bootstrap Node - Cloudflare Compatible
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
# SSL Configuration для Cloudflare
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";
# Bootstrap Node specific headers
add_header X-MY-Network-Node-Type "bootstrap";
add_header X-MY-Network-Version "2.0";
server_tokens off;
# Rate limiting для bootstrap узла
limit_req_zone \$binary_remote_addr zone=bootstrap_api:10m rate=100r/s;
limit_req_zone \$binary_remote_addr zone=bootstrap_monitor:10m rate=10r/s;
limit_req_zone \$binary_remote_addr zone=bootstrap_sync:10m rate=50r/s;
# Bootstrap configuration endpoint (публичный)
location /api/my/bootstrap/ {
limit_req zone=bootstrap_api burst=50 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;
proxy_set_header X-MY-Network-Bootstrap "true";
# CORS для bootstrap API
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
# Health check endpoint (публичный)
location /api/my/health {
limit_req zone=bootstrap_api burst=20 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;
add_header Access-Control-Allow-Origin "*";
}
# Node info (публичный для discovery)
location /api/my/node/info {
limit_req zone=bootstrap_api burst=30 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;
add_header Access-Control-Allow-Origin "*";
}
# Sync endpoints (для других узлов)
location /api/my/sync/ {
limit_req zone=bootstrap_sync burst=100 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;
# Увеличенные таймауты для синхронизации
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# Main API
location /api/my/ {
limit_req zone=bootstrap_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;
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;
}
# Monitoring interface (защищенный)
location /api/my/monitor {
limit_req zone=bootstrap_monitor burst=10 nodelay;
# Разрешить только определенным IP (настроить по необходимости)
allow 127.0.0.1;
allow ::1;
# allow YOUR_ADMIN_IP;
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;
}
# Static files
location /static/ {
alias $PROJECT_DIR/my-uploader-bot/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Блокировка чувствительных путей
location ~ /\.(?!well-known) {
deny all;
}
location ~ ^/(config|\.env|requirements|docker-compose) {
deny all;
}
# Root redirect to monitor
location = / {
return 301 /api/my/monitor/;
}
}
EOF
# Активация nginx конфигурации
ln -sf /etc/nginx/sites-available/my-network-bootstrap /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Проверка nginx конфигурации
nginx -t
# Получение 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'
fi
# ТОЛЬКО HTTP и HTTPS для Cloudflare
ufw allow 80/tcp comment 'HTTP for Cloudflare'
ufw allow 443/tcp comment 'HTTPS for Cloudflare'
# Блокируем прямой доступ к приложению
ufw deny 15100 comment 'Block direct app access'
ufw --force enable
# Настройка fail2ban
echo "🚫 Настройка fail2ban..."
apt install -y 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
# Запуск сервисов
echo "🚀 Запуск сервисов..."
systemctl daemon-reload
systemctl enable my-network-bootstrap
systemctl start my-network-bootstrap
systemctl enable nginx
systemctl start nginx
# Создание мониторинг скрипта
echo "📊 Настройка мониторинга..."
cat > /opt/bootstrap-monitor.sh << '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 || echo "FAIL")
# Check disk space
DISK_USAGE=$(df -h /opt | awk 'NR==2 {print $5}' | sed 's/%//')
# Log status
echo "[$DATE] Bootstrap: $BOOTSTRAP_STATUS, Nginx: $NGINX_STATUS, Docker: $DOCKER_STATUS, API: $API_STATUS, Disk: ${DISK_USAGE}%" >> $LOG_FILE
# Alert if critical
if [[ "$BOOTSTRAP_STATUS" != "active" || "$NGINX_STATUS" != "active" || "$DOCKER_STATUS" != "active" || "$API_STATUS" != "200" ]]; then
echo "[$DATE] ALERT: Bootstrap node has critical issues!" >> $LOG_FILE
fi
EOF
chmod +x /opt/bootstrap-monitor.sh
# Добавить в cron
(crontab -l 2>/dev/null; echo "*/2 * * * * /opt/bootstrap-monitor.sh") | crontab -
# Настройка автообновления SSL
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
# Финальная проверка
echo "🔍 Финальная проверка bootstrap узла..."
sleep 10
echo "📊 Статус сервисов:"
systemctl status my-network-bootstrap --no-pager -l
systemctl status nginx --no-pager -l
systemctl status docker --no-pager -l
echo "🔥 Статус firewall:"
ufw status numbered
echo "🌐 Проверка API:"
curl -s https://$DOMAIN/api/my/health || echo "API недоступен"
echo "🔐 SSL сертификаты:"
certbot certificates
# Сохранение конфигурации
cat > /opt/bootstrap-node-config.txt << EOF
MY Network Bootstrap Node - Конфигурация
=======================================
Домен: $DOMAIN
Тип: Bootstrap Node (Primary)
Внешний порт: 443 (HTTPS only)
Внутренний порт: 15100
Cloudflare: Enabled
Статус сервисов:
systemctl status my-network-bootstrap nginx docker fail2ban
Логи:
journalctl -u my-network-bootstrap -f
tail -f /opt/logs/bootstrap-monitor.log
API Endpoints:
https://$DOMAIN/api/my/health
https://$DOMAIN/api/my/node/info
https://$DOMAIN/api/my/bootstrap/config
https://$DOMAIN/api/my/monitor/ (restricted)
Конфигурационные файлы:
$PROJECT_DIR/my-uploader-bot/.env
$PROJECT_DIR/my-uploader-bot/bootstrap.json
EOF
echo ""
echo "✅ MY Network Bootstrap Node развернут!"
echo "======================================="
echo "🌐 Домен: https://$DOMAIN"
echo "🔐 SSL: Активен"
echo "🔥 Firewall: Только порт 443"
echo "🌍 Cloudflare: Совместимость включена"
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-node-config.txt"
echo ""
echo "🎯 Bootstrap узел готов к работе!"
+718
View File
@@ -0,0 +1,718 @@
#!/bin/bash
# MY Network Production Deployment Script
# Скрипт для развертывания MY Network с nginx, SSL и полной инфраструктурой
set -e # Выход при ошибке
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# ASCII Art заставка
print_header() {
echo -e "${CYAN}"
cat << "EOF"
╔══════════════════════════════════════════════════════════════════════════════╗
║ MY NETWORK v2.0 ║
║ Production Deployment Script ║
║ Distributed Content Protocol Installer ║
╚══════════════════════════════════════════════════════════════════════════════╝
EOF
echo -e "${NC}"
}
# Логирование
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
# Конфигурационные переменные
DOMAIN=${DOMAIN:-"my-network.local"}
EMAIL=${EMAIL:-"admin@${DOMAIN}"}
HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443}
APP_PORT=${APP_PORT:-15100}
REDIS_PORT=${REDIS_PORT:-6379}
DB_PORT=${DB_PORT:-3306}
# Проверка прав root
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
}
# Проверка операционной системы
check_os() {
log_step "Checking operating system..."
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
log_info "Detected OS: $OS $VER"
else
log_error "Cannot detect operating system"
exit 1
fi
}
# Установка зависимостей
install_dependencies() {
log_step "Installing system dependencies..."
if [[ "$OS" == *"Ubuntu"* ]] || [[ "$OS" == *"Debian"* ]]; then
apt update
apt install -y \
nginx \
certbot \
python3-certbot-nginx \
docker.io \
docker-compose \
curl \
wget \
git \
htop \
ufw \
fail2ban
elif [[ "$OS" == *"CentOS"* ]] || [[ "$OS" == *"Red Hat"* ]]; then
yum update -y
yum install -y \
nginx \
certbot \
python3-certbot-nginx \
docker \
docker-compose \
curl \
wget \
git \
htop \
firewalld
else
log_warn "Unsupported OS, attempting generic installation..."
fi
# Запустить Docker
systemctl enable docker
systemctl start docker
log_info "Dependencies installed successfully"
}
# Настройка файрвола
setup_firewall() {
log_step "Configuring firewall..."
if command -v ufw &> /dev/null; then
# Ubuntu/Debian firewall
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
# Разрешить SSH
ufw allow 22/tcp
# Разрешить HTTP/HTTPS
ufw allow $HTTP_PORT/tcp
ufw allow $HTTPS_PORT/tcp
# Разрешить порт приложения
ufw allow $APP_PORT/tcp
# MY Network P2P порты
ufw allow 8000:8010/tcp
ufw allow 8000:8010/udp
ufw --force enable
elif command -v firewall-cmd &> /dev/null; then
# CentOS/RHEL firewall
systemctl enable firewalld
systemctl start firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=$APP_PORT/tcp
firewall-cmd --permanent --add-port=8000-8010/tcp
firewall-cmd --permanent --add-port=8000-8010/udp
firewall-cmd --reload
fi
log_info "Firewall configured successfully"
}
# Создание пользователя для приложения
create_app_user() {
log_step "Creating application user..."
if ! id "my-network" &>/dev/null; then
useradd -r -s /bin/false -d /opt/my-network -m my-network
usermod -aG docker my-network
log_info "User 'my-network' created"
else
log_info "User 'my-network' already exists"
fi
}
# Настройка директорий
setup_directories() {
log_step "Setting up directories..."
# Создать основные директории
mkdir -p /opt/my-network/{app,data,logs,storage,config,ssl}
mkdir -p /var/log/my-network
# Создать директории для хранения
mkdir -p /opt/my-network/storage/{uploads,previews,encrypted,my-network}
# Права доступа
chown -R my-network:my-network /opt/my-network
chown -R my-network:my-network /var/log/my-network
chmod 755 /opt/my-network
chmod 750 /opt/my-network/config
chmod 700 /opt/my-network/ssl
log_info "Directories configured successfully"
}
# Копирование файлов приложения
deploy_application() {
log_step "Deploying MY Network application..."
# Копировать исходники
cp -r . /opt/my-network/app/
# Установить права
chown -R my-network:my-network /opt/my-network/app
# Создать .env файл для продакшена
cat > /opt/my-network/app/.env << EOF
# MY Network Production Configuration
PROJECT_NAME=MY-Network
PROJECT_VERSION=2.0.0
DEBUG=False
ENVIRONMENT=production
# Database Configuration
DATABASE_URL=mysql://mymusic:mymusic_password@localhost:$DB_PORT/mymusic
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=30
# Redis Configuration
REDIS_URL=redis://localhost:$REDIS_PORT/0
REDIS_PASSWORD=
# Application Settings
SECRET_KEY=$(openssl rand -hex 32)
MAX_FILE_SIZE=5368709120
STORAGE_PATH=/opt/my-network/storage
# MY Network Settings
MY_NETWORK_ENABLED=True
MY_NETWORK_NODE_ID=$(uuidgen)
MY_NETWORK_BOOTSTRAP_NODES=[]
MY_NETWORK_P2P_PORT=8001
MY_NETWORK_API_PORT=$APP_PORT
# SSL Settings
SSL_ENABLED=True
SSL_CERT_PATH=/opt/my-network/ssl/fullchain.pem
SSL_KEY_PATH=/opt/my-network/ssl/privkey.pem
# Logging
LOG_LEVEL=INFO
LOG_FILE=/var/log/my-network/app.log
# Monitoring
METRICS_ENABLED=True
PROMETHEUS_PORT=9090
EOF
log_info "Application deployed successfully"
}
# Настройка nginx
setup_nginx() {
log_step "Configuring nginx..."
# Создать конфигурацию nginx
cat > /etc/nginx/sites-available/my-network << EOF
# MY Network Nginx Configuration
upstream my_network_backend {
server 127.0.0.1:$APP_PORT;
keepalive 32;
}
# HTTP -> HTTPS redirect
server {
listen $HTTP_PORT;
server_name $DOMAIN;
# Для Let's Encrypt challenge
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# Редирект на HTTPS
location / {
return 301 https://\$server_name\$request_uri;
}
}
# HTTPS сервер
server {
listen $HTTPS_PORT ssl http2;
server_name $DOMAIN;
# SSL сертификаты
ssl_certificate /opt/my-network/ssl/fullchain.pem;
ssl_certificate_key /opt/my-network/ssl/privkey.pem;
# SSL настройки
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Безопасность
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Основное приложение
location / {
proxy_pass http://my_network_backend;
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;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
proxy_read_timeout 86400;
# Ограничения
client_max_body_size 5G;
proxy_request_buffering off;
}
# MY Network мониторинг
location /api/my/monitor/ {
proxy_pass http://my_network_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
# Разрешить для всех
allow all;
}
# Статические файлы
location /static/ {
alias /opt/my-network/storage/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Логи
access_log /var/log/nginx/my-network-access.log;
error_log /var/log/nginx/my-network-error.log;
}
EOF
# Включить сайт
ln -sf /etc/nginx/sites-available/my-network /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Проверить конфигурацию
nginx -t
log_info "Nginx configured successfully"
}
# Получение SSL сертификата
setup_ssl() {
log_step "Setting up SSL certificate..."
# Запустить nginx для получения сертификата
systemctl start nginx
# Получить сертификат Let's Encrypt
if certbot --nginx -d $DOMAIN --email $EMAIL --agree-tos --non-interactive --redirect; then
log_info "SSL certificate obtained successfully"
# Копировать сертификаты в нашу директорию
cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem /opt/my-network/ssl/
cp /etc/letsencrypt/live/$DOMAIN/privkey.pem /opt/my-network/ssl/
chown my-network:my-network /opt/my-network/ssl/*
# Настроить автообновление
echo "0 3 * * * /usr/bin/certbot renew --quiet && systemctl reload nginx" | crontab -
else
log_warn "Failed to obtain SSL certificate, generating self-signed..."
# Создать самоподписанный сертификат
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/my-network/ssl/privkey.pem \
-out /opt/my-network/ssl/fullchain.pem \
-subj "/C=US/ST=State/L=City/O=Organization/CN=$DOMAIN"
chown my-network:my-network /opt/my-network/ssl/*
fi
}
# Создание docker-compose для продакшена
create_docker_compose() {
log_step "Creating production docker-compose..."
cat > /opt/my-network/docker-compose.prod.yml << EOF
version: '3.8'
services:
# MariaDB Database
mariadb:
image: mariadb:11.2
container_name: my-network-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: \${MYSQL_ROOT_PASSWORD:-root_password}
MYSQL_DATABASE: mymusic
MYSQL_USER: mymusic
MYSQL_PASSWORD: \${MYSQL_PASSWORD:-mymusic_password}
volumes:
- /opt/my-network/data/mysql:/var/lib/mysql
- /opt/my-network/storage:/Storage
ports:
- "127.0.0.1:$DB_PORT:3306"
networks:
- my-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
timeout: 10s
retries: 5
# Redis Cache
redis:
image: redis:7-alpine
container_name: my-network-redis
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- /opt/my-network/data/redis:/data
ports:
- "127.0.0.1:$REDIS_PORT:6379"
networks:
- my-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
# MY Network Application
my-network-app:
build:
context: /opt/my-network/app
dockerfile: Dockerfile.prod
container_name: my-network-app
restart: unless-stopped
environment:
- ENVIRONMENT=production
volumes:
- /opt/my-network/app:/app
- /opt/my-network/storage:/Storage
- /opt/my-network/ssl:/ssl:ro
- /var/log/my-network:/var/log/my-network
ports:
- "127.0.0.1:$APP_PORT:$APP_PORT"
- "$((APP_PORT + 1)):$((APP_PORT + 1))" # P2P порт
networks:
- my-network
depends_on:
mariadb:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:$APP_PORT/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
my-network:
driver: bridge
volumes:
mysql_data:
redis_data:
EOF
# Создать Dockerfile для продакшена
cat > /opt/my-network/app/Dockerfile.prod << EOF
FROM python:3.11-slim
# Установить системные зависимости
RUN apt-get update && apt-get install -y \\
gcc \\
g++ \\
libmariadb-dev \\
pkg-config \\
curl \\
&& rm -rf /var/lib/apt/lists/*
# Создать пользователя приложения
RUN useradd -r -s /bin/false -d /app mynetwork
# Установить зависимости Python
WORKDIR /app
COPY requirements_new.txt .
RUN pip install --no-cache-dir -r requirements_new.txt
# Копировать приложение
COPY . .
RUN chown -R mynetwork:mynetwork /app
# Создать директории
RUN mkdir -p /var/log/my-network && \\
chown mynetwork:mynetwork /var/log/my-network
USER mynetwork
# Порты
EXPOSE $APP_PORT $((APP_PORT + 1))
# Команда запуска
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "$APP_PORT"]
EOF
log_info "Docker configuration created successfully"
}
# Создание systemd сервиса
create_systemd_service() {
log_step "Creating systemd service..."
cat > /etc/systemd/system/my-network.service << EOF
[Unit]
Description=MY Network Distributed Protocol Service
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/my-network
ExecStart=/usr/bin/docker-compose -f docker-compose.prod.yml up -d
ExecStop=/usr/bin/docker-compose -f docker-compose.prod.yml down
User=my-network
Group=my-network
[Install]
WantedBy=multi-user.target
EOF
# Перезагрузить systemd и запустить сервис
systemctl daemon-reload
systemctl enable my-network
log_info "Systemd service created successfully"
}
# Настройка мониторинга
setup_monitoring() {
log_step "Setting up monitoring..."
# Создать скрипт проверки здоровья
cat > /opt/my-network/health_check.sh << 'EOF'
#!/bin/bash
# MY Network Health Check Script
DOMAIN="localhost"
PORT="15100"
LOG_FILE="/var/log/my-network/health.log"
# Функция логирования
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
}
# Проверка HTTP эндпоинта
check_http() {
if curl -f -s "http://$DOMAIN:$PORT/health" > /dev/null; then
return 0
else
return 1
fi
}
# Проверка MY Network
check_my_network() {
if curl -f -s "http://$DOMAIN:$PORT/api/my/health" > /dev/null; then
return 0
else
return 1
fi
}
# Основная проверка
if check_http && check_my_network; then
log_message "Health check PASSED"
exit 0
else
log_message "Health check FAILED"
# Попытаться перезапустить сервис
systemctl restart my-network
log_message "Service restart attempted"
exit 1
fi
EOF
chmod +x /opt/my-network/health_check.sh
chown my-network:my-network /opt/my-network/health_check.sh
# Добавить в cron для мониторинга каждые 5 минут
echo "*/5 * * * * /opt/my-network/health_check.sh" | crontab -u my-network -
log_info "Monitoring configured successfully"
}
# Запуск всех сервисов
start_services() {
log_step "Starting all services..."
# Запустить nginx
systemctl enable nginx
systemctl restart nginx
# Запустить MY Network
systemctl start my-network
# Подождать запуска
sleep 10
# Проверить статус
if systemctl is-active --quiet my-network; then
log_info "MY Network service is running"
else
log_error "MY Network service failed to start"
systemctl status my-network
exit 1
fi
if systemctl is-active --quiet nginx; then
log_info "Nginx service is running"
else
log_error "Nginx service failed to start"
systemctl status nginx
exit 1
fi
}
# Финальная информация
print_summary() {
echo -e "${GREEN}"
cat << EOF
╔══════════════════════════════════════════════════════════════════════════════╗
║ MY NETWORK DEPLOYMENT COMPLETED ║
╚══════════════════════════════════════════════════════════════════════════════╝
🌐 Web Interface: https://$DOMAIN
📊 Monitoring: https://$DOMAIN/api/my/monitor/
🔧 API Documentation: https://$DOMAIN/api/docs
❤️ Health Check: https://$DOMAIN/health
📝 Configuration Files:
• Application: /opt/my-network/app/.env
• Nginx: /etc/nginx/sites-available/my-network
• Docker: /opt/my-network/docker-compose.prod.yml
• SSL: /opt/my-network/ssl/
📋 Management Commands:
• Start service: systemctl start my-network
• Stop service: systemctl stop my-network
• Restart service: systemctl restart my-network
• View logs: journalctl -u my-network -f
• Health check: /opt/my-network/health_check.sh
🔒 Security Features:
✅ SSL/TLS encryption
✅ Firewall configured
✅ Fail2ban protection
✅ Security headers
✅ Rate limiting
🚀 MY Network Features:
✅ Distributed content protocol
✅ P2P networking
✅ Content synchronization
✅ Load balancing
✅ Real-time monitoring
The system is now ready for production use!
EOF
echo -e "${NC}"
}
# Главная функция
main() {
print_header
log_info "Starting MY Network production deployment..."
check_root
check_os
install_dependencies
setup_firewall
create_app_user
setup_directories
deploy_application
setup_nginx
setup_ssl
create_docker_compose
create_systemd_service
setup_monitoring
start_services
print_summary
log_info "Deployment completed successfully!"
}
# Запуск скрипта
main "$@"
+190
View File
@@ -0,0 +1,190 @@
#!/bin/bash
# MY Uploader Bot - Диагностика 502 ошибки
# Автоматическая диагностика проблем с доступностью
DOMAIN="$1"
if [ -z "$DOMAIN" ]; then
echo "Использование: $0 <domain>"
echo "Пример: $0 my-public-node-3.projscale.dev"
exit 1
fi
MAIN_PROJECT_DIR="/home/myuploader/uploader-bot"
COMPOSE_FILE="docker-compose.production.yml"
# Цвета
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}🔍 MY UPLOADER BOT - ДИАГНОСТИКА 502${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
cd "$MAIN_PROJECT_DIR" 2>/dev/null || {
echo -e "${RED}❌ Не найдена директория проекта: $MAIN_PROJECT_DIR${NC}"
exit 1
}
echo -e "${YELLOW}1. 🐳 Проверка статуса Docker контейнеров${NC}"
echo "----------------------------------------"
docker-compose -f "$COMPOSE_FILE" ps
echo ""
echo -e "${YELLOW}2. 🔍 Проверка работающих контейнеров${NC}"
echo "----------------------------------------"
RUNNING_CONTAINERS=$(docker-compose -f "$COMPOSE_FILE" ps --services --filter "status=running")
if [ -z "$RUNNING_CONTAINERS" ]; then
echo -e "${RED}❌ НЕТ РАБОТАЮЩИХ КОНТЕЙНЕРОВ!${NC}"
echo -e "${YELLOW}Попробуйте запустить: sudo ./start.sh${NC}"
exit 1
else
echo -e "${GREEN}✅ Работающие контейнеры:${NC}"
echo "$RUNNING_CONTAINERS"
fi
echo ""
echo -e "${YELLOW}3. 🌐 Проверка доступности локальных портов${NC}"
echo "----------------------------------------"
echo -n "Порт 15100 (API): "
if curl -f -s http://localhost:15100/health > /dev/null 2>&1; then
echo -e "${GREEN}✅ Доступен${NC}"
API_STATUS="OK"
else
echo -e "${RED}❌ Недоступен${NC}"
API_STATUS="FAIL"
fi
echo -n "Порт 3000 (Web2-client): "
if curl -f -s http://localhost:3000/health > /dev/null 2>&1; then
echo -e "${GREEN}✅ Доступен${NC}"
WEB2_STATUS="OK"
else
echo -e "${YELLOW}⚠️ Недоступен (возможно, обычная нода)${NC}"
WEB2_STATUS="SKIP"
fi
echo -n "Порт 80 (Nginx): "
if curl -f -s http://localhost > /dev/null 2>&1; then
echo -e "${GREEN}✅ Доступен${NC}"
NGINX_STATUS="OK"
else
echo -e "${RED}❌ Недоступен${NC}"
NGINX_STATUS="FAIL"
fi
echo ""
echo -e "${YELLOW}4. 🗄️ Проверка базы данных${NC}"
echo "----------------------------------------"
echo -n "PostgreSQL: "
if docker-compose -f "$COMPOSE_FILE" exec -T postgres pg_isready -U my_user -d my_uploader_db 2>/dev/null; then
echo -e "${GREEN}✅ Доступна${NC}"
DB_STATUS="OK"
else
echo -e "${RED}❌ Недоступна${NC}"
DB_STATUS="FAIL"
fi
echo -n "Redis: "
if docker-compose -f "$COMPOSE_FILE" exec -T redis redis-cli ping 2>/dev/null | grep -q PONG; then
echo -e "${GREEN}✅ Доступен${NC}"
REDIS_STATUS="OK"
else
echo -e "${RED}❌ Недоступен${NC}"
REDIS_STATUS="FAIL"
fi
echo ""
echo -e "${YELLOW}5. 🔍 Последние логи основного приложения${NC}"
echo "----------------------------------------"
echo "Последние 10 строк логов app контейнера:"
docker-compose -f "$COMPOSE_FILE" logs --tail=10 app
echo ""
echo -e "${YELLOW}6. 🔍 Проверка nginx конфигурации${NC}"
echo "----------------------------------------"
echo -n "Nginx config test: "
if docker-compose -f "$COMPOSE_FILE" exec -T nginx nginx -t 2>/dev/null; then
echo -e "${GREEN}✅ Конфигурация корректна${NC}"
NGINX_CONFIG="OK"
else
echo -e "${RED}❌ Ошибка в конфигурации${NC}"
NGINX_CONFIG="FAIL"
echo "Детали ошибки:"
docker-compose -f "$COMPOSE_FILE" exec -T nginx nginx -t
fi
echo ""
echo -e "${YELLOW}7. 🌐 Проверка внешней доступности${NC}"
echo "----------------------------------------"
echo -n "HTTPS доступность ($DOMAIN): "
if curl -f -s -k "https://$DOMAIN/health" > /dev/null 2>&1; then
echo -e "${GREEN}✅ Доступен${NC}"
HTTPS_STATUS="OK"
else
echo -e "${RED}❌ Недоступен (502 ошибка)${NC}"
HTTPS_STATUS="FAIL"
fi
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}📊 СВОДКА ДИАГНОСТИКИ${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "API (localhost:15100): $([ "$API_STATUS" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $API_STATUS${NC}"
echo -e "Web2-client (localhost:3000): $([ "$WEB2_STATUS" = "OK" ] && echo -e "${GREEN}✅" || [ "$WEB2_STATUS" = "SKIP" ] && echo -e "${YELLOW}⚠️" || echo -e "${RED}❌") $WEB2_STATUS${NC}"
echo -e "Nginx (localhost:80): $([ "$NGINX_STATUS" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $NGINX_STATUS${NC}"
echo -e "PostgreSQL: $([ "$DB_STATUS" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $DB_STATUS${NC}"
echo -e "Redis: $([ "$REDIS_STATUS" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $REDIS_STATUS${NC}"
echo -e "Nginx Config: $([ "$NGINX_CONFIG" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $NGINX_CONFIG${NC}"
echo -e "HTTPS ($DOMAIN): $([ "$HTTPS_STATUS" = "OK" ] && echo -e "${GREEN}✅" || echo -e "${RED}❌") $HTTPS_STATUS${NC}"
echo ""
echo -e "${BLUE}🛠️ РЕКОМЕНДАЦИИ:${NC}"
if [ "$API_STATUS" != "OK" ]; then
echo -e "${RED}❌ Основная проблема: API приложение не работает${NC}"
echo -e "${YELLOW}Решение:${NC}"
echo "1. Проверьте логи приложения: sudo docker-compose -f $COMPOSE_FILE logs app"
echo "2. Перезапустите приложение: sudo docker-compose -f $COMPOSE_FILE restart app"
echo "3. Проверьте переменные окружения в .env файле"
echo ""
elif [ "$NGINX_CONFIG" != "OK" ]; then
echo -e "${RED}❌ Проблема в конфигурации Nginx${NC}"
echo -e "${YELLOW}Решение:${NC}"
echo "1. Проверьте конфигурацию nginx"
echo "2. Перезапустите nginx: sudo docker-compose -f $COMPOSE_FILE restart nginx"
echo ""
elif [ "$DB_STATUS" != "OK" ] || [ "$REDIS_STATUS" != "OK" ]; then
echo -e "${RED}❌ Проблема с базой данных или Redis${NC}"
echo -e "${YELLOW}Решение:${NC}"
echo "1. Перезапустите сервисы: sudo docker-compose -f $COMPOSE_FILE restart postgres redis"
echo "2. Проверьте логи: sudo docker-compose -f $COMPOSE_FILE logs postgres redis"
echo ""
else
echo -e "${GREEN}🔍 Все локальные сервисы работают корректно${NC}"
echo -e "${YELLOW}Возможные причины 502 ошибки:${NC}"
echo "1. Приложение еще запускается (подождите 2-3 минуты)"
echo "2. Проблема с SSL сертификатом"
echo "3. Неправильная конфигурация домена"
echo ""
echo -e "${BLUE}Дополнительная диагностика:${NC}"
echo "sudo docker-compose -f $COMPOSE_FILE logs -f app"
fi
echo -e "${BLUE}🔧 Быстрые команды для исправления:${NC}"
echo "# Полная перезагрузка всех сервисов:"
echo "sudo docker-compose -f $COMPOSE_FILE down && sudo docker-compose -f $COMPOSE_FILE up -d"
echo ""
echo "# Просмотр логов в реальном времени:"
echo "sudo docker-compose -f $COMPOSE_FILE logs -f"
echo ""
echo "# Перезапуск только основного приложения:"
echo "sudo docker-compose -f $COMPOSE_FILE restart app"
echo ""
echo "# Проверка статуса через 2 минуты:"
echo "sleep 120 && curl -v https://$DOMAIN/health"
+210
View File
@@ -0,0 +1,210 @@
#!/bin/bash
# MY Network Server Issues Fix Script
# Исправляет проблемы с nginx и контейнерами для проекта в /home/uploader-bot
set -e
echo "=============================================="
echo "MY NETWORK SERVER FIX SCRIPT"
echo "Время: $(date)"
echo "=============================================="
PROJECT_DIR="/home/uploader-bot"
echo "🔧 Проверяю проект в: $PROJECT_DIR"
if [ ! -d "$PROJECT_DIR" ]; then
echo "❌ Директория проекта не найдена: $PROJECT_DIR"
exit 1
fi
cd "$PROJECT_DIR"
echo "✅ Работаю в: $(pwd)"
if [ ! -f "docker-compose.production.yml" ]; then
echo "❌ docker-compose.production.yml не найден!"
exit 1
fi
echo "✅ Docker compose файл найден"
echo ""
echo "=== 1. СОЗДАНИЕ NGINX КОНФИГУРАЦИИ ==="
echo "🔧 Создаю правильную nginx конфигурацию..."
cat > /tmp/nginx_uploader.conf << 'EOF'
server {
listen 80;
server_name _;
# 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 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# Альтернативные порты для API
location /api5000/ {
proxy_pass http://localhost:5000/;
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;
}
# Health check
location /health {
proxy_pass http://localhost:3000/api/health;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Основная страница - пробуем API
location / {
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;
}
}
EOF
sudo mv /tmp/nginx_uploader.conf /etc/nginx/sites-available/default
sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
echo "✅ Nginx конфигурация создана"
echo ""
echo "=== 2. ПРОВЕРКА ТЕКУЩИХ КОНТЕЙНЕРОВ ==="
echo "Текущий статус контейнеров:"
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "=== 3. АНАЛИЗ ЛОГОВ ПРИЛОЖЕНИЯ ==="
# Найти контейнер приложения
APP_CONTAINER=$(docker ps --format "{{.Names}}" | grep -E "(app|uploader)" | head -1)
if [ -n "$APP_CONTAINER" ]; then
echo "📄 Логи контейнера $APP_CONTAINER (последние 15 строк):"
docker logs --tail=15 "$APP_CONTAINER" 2>&1 || echo "Не удалось получить логи"
else
echo "❌ Контейнер приложения не найден"
fi
echo ""
echo "=== 4. ПЕРЕЗАПУСК ПРОБЛЕМНЫХ КОНТЕЙНЕРОВ ==="
# Остановить только перезапускающиеся контейнеры
RESTARTING_CONTAINERS=$(docker ps -a --filter "status=restarting" --format "{{.Names}}")
if [ -n "$RESTARTING_CONTAINERS" ]; then
echo "🛑 Останавливаю перезапускающиеся контейнеры:"
echo "$RESTARTING_CONTAINERS"
echo "$RESTARTING_CONTAINERS" | xargs docker stop 2>/dev/null || true
echo "$RESTARTING_CONTAINERS" | xargs docker rm 2>/dev/null || true
else
echo "✅ Нет перезапускающихся контейнеров"
fi
# Удалить старые MariaDB контейнеры если есть
MARIADB_CONTAINERS=$(docker ps -a --format "{{.Names}}" | grep maria || true)
if [ -n "$MARIADB_CONTAINERS" ]; then
echo "🗑️ Удаляю старые MariaDB контейнеры:"
echo "$MARIADB_CONTAINERS" | xargs docker stop 2>/dev/null || true
echo "$MARIADB_CONTAINERS" | xargs docker rm 2>/dev/null || true
fi
echo ""
echo "=== 5. ЗАПУСК СЕРВИСОВ ==="
echo "🚀 Запуск Docker Compose..."
# Запуск основных сервисов
docker-compose -f docker-compose.production.yml up -d postgres redis
echo "⏳ Ждем запуска БД (10 секунд)..."
sleep 10
# Запуск приложения
echo "🚀 Запуск приложения..."
docker-compose -f docker-compose.production.yml up -d app
echo "⏳ Ждем запуска приложения (20 секунд)..."
sleep 20
echo ""
echo "=== 6. ПРОВЕРКА СТАТУСА ==="
echo "Новый статус контейнеров:"
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "=== 7. ТЕСТИРОВАНИЕ NGINX ==="
sudo nginx -t
if [ $? -eq 0 ]; then
sudo systemctl reload nginx
echo "✅ Nginx конфигурация корректна и перезагружена"
else
echo "❌ Ошибка в nginx конфигурации"
fi
echo ""
echo "=== 8. ПРОВЕРКА ПРИЛОЖЕНИЯ ==="
echo "Тест локальных соединений:"
sleep 5
# Проверка портов приложения
for port in 3000 5000; 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
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 "=== 9. ФИНАЛЬНЫЕ ЛОГИ ==="
APP_CONTAINER=$(docker ps --format "{{.Names}}" | grep -E "(app|uploader)" | head -1)
if [ -n "$APP_CONTAINER" ]; then
echo "📄 Финальные логи $APP_CONTAINER:"
docker logs --tail=10 "$APP_CONTAINER" 2>&1 || echo "Логи недоступны"
fi
echo ""
echo "=============================================="
echo "ИСПРАВЛЕНИЕ ЗАВЕРШЕНО!"
echo "Время: $(date)"
echo "=============================================="
echo ""
echo "📊 РЕЗУЛЬТАТ:"
echo "Проект: $PROJECT_DIR"
echo "Активные контейнеры:"
docker ps --format "{{.Names}}: {{.Status}}" | head -10
echo ""
echo "🌐 ВНЕШНИЙ ТЕСТ (выполните вручную):"
echo "curl -I http://$(curl -s ifconfig.me)/api/health"
echo "curl -I http://$(curl -s ifconfig.me)/health"
echo ""
echo "🔍 ДЛЯ ОТЛАДКИ:"
echo "docker logs \$(docker ps --format \"{{.Names}}\" | grep app | head -1)"
echo "sudo journalctl -u nginx -f"
+150
View File
@@ -0,0 +1,150 @@
#!/bin/bash
# MY Network Server Full Diagnosis Script
# Собирает всю информацию о состоянии сервера для удаленной диагностики
echo "=============================================="
echo "MY NETWORK SERVER DIAGNOSIS REPORT"
echo "Время: $(date)"
echo "Сервер: $(hostname)"
echo "=============================================="
echo ""
echo "=== 1. СИСТЕМНАЯ ИНФОРМАЦИЯ ==="
echo "OS: $(lsb_release -d 2>/dev/null | cut -f2 || cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
echo "Kernel: $(uname -r)"
echo "Uptime: $(uptime)"
echo "Disk space:"
df -h | grep -E "(/$|/home)"
echo "Memory:"
free -h
echo "Load average: $(cat /proc/loadavg)"
echo ""
echo "=== 2. СЕТЕВЫЕ ПОРТЫ И СОЕДИНЕНИЯ ==="
echo "Активные порты (LISTEN):"
sudo netstat -tulpn | grep LISTEN | sort -k4
echo ""
echo "Проверка ключевых портов:"
for port in 22 80 443 3000 5000 8080; do
if sudo netstat -tulpn | grep -q ":${port} "; then
echo "✅ Порт $port: АКТИВЕН"
else
echo "❌ Порт $port: НЕ АКТИВЕН"
fi
done
echo ""
echo "=== 3. СТАТУС СИСТЕМНЫХ СЛУЖБ ==="
echo "Docker service:"
sudo systemctl status docker --no-pager -l
echo ""
echo "SSH service:"
sudo systemctl status ssh --no-pager -l
echo ""
echo "Nginx service:"
sudo systemctl status nginx --no-pager -l
echo ""
echo "MyUploader service:"
sudo systemctl status myuploader --no-pager -l 2>/dev/null || echo "MyUploader service не найден"
echo ""
echo "=== 4. DOCKER ИНФОРМАЦИЯ ==="
echo "Docker version:"
docker --version 2>/dev/null || echo "Docker не установлен"
echo ""
echo "Docker-compose version:"
docker-compose --version 2>/dev/null || echo "Docker-compose не установлен"
echo ""
echo "Запущенные контейнеры:"
sudo docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || echo "Контейнеры не найдены"
echo ""
echo "Docker networks:"
sudo docker network ls 2>/dev/null || echo "Docker networks недоступны"
echo ""
echo "=== 5. MY-UPLOADER-BOT ПРОЕКТ ==="
PROJECT_DIR="/home/myuploader/my-uploader-bot"
if [ -d "$PROJECT_DIR" ]; then
echo "✅ Директория проекта найдена: $PROJECT_DIR"
echo "Содержимое директории:"
ls -la "$PROJECT_DIR"
echo ""
if [ -f "$PROJECT_DIR/docker-compose.production.yml" ]; then
echo "✅ Docker-compose файл найден"
echo "Статус compose проекта:"
cd "$PROJECT_DIR"
sudo docker-compose -f docker-compose.production.yml ps 2>/dev/null || echo "Ошибка получения статуса compose"
else
echo "❌ Docker-compose.production.yml не найден"
fi
else
echo "❌ Директория проекта не найдена: $PROJECT_DIR"
fi
echo ""
echo "=== 6. ЛОГИ КОНТЕЙНЕРОВ (последние 10 строк) ==="
for container in uploader-bot-app-1 uploader-bot-postgres-1 uploader-bot-nginx-1; do
echo "--- Логи $container ---"
sudo docker logs --tail=10 "$container" 2>/dev/null || echo "Контейнер $container не найден или не запущен"
echo ""
done
echo ""
echo "=== 7. NGINX КОНФИГУРАЦИЯ ==="
echo "Nginx конфигурация:"
sudo nginx -t 2>&1
echo ""
echo "Default site config:"
if [ -f "/etc/nginx/sites-enabled/default" ]; then
sudo cat /etc/nginx/sites-enabled/default
else
echo "❌ /etc/nginx/sites-enabled/default не найден"
fi
echo ""
echo "=== 8. SSH КОНФИГУРАЦИЯ ==="
echo "SSH config (основные параметры):"
sudo cat /etc/ssh/sshd_config | grep -E "^(Port|PasswordAuthentication|PubkeyAuthentication|PermitRootLogin)" || echo "SSH config недоступен"
echo ""
echo "=== 9. ФАЙРВОЛ (UFW) ==="
echo "UFW статус:"
sudo ufw status verbose 2>/dev/null || echo "UFW не установлен или недоступен"
echo ""
echo "=== 10. ЛОКАЛЬНЫЕ ТЕСТЫ СОЕДИНЕНИЙ ==="
echo "Тест локальных соединений:"
for port in 3000 5000 8080; do
if curl -s --max-time 3 http://localhost:$port/api/health > /dev/null 2>&1; then
echo "✅ localhost:$port/api/health - ДОСТУПЕН"
else
echo "❌ localhost:$port/api/health - НЕ ДОСТУПЕН"
fi
done
echo ""
echo "Тест nginx:"
curl -I http://localhost/ 2>/dev/null | head -5 || echo "❌ Nginx недоступен на localhost"
echo ""
echo "=== 11. ПРОЦЕССЫ ==="
echo "Процессы Python/Docker:"
ps aux | grep -E "(python|docker|nginx)" | grep -v grep
echo ""
echo "=== 12. RECENT SYSTEM LOGS ==="
echo "Последние системные ошибки:"
sudo journalctl --since "1 hour ago" --priority=err --no-pager -n 10 2>/dev/null || echo "Системные логи недоступны"
echo ""
echo "=============================================="
echo "ДИАГНОСТИКА ЗАВЕРШЕНА"
echo "Время завершения: $(date)"
echo "=============================================="
echo ""
echo "📋 КРАТКАЯ СВОДКА:"
echo "Скопируйте весь вывод этого скрипта и отправьте для анализа"
echo ""
+214
View File
@@ -0,0 +1,214 @@
#!/bin/bash
# MY Network - Установка сервиса (Шаг 1 из 2)
# Устанавливает базовый сервис без защиты
# Для защиты используйте: bash secure_service.sh
set -e
echo "🚀 MY Network - Установка сервиса"
echo "================================="
# Проверка прав root
if [[ $EUID -ne 0 ]]; then
echo "❌ Этот скрипт должен запускаться от root"
echo "Используйте: sudo bash install_service.sh"
exit 1
fi
# Получение домена
read -p "🌐 Введите домен (например: my-network.example.com): " DOMAIN
if [[ -z "$DOMAIN" ]]; then
echo "❌ Домен обязателен!"
exit 1
fi
# Получение email для SSL
read -p "📧 Введите email для SSL сертификата: " EMAIL
if [[ -z "$EMAIL" ]]; then
echo "❌ Email обязателен для SSL!"
exit 1
fi
echo "📋 Настройки:"
echo " Домен: $DOMAIN"
echo " Email: $EMAIL"
echo " Порт: 15100"
echo ""
# Обновление системы
echo "🔄 Обновление системы..."
apt update && apt upgrade -y
# Установка основных пакетов
echo "📦 Установка пакетов..."
apt install -y \
docker.io \
docker-compose \
git \
curl \
wget \
unzip \
python3 \
python3-pip \
python3-venv \
htop \
tree \
nano \
ufw
# Запуск Docker
systemctl enable docker
systemctl start docker
# Добавление пользователя в группу docker
usermod -aG docker $USER
# Создание директории проекта
PROJECT_DIR="/opt/my-network"
mkdir -p $PROJECT_DIR
cd $PROJECT_DIR
# Клонирование или копирование проекта
if [[ -d "my-uploader-bot" ]]; then
echo "📁 Проект уже существует, обновляем..."
cd my-uploader-bot
git pull 2>/dev/null || echo "Git pull failed, продолжаем..."
cd ..
else
echo "📥 Копирование проекта..."
# Если запускается из директории проекта, копируем
if [[ -f "../pyproject.toml" ]]; then
cp -r ../ ./my-uploader-bot/
else
echo "❌ Не найден файл проекта. Убедитесь что скрипт запускается из директории проекта."
exit 1
fi
fi
cd my-uploader-bot
# Создание .env файла
echo "📝 Создание конфигурации..."
cat > .env << EOF
# MY Network Configuration
NODE_ID=node-$(date +%s)
NODE_PORT=15100
DOMAIN=$DOMAIN
EMAIL=$EMAIL
# Database
DB_HOST=localhost
DB_PORT=3306
DB_NAME=my_network
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
# Network
BOOTSTRAP_NODES=[]
SYNC_INTERVAL=300
MAX_PEERS=10
EOF
# Создание директорий
echo "📁 Создание директорий..."
mkdir -p /opt/storage /opt/logs
chmod 755 /opt/storage /opt/logs
# Установка Python зависимостей
echo "🐍 Установка Python зависимостей..."
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements_new.txt
# Создание systemd сервиса
echo "⚙️ Создание systemd сервиса..."
cat > /etc/systemd/system/my-network.service << EOF
[Unit]
Description=MY Network Service
After=network.target docker.service
Requires=docker.service
[Service]
Type=forking
User=root
WorkingDirectory=$PROJECT_DIR/my-uploader-bot
Environment=PATH=$PROJECT_DIR/my-uploader-bot/venv/bin
ExecStart=/bin/bash -c 'source venv/bin/activate && python app/main.py'
ExecStop=/bin/kill -TERM \$MAINPID
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Запуск Docker Compose
echo "🐳 Запуск Docker сервисов..."
docker-compose -f docker-compose.new.yml up -d
# Активация сервиса
echo "🔧 Активация сервиса..."
systemctl daemon-reload
systemctl enable my-network
systemctl start my-network
# Проверка статуса
sleep 5
echo "📊 Проверка статуса..."
systemctl status my-network --no-pager
# Проверка портов
echo "🌐 Проверка портов..."
netstat -tlnp | grep :15100 || echo "⚠️ Порт 15100 не слушается"
# Сохранение конфигурации
echo "💾 Сохранение конфигурации..."
cat > /opt/my-network-config.txt << EOF
MY Network Service - Конфигурация
===============================
Домен: $DOMAIN
Email: $EMAIL
Порт: 15100
Директория: $PROJECT_DIR
Логи: /opt/logs
Хранилище: /opt/storage
Статус сервиса: systemctl status my-network
Логи сервиса: journalctl -u my-network -f
Перезапуск: systemctl restart my-network
Для защиты сервера запустите:
sudo bash secure_service.sh
EOF
echo ""
echo "✅ MY Network сервис установлен!"
echo "================================"
echo "📍 Конфигурация сохранена в: /opt/my-network-config.txt"
echo "🌐 Домен: $DOMAIN"
echo "🔌 Порт: 15100"
echo "📁 Директория: $PROJECT_DIR"
echo ""
echo "🔍 Проверка работы:"
echo " curl http://localhost:15100/api/my/health"
echo " systemctl status my-network"
echo ""
echo "⚠️ ВАЖНО: Для защиты сервера выполните:"
echo " sudo bash secure_service.sh"
echo ""
echo "📚 Документация: /opt/my-network/my-uploader-bot/MY_NETWORK_README.md"
+353
View File
@@ -0,0 +1,353 @@
#!/bin/bash
#
# Healthcheck script for MariaDB
#
# Runs various tests on the MariaDB server to check its health. Pass the tests
# to run as arguments. If all tests succeed, the server is considered healthy,
# otherwise it's not.
#
# Arguments are processed in strict order. Set replication_* options before
# the --replication option. This allows a different set of replication checks
# on different connections.
#
# --su{=|-mysql} is option to run the healthcheck as a different unix user.
# Useful if mysql@localhost user exists with unix socket authentication
# Using this option disregards previous options set, so should usually be the
# first option.
#
# Some tests require SQL privileges.
#
# TEST MINIMUM GRANTS REQUIRED
# connect none*
# innodb_initialized USAGE
# innodb_buffer_pool_loaded USAGE
# galera_online USAGE
# galera_ready USAGE
# replication REPLICATION_CLIENT (<10.5)or REPLICA MONITOR (10.5+)
# mariadbupgrade none, however unix user permissions on datadir
#
# The SQL user used is the default for the mysql client. This can be the unix user
# if no user(or password) is set in the [mariadb-client] section of a configuration
# file. --defaults-{file,extra-file,group-suffix} can specify a file/configuration
# different from elsewhere.
#
# Note * though denied error message will result in error log without
# any permissions.
set -eo pipefail
_process_sql()
{
mysql ${nodefaults:+--no-defaults} \
${def['file']:+--defaults-file=${def['file']}} \
${def['extra_file']:+--defaults-extra-file=${def['extra_file']}} \
${def['group_suffix']:+--defaults-group-suffix=${def['group_suffix']}} \
-B "$@"
}
# TESTS
# CONNECT
#
# Tests that a connection can be made over TCP, the final state
# of the entrypoint and is listening. The authentication used
# isn't tested.
connect()
{
set +e +o pipefail
# (on second extra_file)
# shellcheck disable=SC2086
mysql ${nodefaults:+--no-defaults} \
${def['file']:+--defaults-file=${def['file']}} \
${def['extra_file']:+--defaults-extra-file=${def['extra_file']}} \
${def['group_suffix']:+--defaults-group-suffix=${def['group_suffix']}} \
-h localhost --protocol tcp -e 'select 1' 2>&1 \
| grep -qF "Can't connect"
local ret=${PIPESTATUS[1]}
set -eo pipefail
if (( "$ret" == 0 )); then
# grep Matched "Can't connect" so we fail
return 1
fi
return 0
}
# INNODB_INITIALIZED
#
# This tests that the crash recovery of InnoDB has completed
# along with all the other things required to make it to a healthy
# operational state. Note this may return true in the early
# states of initialization. Use with a connect test to avoid
# these false positives.
innodb_initialized()
{
local s
s=$(_process_sql --skip-column-names -e "select 1 from information_schema.ENGINES WHERE engine='innodb' AND support in ('YES', 'DEFAULT', 'ENABLED')")
[ "$s" == 1 ]
}
# INNODB_BUFFER_POOL_LOADED
#
# Tests the load of the innodb buffer pool as been complete
# implies innodb_buffer_pool_load_at_startup=1 (default), or if
# manually SET innodb_buffer_pool_load_now=1
innodb_buffer_pool_loaded()
{
local s
s=$(_process_sql --skip-column-names -e "select VARIABLE_VALUE from information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME='Innodb_buffer_pool_load_status'")
if [[ $s =~ 'load completed' ]]; then
return 0
fi
return 1
}
# GALERA_ONLINE
#
# Tests that the galera node is in the SYNCed state
galera_online()
{
local s
s=$(_process_sql --skip-column-names -e "select VARIABLE_VALUE from information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME='WSREP_LOCAL_STATE'")
# 4 from https://galeracluster.com/library/documentation/node-states.html#node-state-changes
# not https://xkcd.com/221/
if [[ $s -eq 4 ]]; then
return 0
fi
return 1
}
# GALERA_READY
#
# Tests that the Galera provider is ready.
galera_ready()
{
local s
s=$(_process_sql --skip-column-names -e "select VARIABLE_VALUE from information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME='WSREP_READY'")
if [ "$s" = "ON" ]; then
return 0
fi
return 1
}
# REPLICATION
#
# Tests the replication has the required set of functions:
# --replication_all -> Checks all replication sources
# --replication_name=n -> sets the multisource connection name tested
# --replication_io -> IO thread is running
# --replication_sql -> SQL thread is running
# --replication_seconds_behind_master=n -> less than or equal this seconds of delay
# --replication_sql_remaining_delay=n -> less than or equal this seconds of remaining delay
# (ref: https://mariadb.com/kb/en/delayed-replication/)
replication()
{
# SHOW REPLICA available 10.5+
# https://github.com/koalaman/shellcheck/issues/2383
# shellcheck disable=SC2016,SC2026
_process_sql -e "SHOW ${repl['all']:+all} REPLICA${repl['all']:+S} ${repl['name']:+'${repl['name']}'} STATUS\G" | \
{
# required for trim of leading space.
shopt -s extglob
# Row header
read -t 5 -r
# read timeout
[ $? -gt 128 ] && return 1
while IFS=":" read -t 1 -r n v; do
# Trim leading space
n=${n##+([[:space:]])}
# Leading space on all values by the \G format needs to be trimmed.
v=${v:1}
case "$n" in
Slave_IO_Running)
if [ -n "${repl['io']}" ] && [ "$v" = 'No' ]; then
return 1
fi
;;
Slave_SQL_Running)
if [ -n "${repl['sql']}" ] && [ "$v" = 'No' ]; then
return 1
fi
;;
Seconds_Behind_Master)
# A NULL value is the IO thread not running:
if [ -n "${repl['seconds_behind_master']}" ] &&
{ [ "$v" = NULL ] ||
(( "${repl['seconds_behind_master']}" < "$v" )); }; then
return 1
fi
;;
SQL_Remaining_Delay)
# Unlike Seconds_Behind_Master, sql_remaining_delay will hit NULL
# once replication is caught up - https://mariadb.com/kb/en/delayed-replication/
if [ -n "${repl['sql_remaining_delay']}" ] &&
[ "$v" != NULL ] &&
(( "${repl['sql_remaining_delay']}" < "$v" )); then
return 1
fi
;;
esac
done
# read timeout
[ $? -gt 128 ] && return 1
return 0
}
# reachable in command not found(?)
# shellcheck disable=SC2317
return $?
}
# mariadbupgrade
#
# Test the lock on the file $datadir/mysql_upgrade_info
# https://jira.mariadb.org/browse/MDEV-27068
mariadbupgrade()
{
local f="$datadir/mysql_upgrade_info"
if [ -r "$f" ]; then
flock --exclusive --nonblock -n 9 9<"$f"
return $?
fi
return 0
}
# MAIN
if [ $# -eq 0 ]; then
echo "At least one argument required" >&2
exit 1
fi
#ENDOFSUBSTITUTIONS
# Marks the end of mysql -> mariadb name changes in 10.6+
# Global variables used by tests
declare -A repl
declare -A def
nodefaults=
datadir=/var/lib/mysql
if [ -f $datadir/.my-healthcheck.cnf ]; then
def['extra_file']=$datadir/.my-healthcheck.cnf
fi
_repl_param_check()
{
case "$1" in
seconds_behind_master) ;&
sql_remaining_delay)
if [ -z "${repl['io']}" ]; then
repl['io']=1
echo "Forcing --replication_io=1, $1 requires IO thread to be running" >&2
fi
;;
all)
if [ -n "${repl['name']}" ]; then
unset 'repl[name]'
echo "Option --replication_all incompatible with specified source --replication_name, clearing replication_name" >&2
fi
;;
name)
if [ -n "${repl['all']}" ]; then
unset 'repl[all]'
echo "Option --replication_name incompatible with --replication_all, clearing replication_all" >&2
fi
;;
esac
}
_test_exists() {
declare -F "$1" > /dev/null
return $?
}
while [ $# -gt 0 ]; do
case "$1" in
--su=*)
u="${1#*=}"
shift
exec gosu "${u}" "${BASH_SOURCE[0]}" "$@"
;;
--su)
shift
u=$1
shift
exec gosu "$u" "${BASH_SOURCE[0]}" "$@"
;;
--su-mysql)
shift
exec gosu mysql "${BASH_SOURCE[0]}" "$@"
;;
--replication_*=*)
# Change the n to what is between _ and = and make lower case
n=${1#*_}
n=${n%%=*}
n=${n,,*}
# v is after the =
v=${1#*=}
repl[$n]=$v
_repl_param_check "$n"
;;
--replication_*)
# Without =, look for a non --option next as the value,
# otherwise treat it as an "enable", just equate to 1.
# Clearing option is possible with "--replication_X="
n=${1#*_}
n=${n,,*}
if [ "${2:0:2}" == '--' ]; then
repl[$n]=1
else
repl[$n]=$2
shift
fi
_repl_param_check "$n"
;;
--datadir=*)
datadir=${1#*=}
;;
--datadir)
shift
datadir=${1}
;;
--no-defaults)
def=()
nodefaults=1
;;
--defaults-file=*|--defaults-extra-file=*|--defaults-group-suffix=*)
n=${1:11} # length --defaults-
n=${n%%=*}
n=${n//-/_}
# v is after the =
v=${1#*=}
def[$n]=$v
nodefaults=
;;
--defaults-file|--defaults-extra-file|--defaults-group-suffix)
n=${1:11} # length --defaults-
n=${n//-/_}
if [ "${2:0:2}" == '--' ]; then
def[$n]=""
else
def[$n]=$2
shift
fi
nodefaults=
;;
--*)
test=${1#--}
;;
*)
echo "Unknown healthcheck option $1" >&2
exit 1
esac
if [ -n "$test" ]; then
if ! _test_exists "$test" ; then
echo "healthcheck unknown option or test '$test'" >&2
exit 1
elif ! "$test"; then
echo "healthcheck $test failed" >&2
exit 1
fi
test=
fi
shift
done
+126
View File
@@ -0,0 +1,126 @@
#!/bin/bash
# MY Network Bootstrap Deployment Monitor
# Скрипт для наблюдения за процессом развертывания
echo "🚀 MY Network Bootstrap Deployment Monitor"
echo "=========================================="
echo "Сервер: 2.58.65.188"
echo "Домен: my-public-node-3.projscale.dev"
echo "Время запуска: $(date)"
echo ""
while true; do
clear
echo "🚀 MY Network Bootstrap - Live Monitor"
echo "====================================="
echo "⏰ $(date '+%H:%M:%S') | Обновляется каждые 30 секунд"
echo ""
# Проверка локальных процессов
echo "📡 Локальные процессы:"
SCP_COUNT=$(ps aux | grep 'scp.*auto_deploy.sh' | grep -v grep | wc -l | tr -d ' ')
SSH_COUNT=$(ps aux | grep 'auto_ssh_deploy.exp' | grep -v grep | wc -l | tr -d ' ')
if [[ $SCP_COUNT -gt 0 ]]; then
echo " ✅ SCP Transfer: Активен (передача файлов)"
else
echo " ✅ SCP Transfer: Завершен"
fi
if [[ $SSH_COUNT -gt 0 ]]; then
echo " 🔄 SSH Deploy: Активен (установка на сервере)"
else
echo " ⚠️ SSH Deploy: Завершен или прерван"
fi
echo ""
# Проверка доступности домена
echo "🌐 Проверка домена:"
DOMAIN_STATUS=$(curl -s --connect-timeout 3 -o /dev/null -w "%{http_code}" https://my-public-node-3.projscale.dev/api/my/health 2>/dev/null || echo "TIMEOUT")
case $DOMAIN_STATUS in
"200")
echo " ✅ API доступен: https://my-public-node-3.projscale.dev/api/my/health"
echo " 🎉 РАЗВЕРТЫВАНИЕ ЗАВЕРШЕНО УСПЕШНО!"
;;
"521")
echo " ⏳ Error 521: Сервер недоступен (установка в процессе)"
;;
"522")
echo " ⏳ Error 522: Connection timeout (сервис запускается)"
;;
"TIMEOUT")
echo " ⏳ Timeout: Проверяем соединение..."
;;
*)
echo " ⚠️ HTTP $DOMAIN_STATUS: Проверяем статус..."
;;
esac
echo ""
# Проверка прямого подключения к серверу
echo "🔍 Проверка сервера:"
SERVER_PING=$(ping -c 1 -W 1000 2.58.65.188 2>/dev/null | grep "1 received" | wc -l | tr -d ' ')
if [[ $SERVER_PING -gt 0 ]]; then
echo " ✅ Сервер 2.58.65.188 доступен"
else
echo " ⚠️ Сервер 2.58.65.188 недоступен"
fi
# Попытка проверить порты
echo ""
echo "🔌 Проверка портов:"
# Проверяем SSH (22)
SSH_CHECK=$(timeout 3 bash -c "</dev/tcp/2.58.65.188/22" 2>/dev/null && echo "open" || echo "closed")
echo " SSH (22): $SSH_CHECK"
# Проверяем HTTP (80)
HTTP_CHECK=$(timeout 3 bash -c "</dev/tcp/2.58.65.188/80" 2>/dev/null && echo "open" || echo "closed")
echo " HTTP (80): $HTTP_CHECK"
# Проверяем HTTPS (443)
HTTPS_CHECK=$(timeout 3 bash -c "</dev/tcp/2.58.65.188/443" 2>/dev/null && echo "open" || echo "closed")
echo " HTTPS (443): $HTTPS_CHECK"
echo ""
echo "📊 Статус развертывания:"
if [[ $DOMAIN_STATUS == "200" ]]; then
echo " 🎯 Статус: ЗАВЕРШЕНО"
echo " ✅ MY Network Bootstrap Node готов к работе!"
echo ""
echo "🔗 Доступные endpoints:"
echo " • Health: https://my-public-node-3.projscale.dev/api/my/health"
echo " • Node Info: https://my-public-node-3.projscale.dev/api/my/node/info"
echo " • Bootstrap: https://my-public-node-3.projscale.dev/api/my/bootstrap/config"
echo ""
echo "🎉 Развертывание успешно завершено!"
break
elif [[ $SSH_COUNT -gt 0 ]]; then
echo " 🔄 Статус: В ПРОЦЕССЕ"
echo " ⏳ Установка компонентов на сервере..."
if [[ $HTTPS_CHECK == "open" ]]; then
echo " ✅ Порт 443 открыт - nginx работает"
fi
elif [[ $SCP_COUNT -gt 0 ]]; then
echo " 📤 Статус: ПЕРЕДАЧА ФАЙЛОВ"
echo " ⏳ Копирование скриптов на сервер..."
else
echo " ⚠️ Статус: НЕИЗВЕСТНО"
echo " 🔍 Проверьте терминалы или перезапустите развертывание"
fi
echo ""
echo "💡 Для детального мониторинга:"
echo " Terminal 1: SCP процесс"
echo " Terminal 2: SSH развертывание"
echo ""
echo "⏹️ Нажмите Ctrl+C для выхода"
echo "🔄 Следующее обновление через 30 секунд..."
sleep 30
done
+55
View File
@@ -0,0 +1,55 @@
#!/bin/bash
# Быстрая проверка статуса MY Network на сервере
DOMAIN="my-public-node-3.projscale.dev"
SERVER="2.58.65.188"
echo "🔍 Проверка статуса MY Network Bootstrap Node"
echo "=============================================="
echo ""
# Проверка подключения к серверу
echo "📡 Проверка подключения к серверу $SERVER..."
if ping -c 1 $SERVER >/dev/null 2>&1; then
echo "✅ Сервер доступен"
else
echo "❌ Сервер недоступен"
exit 1
fi
# Проверка портов
echo ""
echo "🔌 Проверка портов на сервере..."
for port in 22 80 443; do
if nc -z -w3 $SERVER $port 2>/dev/null; then
echo "✅ Порт $port: открыт"
else
echo "❌ Порт $port: закрыт"
fi
done
# Проверка домена
echo ""
echo "🌐 Проверка домена $DOMAIN..."
if curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN" | grep -q "200\|404\|302"; then
echo "✅ Домен отвечает"
echo "📊 HTTP код: $(curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN")"
else
echo "❌ Домен не отвечает (521 - сервер недоступен)"
fi
# Проверка API
echo ""
echo "🎯 Проверка MY Network API..."
API_RESPONSE=$(curl -s -w "%{http_code}" "https://$DOMAIN/api/my/health" -o /tmp/api_response.json)
if [[ "$API_RESPONSE" == "200" ]]; then
echo "✅ MY Network API работает"
echo "📄 Ответ API:"
cat /tmp/api_response.json | jq . 2>/dev/null || cat /tmp/api_response.json
else
echo "❌ MY Network API не работает (код: $API_RESPONSE)"
fi
echo ""
echo "🏁 Проверка завершена"
+351
View File
@@ -0,0 +1,351 @@
#!/bin/bash
# MY Network - Защита сервиса (Шаг 2 из 2)
# Настройка безопасности, nginx, SSL, firewall
# Запускать после install_service.sh
set -e
echo "🔒 MY Network - Защита сервиса"
echo "==============================="
# Проверка прав root
if [[ $EUID -ne 0 ]]; then
echo "❌ Этот скрипт должен запускаться от root"
echo "Используйте: sudo bash secure_service.sh"
exit 1
fi
# Проверка конфигурации
CONFIG_FILE="/opt/my-network-config.txt"
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "❌ Конфигурация не найдена!"
echo "Сначала запустите: sudo bash install_service.sh"
exit 1
fi
# Извлечение конфигурации
DOMAIN=$(grep "Домен:" $CONFIG_FILE | cut -d' ' -f2)
EMAIL=$(grep "Email:" $CONFIG_FILE | cut -d' ' -f2)
if [[ -z "$DOMAIN" || -z "$EMAIL" ]]; then
echo "❌ Не удалось прочитать конфигурацию!"
exit 1
fi
echo "📋 Настройки безопасности:"
echo " Домен: $DOMAIN"
echo " Email: $EMAIL"
echo " SSL: Let's Encrypt"
echo " Firewall: UFW"
echo ""
# Установка nginx и certbot
echo "🌐 Установка nginx и certbot..."
apt install -y nginx certbot python3-certbot-nginx
# Настройка nginx
echo "⚙️ Настройка nginx..."
cat > /etc/nginx/sites-available/my-network << EOF
# MY Network - nginx configuration
server {
listen 80;
server_name $DOMAIN;
# Redirect HTTP to HTTPS
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
# SSL Configuration (will be updated by certbot)
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
# 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";
# Hide nginx version
server_tokens off;
# Rate limiting
limit_req_zone \$binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone \$binary_remote_addr zone=monitor:10m rate=2r/s;
# Main application
location / {
limit_req zone=api burst=20 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;
# Websocket support
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Monitoring interface (restricted)
location /api/my/monitor {
limit_req zone=monitor burst=5 nodelay;
# IP whitelist (localhost only by default)
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;
}
# Static files
location /static/ {
alias /opt/my-network/my-uploader-bot/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# 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 /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Проверка конфигурации nginx
nginx -t
# Получение SSL сертификата
echo "🔐 Получение SSL сертификата..."
certbot --nginx -d $DOMAIN --email $EMAIL --agree-tos --non-interactive --redirect
# Настройка автообновления сертификата
echo "🔄 Настройка автообновления SSL..."
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
# Настройка firewall
echo "🔥 Настройка firewall..."
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'
fi
# Разрешение HTTP/HTTPS
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
# Разрешение внутренних соединений
ufw allow from 127.0.0.1 to any port 15100 comment 'MY Network internal'
# Включение firewall
ufw --force enable
# Дополнительная защита системы
echo "🛡️ Дополнительная защита..."
# Отключение ненужных сервисов
systemctl disable --now apache2 2>/dev/null || true
systemctl disable --now nginx 2>/dev/null || true
# Запуск nginx
systemctl enable nginx
systemctl start nginx
# Настройка fail2ban
echo "🚫 Установка fail2ban..."
apt install -y 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 = 3
EOF
systemctl enable fail2ban
systemctl start fail2ban
# Настройка logrotate
echo "📜 Настройка ротации логов..."
cat > /etc/logrotate.d/my-network << EOF
/opt/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
}
EOF
# Настройка мониторинга
echo "📊 Настройка мониторинга..."
cat > /opt/monitor.sh << 'EOF'
#!/bin/bash
# MY Network monitoring script
LOG_FILE="/opt/logs/monitor.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
# Check service status
if systemctl is-active --quiet my-network; then
SERVICE_STATUS="OK"
else
SERVICE_STATUS="FAIL"
fi
# Check nginx status
if systemctl is-active --quiet nginx; then
NGINX_STATUS="OK"
else
NGINX_STATUS="FAIL"
fi
# Check disk space
DISK_USAGE=$(df -h /opt | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ $DISK_USAGE -gt 90 ]]; then
DISK_STATUS="CRITICAL"
elif [[ $DISK_USAGE -gt 80 ]]; then
DISK_STATUS="WARNING"
else
DISK_STATUS="OK"
fi
# Check memory
MEM_USAGE=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}')
if [[ $MEM_USAGE -gt 90 ]]; then
MEM_STATUS="CRITICAL"
elif [[ $MEM_USAGE -gt 80 ]]; then
MEM_STATUS="WARNING"
else
MEM_STATUS="OK"
fi
# Log status
echo "[$DATE] Service: $SERVICE_STATUS, Nginx: $NGINX_STATUS, Disk: $DISK_STATUS ($DISK_USAGE%), Memory: $MEM_STATUS ($MEM_USAGE%)" >> $LOG_FILE
# Alert if critical
if [[ "$SERVICE_STATUS" == "FAIL" || "$NGINX_STATUS" == "FAIL" || "$DISK_STATUS" == "CRITICAL" || "$MEM_STATUS" == "CRITICAL" ]]; then
echo "[$DATE] ALERT: Critical status detected!" >> $LOG_FILE
# Here you can add email notification or webhook
fi
EOF
chmod +x /opt/monitor.sh
# Добавление в cron
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/monitor.sh") | crontab -
# Обновление конфигурации
echo "💾 Обновление конфигурации..."
cat >> /opt/my-network-config.txt << EOF
Безопасность настроена:
======================
SSL: Включен (Let's Encrypt)
Firewall: Включен (UFW)
Nginx: Включен с rate limiting
Fail2ban: Включен
Мониторинг: /opt/monitor.sh (каждые 5 мин)
Проверка безопасности:
ufw status
systemctl status nginx
systemctl status fail2ban
certbot certificates
Логи безопасности:
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/fail2ban.log
/opt/logs/monitor.log
EOF
# Финальная проверка
echo "🔍 Финальная проверка..."
sleep 3
echo "🌐 Проверка nginx..."
systemctl status nginx --no-pager -l
echo "🔥 Статус firewall..."
ufw status numbered
echo "🔐 SSL сертификаты..."
certbot certificates
echo "📡 Проверка доступности..."
curl -s -o /dev/null -w "%{http_code}" https://$DOMAIN/api/my/health || echo "Сервис недоступен"
echo ""
echo "✅ MY Network защищен!"
echo "======================"
echo "🌐 Домен: https://$DOMAIN"
echo "🔐 SSL: Включен"
echo "🔥 Firewall: Включен"
echo "🚫 Fail2ban: Включен"
echo "📊 Мониторинг: Включен"
echo ""
echo "🔍 Проверка работы:"
echo " curl https://$DOMAIN/api/my/health"
echo " systemctl status my-network nginx fail2ban"
echo ""
echo "📈 Мониторинг:"
echo " https://$DOMAIN/api/my/monitor/ (только с localhost)"
echo " tail -f /opt/logs/monitor.log"
echo ""
echo "🛡️ Безопасность:"
echo " ufw status"
echo " fail2ban-client status"
echo " certbot certificates"
echo ""
echo "📚 Полная документация: /opt/my-network/my-uploader-bot/DOCS_RU.md"
+430
View File
@@ -0,0 +1,430 @@
#!/bin/bash
# MY Network Minimal Setup - только встроенные модули Python
# Без pip, без внешних зависимостей
set -e
echo "🚀 MY Network Minimal Setup"
echo "==========================="
echo "Пользователь: $(whoami)"
echo "Директория: $(pwd)"
echo ""
# Переход в my-uploader-bot
if [[ -d "my-uploader-bot" ]]; then
cd my-uploader-bot
echo "✅ Директория my-uploader-bot найдена"
else
echo "❌ Директория my-uploader-bot не найдена!"
echo "Содержимое текущей директории:"
ls -la
exit 1
fi
# Создание директорий
mkdir -p app/api
mkdir -p logs
# Проверка Python
echo "🐍 Проверка Python..."
python3 --version || { echo "❌ Python3 не найден"; exit 1; }
# Создание минимального MY Network приложения
echo "🏗️ Создание MY Network приложения (только встроенные модули)..."
cat > app/main.py << 'EOF'
#!/usr/bin/env python3
"""MY Network Bootstrap Node - Minimal Version (только встроенные модули)"""
import os
import json
import sys
import logging
import time
from datetime import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse
import threading
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('logs/my-network.log', encoding='utf-8'),
logging.StreamHandler()
]
)
logger = logging.getLogger("MY-Network")
NODE_ID = f"bootstrap-minimal-{int(datetime.now().timestamp())}"
DOMAIN = "my-public-node-3.projscale.dev"
PORT = 15100
class MyNetworkHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
parsed_path = urlparse(self.path)
path = parsed_path.path
# Маршруты
if path == '/':
self.send_json_response({"message": "MY Network Bootstrap Node v2.0 - Minimal", "status": "active"})
elif path == '/api/my/health':
self.send_json_response({
"status": "healthy",
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"mode": "minimal",
"timestamp": datetime.utcnow().isoformat(),
"services": ["api", "monitor"],
"version": "2.0.0"
})
elif path == '/api/my/node/info':
self.send_json_response({
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "minimal",
"mode": "minimal",
"services": ["api", "monitor"],
"protocol_version": "2.0",
"last_seen": datetime.utcnow().isoformat()
})
elif path == '/api/my/bootstrap/config':
config = {
"version": "2.0",
"network_id": "my-network-main",
"bootstrap_nodes": [
{
"id": NODE_ID,
"host": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "minimal",
"mode": "minimal",
"services": ["api", "monitor"],
"last_seen": datetime.utcnow().isoformat()
}
],
"network_config": {
"protocol_version": "2.0",
"max_peers": 5,
"sync_interval": 300
},
"api_endpoints": {
"base_url": f"http://{DOMAIN}:{PORT}",
"health": "/api/my/health",
"node_info": "/api/my/node/info",
"bootstrap": "/api/my/bootstrap/config"
}
}
self.send_json_response(config)
elif path == '/api/my/monitor/' or path == '/api/my/monitor':
self.send_html_response(self.get_monitor_html())
else:
self.send_response(404)
self.send_header('Content-type', 'application/json')
self.end_headers()
error_response = {"error": "Not Found", "path": path}
self.wfile.write(json.dumps(error_response).encode('utf-8'))
except Exception as e:
logger.error(f"Error handling request: {e}")
self.send_response(500)
self.end_headers()
self.wfile.write(b'Internal Server Error')
def send_json_response(self, data):
try:
self.send_response(200)
self.send_header('Content-type', 'application/json; charset=utf-8')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
self.send_header('X-MY-Network-Version', '2.0')
self.send_header('Server', 'MY-Network-Bootstrap/2.0')
self.end_headers()
json_data = json.dumps(data, indent=2, ensure_ascii=False)
self.wfile.write(json_data.encode('utf-8'))
except Exception as e:
logger.error(f"Error sending JSON response: {e}")
def send_html_response(self, html):
try:
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('X-MY-Network-Version', '2.0')
self.send_header('Server', 'MY-Network-Bootstrap/2.0')
self.end_headers()
self.wfile.write(html.encode('utf-8'))
except Exception as e:
logger.error(f"Error sending HTML response: {e}")
def get_monitor_html(self):
uptime = int(time.time() - start_time)
uptime_str = f"{uptime // 3600}h {(uptime % 3600) // 60}m {uptime % 60}s"
return f"""<!DOCTYPE html>
<html>
<head>
<title>MY Network Bootstrap Monitor - Minimal</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="30">
<style>
body {{ font-family: 'Courier New', monospace; background: #000; color: #0f0; padding: 20px; margin: 0; }}
h1 {{ color: #ff0; text-align: center; text-shadow: 0 0 10px #ff0; }}
.box {{ border: 1px solid #0f0; padding: 15px; margin: 10px 0; background: rgba(0,255,0,0.1); }}
.status {{ color: #0f0; font-weight: bold; }}
.info {{ color: #00f; }}
.warning {{ color: #f80; }}
.timestamp {{ color: #fff; font-size: 0.8em; }}
.ascii-art {{ color: #0f0; font-size: 0.7em; text-align: center; }}
</style>
</head>
<body>
<div class="ascii-art">
███╗ ███╗██╗ ██╗ ███╗ ██╗███████╗████████╗██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗
████╗ ████║╚██╗ ██╔╝ ████╗ ██║██╔════╝╚══██╔══╝██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝
██╔████╔██║ ╚████╔╝ ██╔██╗ ██║█████╗ ██║ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝
██║╚██╔╝██║ ╚██╔╝ ██║╚██╗██║██╔══╝ ██║ ██║███╗██║██║ ██║██╔══██╗██╔═██╗
██║ ╚═╝ ██║ ██║ ██║ ╚████║███████╗ ██║ ╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
</div>
<h1>🚀 MY Network Bootstrap Node Monitor</h1>
<div class="box">
<h3 class="status">🟢 Node Status: ACTIVE (Minimal Mode)</h3>
<p class="info">🆔 Node ID: {NODE_ID}</p>
<p class="info">🌐 Domain: {DOMAIN}</p>
<p class="info">🔌 Port: {PORT}</p>
<p class="info">📡 Type: Bootstrap Primary</p>
<p class="info">🏷️ Version: 2.0.0</p>
<p class="info">⚙️ Mode: Minimal HTTP Server</p>
<p class="info">🛠️ Services: API, Monitor</p>
<p class="info">⏱️ Uptime: {uptime_str}</p>
<p class="timestamp">🕐 Last Update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="box">
<h3 class="status">🌐 Network Configuration</h3>
<p class="info">📋 Protocol Version: 2.0</p>
<p class="info">👥 Max Peers: 5</p>
<p class="info">🔓 Public Access: Enabled</p>
<p class="warning">⚠️ SSL: Disabled (Minimal Mode)</p>
<p class="info">🔄 Sync Interval: 300s</p>
</div>
<div class="box">
<h3 class="warning">⚠️ Minimal Mode</h3>
<p class="warning">🔧 Сервис запущен в минимальном режиме</p>
<p class="warning">📦 Использует только встроенные модули Python</p>
<p class="warning">🚫 Без внешних зависимостей</p>
<p class="info">🌍 Доступ: http://{DOMAIN}:{PORT}</p>
</div>
<div class="box">
<h3 class="status">🔗 API Endpoints</h3>
<p class="info">📊 Health: <a href="/api/my/health" style="color: #0ff;">/api/my/health</a></p>
<p class="info">ℹ️ Node Info: <a href="/api/my/node/info" style="color: #0ff;">/api/my/node/info</a></p>
<p class="info">🏗️ Bootstrap Config: <a href="/api/my/bootstrap/config" style="color: #0ff;">/api/my/bootstrap/config</a></p>
</div>
<div class="timestamp" style="text-align: center; margin-top: 20px;">
⏰ Автообновление каждые 30 секунд
</div>
</body>
</html>"""
def log_message(self, format, *args):
client_ip = self.address_string()
message = format % args
logger.info(f"{client_ip} - {message}")
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
self.end_headers()
# Глобальная переменная для времени запуска
start_time = time.time()
def start_server():
global start_time
start_time = time.time()
logger.info("=" * 50)
logger.info("🚀 MY Network Bootstrap Node - Minimal Mode")
logger.info("=" * 50)
logger.info(f"🌐 Domain: {DOMAIN}")
logger.info(f"🔌 Port: {PORT}")
logger.info(f"🆔 Node ID: {NODE_ID}")
logger.info(f"⚙️ Mode: Minimal HTTP Server")
logger.info(f"🌍 Access: http://0.0.0.0:{PORT}")
logger.info(f"📊 Health: http://0.0.0.0:{PORT}/api/my/health")
logger.info(f"🖥️ Monitor: http://0.0.0.0:{PORT}/api/my/monitor/")
logger.info("=" * 50)
try:
# Создание HTTP сервера
server_address = ("0.0.0.0", PORT)
httpd = HTTPServer(server_address, MyNetworkHandler)
logger.info(f"✅ Server started successfully")
logger.info(f"🎯 MY Network Bootstrap Node is ready!")
# Запуск сервера
httpd.serve_forever()
except KeyboardInterrupt:
logger.info("🛑 Server stopped by user")
except Exception as e:
logger.error(f"❌ Server error: {e}")
raise
if __name__ == "__main__":
try:
start_server()
except KeyboardInterrupt:
print("\n🛑 Stopping server...")
sys.exit(0)
except Exception as e:
print(f"❌ Fatal error: {e}")
sys.exit(1)
EOF
# Создание скрипта запуска
cat > start_my_network.sh << 'EOF'
#!/bin/bash
cd /home/service/my-uploader-bot
echo "🚀 Запуск MY Network Bootstrap Node (Minimal Mode)"
echo "==============================================="
echo ""
# Создание директории для логов
mkdir -p logs
# Запуск приложения
echo "▶️ Запуск сервера..."
python3 app/main.py
EOF
chmod +x start_my_network.sh
# Создание скрипта для фонового запуска
cat > run_my_network.sh << 'EOF'
#!/bin/bash
# Проверка, запущен ли MY Network
if ! pgrep -f "python3 app/main.py" > /dev/null; then
echo "$(date): Запуск MY Network" >> /home/service/my-uploader-bot/logs/cron.log
cd /home/service/my-uploader-bot
nohup python3 app/main.py >> logs/app.log 2>&1 &
PID=$!
echo "$(date): MY Network запущен (PID: $PID)" >> /home/service/my-uploader-bot/logs/cron.log
echo "MY Network запущен (PID: $PID)"
else
echo "$(date): MY Network уже запущен" >> /home/service/my-uploader-bot/logs/cron.log
echo "MY Network уже запущен"
fi
EOF
chmod +x run_my_network.sh
# Создание скрипта остановки
cat > stop_my_network.sh << 'EOF'
#!/bin/bash
echo "🛑 Остановка MY Network..."
if pgrep -f "python3 app/main.py" > /dev/null; then
pkill -f "python3 app/main.py"
echo "✅ MY Network остановлен"
echo "$(date): MY Network остановлен" >> /home/service/my-uploader-bot/logs/cron.log
else
echo "⚠️ MY Network не запущен"
fi
EOF
chmod +x stop_my_network.sh
# Создание скрипта проверки статуса
cat > status_my_network.sh << 'EOF'
#!/bin/bash
echo "📊 Статус MY Network Bootstrap Node"
echo "================================="
if pgrep -f "python3 app/main.py" > /dev/null; then
PID=$(pgrep -f "python3 app/main.py")
echo "✅ MY Network запущен (PID: $PID)"
echo "🌐 Доступ: http://my-public-node-3.projscale.dev:15100"
echo "📊 Health: http://my-public-node-3.projscale.dev:15100/api/my/health"
echo "🖥️ Monitor: http://my-public-node-3.projscale.dev:15100/api/my/monitor/"
echo ""
echo "📈 Процесс:"
ps aux | grep "python3 app/main.py" | grep -v grep
echo ""
echo "🔌 Порт 15100:"
netstat -tulpn 2>/dev/null | grep :15100 || echo "netstat недоступен"
else
echo "❌ MY Network не запущен"
fi
echo ""
echo "📝 Последние логи:"
if [[ -f logs/my-network.log ]]; then
tail -5 logs/my-network.log
else
echo "Лог файл не найден"
fi
EOF
chmod +x status_my_network.sh
# Добавление в crontab
echo "📅 Настройка автозапуска..."
(crontab -l 2>/dev/null | grep -v "run_my_network.sh"; echo "*/5 * * * * /home/service/my-uploader-bot/run_my_network.sh") | crontab -
echo ""
echo "✅ MY Network Bootstrap Node установлен!"
echo "======================================="
echo ""
echo "🚀 Команды управления:"
echo " cd /home/service/my-uploader-bot"
echo " ./start_my_network.sh # Запуск в терминале"
echo " ./run_my_network.sh # Запуск в фоне"
echo " ./stop_my_network.sh # Остановка"
echo " ./status_my_network.sh # Проверка статуса"
echo ""
echo "🌐 Доступ к сервису:"
echo " http://my-public-node-3.projscale.dev:15100"
echo " http://my-public-node-3.projscale.dev:15100/api/my/health"
echo " http://my-public-node-3.projscale.dev:15100/api/my/monitor/"
echo ""
echo "📝 Логи:"
echo " tail -f logs/my-network.log # Основной лог"
echo " tail -f logs/app.log # Лог приложения"
echo " tail -f logs/cron.log # Лог cron"
echo ""
echo "⚡ Автозапуск настроен через cron (каждые 5 минут)"
echo ""
echo "🎯 MY Network Bootstrap Node готов к работе!"
echo ""
echo "▶️ Запустить сейчас? Выполните:"
echo " ./run_my_network.sh"
+331
View File
@@ -0,0 +1,331 @@
#!/bin/bash
# MY Network Nginx + SSL Setup
# Настройка nginx с SSL сертификатами через certbot
set -e
DOMAIN="my-public-node-3.projscale.dev"
EMAIL="admin@projscale.dev"
SERVICE_PORT="15100"
echo "🔒 MY Network Nginx + SSL Setup"
echo "==============================="
echo "Домен: $DOMAIN"
echo "Email: $EMAIL"
echo "Сервис порт: $SERVICE_PORT"
echo ""
# Проверка root прав
if [[ $EUID -ne 0 ]]; then
echo "❌ Запустите от root: sudo bash setup_nginx_ssl.sh"
exit 1
fi
# Обновление системы
echo "🔄 Обновление системы..."
apt update
# Установка необходимых пакетов
echo "📦 Установка nginx, certbot, ufw..."
apt install -y nginx certbot python3-certbot-nginx ufw curl
# Остановка nginx для получения сертификата
echo "🛑 Остановка nginx..."
systemctl stop nginx || true
# Настройка firewall
echo "🔥 Настройка firewall..."
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
# SSH
ufw allow 22/tcp comment 'SSH'
# HTTP/HTTPS
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
# Внутренний порт сервиса (только локально)
ufw allow from 127.0.0.1 to any port $SERVICE_PORT comment 'MY Network Local'
ufw --force enable
# Получение SSL сертификата
echo "🔐 Получение SSL сертификата..."
certbot certonly \
--standalone \
--non-interactive \
--agree-tos \
--email $EMAIL \
-d $DOMAIN
# Проверка что сертификат получен
if [[ ! -f "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" ]]; then
echo "❌ Не удалось получить SSL сертификат!"
exit 1
fi
echo "✅ SSL сертификат получен"
# Создание конфигурации nginx
echo "🌐 Настройка nginx..."
# Удаление дефолтного сайта
rm -f /etc/nginx/sites-enabled/default
# Создание конфигурации MY Network
cat > /etc/nginx/sites-available/my-network << EOF
# MY Network Bootstrap Node - Nginx Configuration
# HTTP -> HTTPS redirect
server {
listen 80;
server_name $DOMAIN;
# Certbot renewal
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# Redirect all HTTP to HTTPS
location / {
return 301 https://\$server_name\$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
server_name $DOMAIN;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
# SSL Security
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-MY-Network-Version "2.0" always;
add_header X-MY-Network-Node "bootstrap" always;
# Hide nginx version
server_tokens off;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Rate limiting
limit_req_zone \$binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone \$binary_remote_addr zone=monitor:10m rate=1r/s;
# Main application proxy
location / {
# Rate limiting
limit_req zone=api burst=20 nodelay;
proxy_pass http://127.0.0.1:$SERVICE_PORT;
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_set_header X-Forwarded-Host \$host;
proxy_set_header X-Forwarded-Port \$server_port;
# Timeouts
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# CORS headers
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
# Handle preflight requests
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 Access-Control-Max-Age 86400;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
# Monitor endpoint with stricter rate limiting
location /api/my/monitor/ {
limit_req zone=monitor burst=5 nodelay;
proxy_pass http://127.0.0.1:$SERVICE_PORT;
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;
# Cache static content
expires 30s;
add_header Cache-Control "public, no-transform";
}
# Health check endpoint
location /api/my/health {
proxy_pass http://127.0.0.1:$SERVICE_PORT;
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;
# No caching for health checks
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Block access to sensitive files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /404.html {
return 404 '{"error": "Not Found", "message": "MY Network endpoint not found"}';
add_header Content-Type application/json;
}
location = /50x.html {
return 500 '{"error": "Server Error", "message": "MY Network temporarily unavailable"}';
add_header Content-Type application/json;
}
}
EOF
# Активация сайта
ln -sf /etc/nginx/sites-available/my-network /etc/nginx/sites-enabled/
# Проверка конфигурации nginx
echo "🔍 Проверка конфигурации nginx..."
nginx -t
if [[ $? -ne 0 ]]; then
echo "❌ Ошибка в конфигурации nginx!"
exit 1
fi
# Настройка автообновления сертификатов
echo "🔄 Настройка автообновления сертификатов..."
cat > /etc/cron.d/certbot-renew << EOF
# Автообновление SSL сертификатов MY Network
0 12 * * * root certbot renew --quiet --post-hook "systemctl reload nginx"
EOF
# Запуск nginx
echo "🚀 Запуск nginx..."
systemctl enable nginx
systemctl start nginx
# Проверка статуса
sleep 2
if systemctl is-active --quiet nginx; then
echo "✅ Nginx запущен успешно"
else
echo "❌ Ошибка запуска nginx"
systemctl status nginx
exit 1
fi
# Проверка MY Network сервиса
echo "🔍 Проверка MY Network сервиса..."
if pgrep -f "python3 app/main.py" > /dev/null; then
echo "✅ MY Network сервис работает"
else
echo "⚠️ MY Network сервис не запущен, запускаем..."
cd /home/service/my-uploader-bot
sudo -u service ./run_my_network.sh
sleep 3
fi
# Финальная проверка
echo "🎯 Финальная проверка..."
echo ""
# Проверка HTTP -> HTTPS redirect
echo "📡 Проверка HTTP redirect..."
HTTP_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://$DOMAIN/ || echo "000")
if [[ "$HTTP_RESPONSE" == "301" ]]; then
echo "✅ HTTP -> HTTPS redirect работает"
else
echo "⚠️ HTTP redirect: $HTTP_RESPONSE"
fi
# Проверка HTTPS
echo "🔒 Проверка HTTPS..."
HTTPS_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" https://$DOMAIN/api/my/health || echo "000")
if [[ "$HTTPS_RESPONSE" == "200" ]]; then
echo "✅ HTTPS работает"
else
echo "❌ HTTPS не работает: $HTTPS_RESPONSE"
fi
# Проверка SSL сертификата
echo "🔐 Проверка SSL сертификата..."
SSL_INFO=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null || echo "SSL check failed")
if [[ "$SSL_INFO" != "SSL check failed" ]]; then
echo "✅ SSL сертификат валиден"
echo "$SSL_INFO"
else
echo "⚠️ Не удалось проверить SSL сертификат"
fi
echo ""
echo "🎉 MY Network Bootstrap Node с SSL настроен!"
echo "============================================"
echo ""
echo "🌐 Доступ:"
echo " https://$DOMAIN"
echo " https://$DOMAIN/api/my/health"
echo " https://$DOMAIN/api/my/bootstrap/config"
echo " https://$DOMAIN/api/my/monitor/"
echo ""
echo "🔒 Безопасность:"
echo " ✅ SSL/TLS сертификат от Let's Encrypt"
echo " ✅ HTTP -> HTTPS redirect"
echo " ✅ Security headers"
echo " ✅ Rate limiting"
echo " ✅ Firewall (UFW)"
echo ""
echo "🔄 Автообновление:"
echo " ✅ SSL сертификаты (cron)"
echo " ✅ MY Network сервис (cron)"
echo ""
echo "📊 Мониторинг:"
echo " systemctl status nginx"
echo " systemctl status my-network"
echo " tail -f /var/log/nginx/access.log"
echo " tail -f /var/log/nginx/error.log"
echo ""
echo "🎯 MY Network Bootstrap Node полностью готов!"
File diff suppressed because it is too large. Load diff
+320
View File
@@ -0,0 +1,320 @@
#!/bin/bash
# MY Network Direct Setup - для работы с файлами в /home/service
# Упрощенная версия без лишних проверок
set -e
echo "🚀 MY Network Direct Setup"
echo "========================="
echo "Работаем с файлами в /home/service"
echo "Домен: my-public-node-3.projscale.dev"
echo ""
# Проверка что мы root
if [[ $EUID -ne 0 ]]; then
echo "❌ Запустите от root: sudo bash setup_server_direct.sh"
exit 1
fi
DOMAIN="my-public-node-3.projscale.dev"
EMAIL="admin@projscale.dev"
# Переход в директорию проекта
cd /home/service
echo "📁 Содержимое /home/service:"
ls -la
# Обновление системы быстро
echo "🔄 Быстрое обновление системы..."
apt update
# Установка только необходимого
echo "📦 Установка базовых пакетов..."
apt install -y \
python3 \
python3-pip \
python3-venv \
nginx \
ufw \
curl \
wget
# Переход в my-uploader-bot если есть
if [[ -d "my-uploader-bot" ]]; then
cd my-uploader-bot
echo "✅ Найдена директория my-uploader-bot"
else
echo "❌ Директория my-uploader-bot не найдена!"
echo "Содержимое /home/service:"
ls -la /home/service/
exit 1
fi
# Создание Python venv
echo "🐍 Создание Python окружения..."
python3 -m venv venv
source venv/bin/activate
# Установка базовых пакетов Python
echo "📦 Установка Python пакетов..."
pip install --upgrade pip
pip install fastapi uvicorn sanic requests python-dotenv
# Создание минимального приложения MY Network
echo "🏗️ Создание минимального MY Network приложения..."
mkdir -p app/api
# Простое FastAPI приложение
cat > app/main.py << 'EOF'
#!/usr/bin/env python3
"""MY Network Bootstrap Node - Minimal Version"""
import os
import json
from datetime import datetime
from fastapi import FastAPI
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
app = FastAPI(
title="MY Network Bootstrap Node",
description="MY Network v2.0 Bootstrap Node - Minimal",
version="2.0.0"
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
NODE_ID = f"bootstrap-{int(datetime.now().timestamp())}"
DOMAIN = "my-public-node-3.projscale.dev"
@app.get("/")
async def root():
return {"message": "MY Network Bootstrap Node v2.0", "status": "active"}
@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", "monitor"],
"version": "2.0.0"
})
@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", "monitor"],
"protocol_version": "2.0",
"last_seen": datetime.utcnow().isoformat()
})
@app.get("/api/my/bootstrap/config")
async def bootstrap_config():
config = {
"version": "2.0",
"network_id": "my-network-main",
"bootstrap_nodes": [
{
"id": NODE_ID,
"host": DOMAIN,
"port": 443,
"ssl": True,
"public": True,
"region": "eu-central",
"capacity": "high",
"services": ["api", "monitor"],
"last_seen": datetime.utcnow().isoformat()
}
],
"network_config": {
"protocol_version": "2.0",
"max_peers": 100,
"sync_interval": 300
},
"api_endpoints": {
"base_url": f"https://{DOMAIN}",
"health": "/api/my/health",
"node_info": "/api/my/node/info",
"bootstrap": "/api/my/bootstrap/config"
}
}
return JSONResponse(config)
@app.get("/api/my/monitor/")
async def monitor_dashboard():
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>MY Network Bootstrap Monitor</title>
<meta charset="utf-8">
<style>
body {{ font-family: 'Courier New', monospace; background: #000; color: #0f0; padding: 20px; }}
h1 {{ color: #ff0; text-align: center; }}
.box {{ border: 1px solid #0f0; padding: 15px; margin: 10px 0; }}
.status {{ color: #0f0; }}
.info {{ color: #00f; }}
</style>
</head>
<body>
<h1>🚀 MY Network Bootstrap Node Monitor</h1>
<div class="box">
<h3 class="status">Node Status: ACTIVE</h3>
<p class="info">Node ID: {NODE_ID}</p>
<p class="info">Domain: {DOMAIN}</p>
<p class="info">Type: Bootstrap Primary</p>
<p class="info">Version: 2.0.0</p>
<p class="info">Services: API, Monitor</p>
<p class="info">Last Update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="box">
<h3 class="status">Network Configuration</h3>
<p class="info">Protocol Version: 2.0</p>
<p class="info">Max Peers: 100</p>
<p class="info">Public Access: Enabled</p>
<p class="info">SSL: Required</p>
</div>
<script>
setTimeout(() => location.reload(), 30000);
</script>
</body>
</html>
"""
return HTMLResponse(content=html)
if __name__ == "__main__":
print(f"🚀 Starting MY Network Bootstrap Node")
print(f"Domain: {DOMAIN}")
print(f"Node ID: {NODE_ID}")
uvicorn.run(app, host="0.0.0.0", port=15100)
EOF
# Создание systemd сервиса
echo "⚙️ Создание systemd сервиса..."
cat > /etc/systemd/system/my-network.service << EOF
[Unit]
Description=MY Network Bootstrap Node
After=network.target
[Service]
Type=simple
User=service
Group=service
WorkingDirectory=/home/service/my-uploader-bot
Environment=PATH=/home/service/my-uploader-bot/venv/bin
ExecStart=/home/service/my-uploader-bot/venv/bin/python app/main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Права доступа
chown -R service:service /home/service/
# Настройка nginx
echo "🌐 Настройка nginx..."
cat > /etc/nginx/sites-available/my-network << EOF
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
# Временный самоподписанный сертификат
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-MY-Network-Version "2.0";
server_tokens off;
# Main application
location / {
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
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
}
EOF
# Активация сайта
ln -sf /etc/nginx/sites-available/my-network /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Проверка nginx
nginx -t
# Простой firewall
echo "🔥 Настройка firewall..."
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
# SSH
ufw allow 22/tcp comment 'SSH'
# HTTP/HTTPS
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw --force enable
# Запуск сервисов
echo "🚀 Запуск сервисов..."
systemctl daemon-reload
systemctl enable my-network
systemctl start my-network
systemctl enable nginx
systemctl start nginx
# Проверка
sleep 5
echo ""
echo "✅ MY Network Bootstrap Node запущен!"
echo "=================================="
echo "🌐 Домен: https://$DOMAIN"
echo "🔌 Локальный порт: 15100"
echo ""
echo "🔍 Проверка:"
echo "systemctl status my-network"
echo "curl http://localhost:15100/api/my/health"
echo ""
echo "🎯 Bootstrap узел готов к работе!"
+318
View File
@@ -0,0 +1,318 @@
#!/bin/bash
# MY Network Simple Setup - без venv, прямо с системным Python
# Самый простой способ запуска
set -e
echo "🚀 MY Network Simple Setup"
echo "=========================="
echo "Пользователь: $(whoami)"
echo "Директория: $(pwd)"
echo ""
# Переход в my-uploader-bot
if [[ -d "my-uploader-bot" ]]; then
cd my-uploader-bot
echo "✅ Директория my-uploader-bot найдена"
else
echo "❌ Директория my-uploader-bot не найдена!"
echo "Содержимое текущей директории:"
ls -la
exit 1
fi
# Создание директорий
mkdir -p app/api
mkdir -p logs
# Проверка Python
echo "🐍 Проверка Python..."
python3 --version || { echo "❌ Python3 не найден"; exit 1; }
# Установка пакетов через pip --user
echo "📦 Установка Python пакетов (--user)..."
python3 -m pip install --user fastapi uvicorn requests python-dotenv
# Создание упрощенного MY Network приложения
echo "🏗️ Создание MY Network приложения..."
cat > app/main.py << 'EOF'
#!/usr/bin/env python3
"""MY Network Bootstrap Node - Simple Version"""
import os
import json
import sys
import logging
from datetime import datetime
from typing import Dict, Any
# Простой HTTP сервер без FastAPI
try:
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import socketserver
import threading
USE_SIMPLE_SERVER = True
except ImportError:
USE_SIMPLE_SERVER = True
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('logs/my-network.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger("MY-Network")
NODE_ID = f"bootstrap-simple-{int(datetime.now().timestamp())}"
DOMAIN = "my-public-node-3.projscale.dev"
PORT = 15100
class MyNetworkHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed_path = urlparse(self.path)
path = parsed_path.path
# Маршруты
if path == '/':
self.send_json_response({"message": "MY Network Bootstrap Node v2.0 - Simple", "status": "active"})
elif path == '/api/my/health':
self.send_json_response({
"status": "healthy",
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"mode": "simple",
"timestamp": datetime.utcnow().isoformat(),
"services": ["api", "monitor"],
"version": "2.0.0"
})
elif path == '/api/my/node/info':
self.send_json_response({
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "low",
"mode": "simple",
"services": ["api", "monitor"],
"protocol_version": "2.0",
"last_seen": datetime.utcnow().isoformat()
})
elif path == '/api/my/bootstrap/config':
config = {
"version": "2.0",
"network_id": "my-network-main",
"bootstrap_nodes": [
{
"id": NODE_ID,
"host": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "low",
"mode": "simple",
"services": ["api", "monitor"],
"last_seen": datetime.utcnow().isoformat()
}
],
"network_config": {
"protocol_version": "2.0",
"max_peers": 10,
"sync_interval": 300
},
"api_endpoints": {
"base_url": f"http://{DOMAIN}:{PORT}",
"health": "/api/my/health",
"node_info": "/api/my/node/info",
"bootstrap": "/api/my/bootstrap/config"
}
}
self.send_json_response(config)
elif path == '/api/my/monitor/' or path == '/api/my/monitor':
self.send_html_response(self.get_monitor_html())
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b'Not Found')
def send_json_response(self, data: Dict[Any, Any]):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
self.send_header('X-MY-Network-Version', '2.0')
self.end_headers()
json_data = json.dumps(data, indent=2)
self.wfile.write(json_data.encode('utf-8'))
def send_html_response(self, html: str):
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('X-MY-Network-Version', '2.0')
self.end_headers()
self.wfile.write(html.encode('utf-8'))
def get_monitor_html(self) -> str:
return f"""
<!DOCTYPE html>
<html>
<head>
<title>MY Network Bootstrap Monitor - Simple</title>
<meta charset="utf-8">
<style>
body {{ font-family: 'Courier New', monospace; background: #000; color: #0f0; padding: 20px; }}
h1 {{ color: #ff0; text-align: center; }}
.box {{ border: 1px solid #0f0; padding: 15px; margin: 10px 0; }}
.status {{ color: #0f0; }}
.info {{ color: #00f; }}
.warning {{ color: #f80; }}
</style>
</head>
<body>
<h1>🚀 MY Network Bootstrap Node Monitor</h1>
<div class="box">
<h3 class="status">Node Status: ACTIVE (Simple Mode)</h3>
<p class="info">Node ID: {NODE_ID}</p>
<p class="info">Domain: {DOMAIN}</p>
<p class="info">Port: {PORT}</p>
<p class="info">Type: Bootstrap Primary</p>
<p class="info">Version: 2.0.0</p>
<p class="info">Mode: Simple HTTP Server</p>
<p class="info">Services: API, Monitor</p>
<p class="info">Last Update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="box">
<h3 class="status">Network Configuration</h3>
<p class="info">Protocol Version: 2.0</p>
<p class="info">Max Peers: 10</p>
<p class="info">Public Access: Enabled</p>
<p class="warning">SSL: Disabled (Simple Mode)</p>
</div>
<div class="box">
<h3 class="warning">⚠️ Simple Mode</h3>
<p class="warning">Сервис запущен в упрощенном режиме</p>
<p class="warning">Использует встроенный HTTP сервер Python</p>
<p class="info">Доступ: http://{DOMAIN}:{PORT}</p>
</div>
<script>
setTimeout(() => location.reload(), 30000);
</script>
</body>
</html>
"""
def log_message(self, format, *args):
logger.info(f"{self.address_string()} - {format % args}")
def start_server():
logger.info(f"🚀 Starting MY Network Bootstrap Node - Simple Mode")
logger.info(f"Domain: {DOMAIN}")
logger.info(f"Port: {PORT}")
logger.info(f"Node ID: {NODE_ID}")
logger.info(f"Mode: Simple HTTP Server")
logger.info(f"Access: http://{DOMAIN}:{PORT}")
try:
with HTTPServer(("0.0.0.0", PORT), MyNetworkHandler) as httpd:
logger.info(f"✅ Server started on http://0.0.0.0:{PORT}")
httpd.serve_forever()
except Exception as e:
logger.error(f"❌ Server error: {e}")
raise
if __name__ == "__main__":
start_server()
EOF
# Создание скрипта запуска
cat > start_my_network.sh << 'EOF'
#!/bin/bash
cd /home/service/my-uploader-bot
echo "🚀 Запуск MY Network Bootstrap Node (Simple Mode)"
echo "==============================================="
echo ""
# Создание директории для логов
mkdir -p logs
# Запуск приложения
python3 app/main.py
EOF
chmod +x start_my_network.sh
# Создание скрипта для фонового запуска
cat > run_my_network.sh << 'EOF'
#!/bin/bash
# Проверка, запущен ли MY Network
if ! pgrep -f "python3 app/main.py" > /dev/null; then
echo "$(date): Запуск MY Network" >> /home/service/my-uploader-bot/logs/cron.log
cd /home/service/my-uploader-bot
nohup python3 app/main.py >> logs/app.log 2>&1 &
echo "$(date): MY Network запущен (PID: $!)" >> /home/service/my-uploader-bot/logs/cron.log
else
echo "$(date): MY Network уже запущен" >> /home/service/my-uploader-bot/logs/cron.log
fi
EOF
chmod +x run_my_network.sh
# Создание скрипта остановки
cat > stop_my_network.sh << 'EOF'
#!/bin/bash
echo "🛑 Остановка MY Network..."
if pgrep -f "python3 app/main.py" > /dev/null; then
pkill -f "python3 app/main.py"
echo "✅ MY Network остановлен"
echo "$(date): MY Network остановлен" >> /home/service/my-uploader-bot/logs/cron.log
else
echo "⚠️ MY Network не запущен"
fi
EOF
chmod +x stop_my_network.sh
# Добавление в crontab
echo "📅 Добавление в crontab..."
(crontab -l 2>/dev/null | grep -v "run_my_network.sh"; echo "*/5 * * * * /home/service/my-uploader-bot/run_my_network.sh") | crontab -
echo ""
echo "✅ MY Network Bootstrap Node установлен!"
echo "======================================="
echo ""
echo "🚀 Запуск:"
echo " cd /home/service/my-uploader-bot"
echo " ./start_my_network.sh # В терминале"
echo " ./run_my_network.sh # В фоне"
echo " ./stop_my_network.sh # Остановка"
echo ""
echo "🌐 Доступ:"
echo " http://my-public-node-3.projscale.dev:15100"
echo " http://my-public-node-3.projscale.dev:15100/api/my/health"
echo " http://my-public-node-3.projscale.dev:15100/api/my/monitor/"
echo ""
echo "📝 Логи:"
echo " tail -f logs/my-network.log"
echo " tail -f logs/app.log"
echo " tail -f logs/cron.log"
echo ""
echo "⚡ Автозапуск настроен через cron (каждые 5 минут)"
echo ""
echo "🎯 MY Network Bootstrap Node готов к работе!"
+291
View File
@@ -0,0 +1,291 @@
#!/bin/bash
# MY Network User Setup - без sudo, только для пользователя service
# Запуск MY Network в пользовательском пространстве
set -e
echo "🚀 MY Network User Setup (без sudo)"
echo "==================================="
echo "Пользователь: $(whoami)"
echo "Директория: $(pwd)"
echo ""
# Переход в my-uploader-bot
if [[ -d "my-uploader-bot" ]]; then
cd my-uploader-bot
echo "✅ Директория my-uploader-bot найдена"
else
echo "❌ Директория my-uploader-bot не найдена!"
echo "Содержимое текущей директории:"
ls -la
exit 1
fi
# Создание Python venv
echo "🐍 Создание Python окружения..."
python3 -m venv venv
source venv/bin/activate
# Обновление pip
echo "📦 Обновление pip..."
pip install --upgrade pip
# Установка базовых пакетов
echo "📦 Установка Python пакетов..."
pip install fastapi uvicorn sanic requests python-dotenv
# Создание директорий
mkdir -p app/api
mkdir -p logs
# Создание упрощенного MY Network приложения
echo "🏗️ Создание MY Network приложения..."
cat > app/main.py << 'EOF'
#!/usr/bin/env python3
"""MY Network Bootstrap Node - User Space Version"""
import os
import json
import asyncio
from datetime import datetime
from fastapi import FastAPI
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import logging
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('logs/my-network.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger("MY-Network")
app = FastAPI(
title="MY Network Bootstrap Node",
description="MY Network v2.0 Bootstrap Node - User Space",
version="2.0.0"
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
NODE_ID = f"bootstrap-user-{int(datetime.now().timestamp())}"
DOMAIN = "my-public-node-3.projscale.dev"
PORT = 15100
@app.on_event("startup")
async def startup():
logger.info(f"🚀 MY Network Bootstrap Node запущен")
logger.info(f"Node ID: {NODE_ID}")
logger.info(f"Domain: {DOMAIN}")
logger.info(f"Port: {PORT}")
@app.get("/")
async def root():
return {"message": "MY Network Bootstrap Node v2.0 - User Space", "status": "active"}
@app.get("/api/my/health")
async def health_check():
return JSONResponse({
"status": "healthy",
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"mode": "user-space",
"timestamp": datetime.utcnow().isoformat(),
"services": ["api", "monitor"],
"version": "2.0.0"
})
@app.get("/api/my/node/info")
async def node_info():
return JSONResponse({
"node_id": NODE_ID,
"node_type": "bootstrap",
"domain": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "medium",
"mode": "user-space",
"services": ["api", "monitor"],
"protocol_version": "2.0",
"last_seen": datetime.utcnow().isoformat()
})
@app.get("/api/my/bootstrap/config")
async def bootstrap_config():
config = {
"version": "2.0",
"network_id": "my-network-main",
"bootstrap_nodes": [
{
"id": NODE_ID,
"host": DOMAIN,
"port": PORT,
"ssl": False,
"public": True,
"region": "eu-central",
"capacity": "medium",
"mode": "user-space",
"services": ["api", "monitor"],
"last_seen": datetime.utcnow().isoformat()
}
],
"network_config": {
"protocol_version": "2.0",
"max_peers": 50,
"sync_interval": 300
},
"api_endpoints": {
"base_url": f"http://{DOMAIN}:{PORT}",
"health": "/api/my/health",
"node_info": "/api/my/node/info",
"bootstrap": "/api/my/bootstrap/config"
}
}
return JSONResponse(config)
@app.get("/api/my/monitor/")
async def monitor_dashboard():
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>MY Network Bootstrap Monitor - User Space</title>
<meta charset="utf-8">
<style>
body {{ font-family: 'Courier New', monospace; background: #000; color: #0f0; padding: 20px; }}
h1 {{ color: #ff0; text-align: center; }}
.box {{ border: 1px solid #0f0; padding: 15px; margin: 10px 0; }}
.status {{ color: #0f0; }}
.info {{ color: #00f; }}
.warning {{ color: #f80; }}
</style>
</head>
<body>
<h1>🚀 MY Network Bootstrap Node Monitor</h1>
<div class="box">
<h3 class="status">Node Status: ACTIVE (User Space)</h3>
<p class="info">Node ID: {NODE_ID}</p>
<p class="info">Domain: {DOMAIN}</p>
<p class="info">Port: {PORT}</p>
<p class="info">Type: Bootstrap Primary</p>
<p class="info">Version: 2.0.0</p>
<p class="info">Mode: User Space</p>
<p class="info">Services: API, Monitor</p>
<p class="info">Last Update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="box">
<h3 class="status">Network Configuration</h3>
<p class="info">Protocol Version: 2.0</p>
<p class="info">Max Peers: 50</p>
<p class="info">Public Access: Enabled</p>
<p class="warning">SSL: Disabled (User Space Mode)</p>
</div>
<div class="box">
<h3 class="warning">⚠️ User Space Mode</h3>
<p class="warning">Сервис запущен в пользовательском режиме</p>
<p class="warning">Для полной функциональности требуются root права</p>
<p class="info">Доступ: http://{DOMAIN}:{PORT}</p>
</div>
<script>
setTimeout(() => location.reload(), 30000);
</script>
</body>
</html>
"""
return HTMLResponse(content=html)
if __name__ == "__main__":
print(f"🚀 Starting MY Network Bootstrap Node - User Space")
print(f"Domain: {DOMAIN}")
print(f"Port: {PORT}")
print(f"Node ID: {NODE_ID}")
print(f"Mode: User Space (no root required)")
print(f"Access: http://{DOMAIN}:{PORT}")
print("")
uvicorn.run(app, host="0.0.0.0", port=PORT)
EOF
# Создание скрипта запуска
cat > start_my_network.sh << 'EOF'
#!/bin/bash
cd /home/service/my-uploader-bot
source venv/bin/activate
echo "🚀 Запуск MY Network Bootstrap Node (User Space)"
echo "==============================================="
echo ""
# Создание директории для логов
mkdir -p logs
# Запуск приложения
python app/main.py
EOF
chmod +x start_my_network.sh
# Создание cron задачи для автозапуска
echo "⏰ Создание задачи для автозапуска..."
cat > run_my_network.sh << 'EOF'
#!/bin/bash
# Проверка, запущен ли MY Network
if ! pgrep -f "python app/main.py" > /dev/null; then
echo "$(date): Запуск MY Network" >> /home/service/my-uploader-bot/logs/cron.log
cd /home/service/my-uploader-bot
source venv/bin/activate
nohup python app/main.py >> logs/app.log 2>&1 &
else
echo "$(date): MY Network уже запущен" >> /home/service/my-uploader-bot/logs/cron.log
fi
EOF
chmod +x run_my_network.sh
# Добавление в crontab
echo "📅 Добавление в crontab..."
(crontab -l 2>/dev/null; echo "*/5 * * * * /home/service/my-uploader-bot/run_my_network.sh") | crontab -
echo ""
echo "✅ MY Network Bootstrap Node установлен!"
echo "======================================="
echo ""
echo "🚀 Запуск вручную:"
echo " cd /home/service/my-uploader-bot"
echo " ./start_my_network.sh"
echo ""
echo "🚀 Запуск в фоне:"
echo " ./run_my_network.sh"
echo ""
echo "🌐 Доступ:"
echo " http://my-public-node-3.projscale.dev:15100"
echo " http://my-public-node-3.projscale.dev:15100/api/my/health"
echo " http://my-public-node-3.projscale.dev:15100/api/my/monitor/"
echo ""
echo "📝 Логи:"
echo " tail -f logs/my-network.log"
echo " tail -f logs/app.log"
echo ""
echo "⚠️ Примечание: Сервис работает в пользовательском режиме"
echo " Для полной функциональности требуются root права"
echo ""
echo "🎯 MY Network Bootstrap Node готов к работе!"
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/expect -f
set timeout 30
set password "DMUEjmnh6mDs/qlzhpjDzQ"
spawn ssh -o StrictHostKeyChecking=no service@2.58.65.188
expect {
"password:" {
send "$password\r"
exp_continue
}
"$ " {
interact
}
eof {
exit
}
}