433 lines
14 KiB
Bash
433 lines
14 KiB
Bash
#!/bin/bash
|
||
|
||
# MY NETWORK UNIVERSAL INSTALLER
|
||
# Универсальный установщик для любого сервера с автопоиском проекта и полной настройкой
|
||
|
||
set -e
|
||
|
||
echo "=================================================="
|
||
echo "🚀 MY NETWORK UNIVERSAL INSTALLER"
|
||
echo "Универсальная установка и восстановление сервера"
|
||
echo "=================================================="
|
||
|
||
# Определение системы
|
||
OS_ID=$(lsb_release -i 2>/dev/null | cut -f2 || echo "unknown")
|
||
OS_VERSION=$(lsb_release -r 2>/dev/null | cut -f2 || echo "unknown")
|
||
|
||
echo "🖥️ Система: $OS_ID $OS_VERSION"
|
||
echo "👤 Пользователь: $(whoami)"
|
||
echo "📁 Текущая директория: $(pwd)"
|
||
|
||
# ===========================
|
||
# ПОИСК ПРОЕКТА
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 1. ПОИСК ПРОЕКТА ==="
|
||
|
||
PROJECT_LOCATIONS=(
|
||
"/home/myuploader/uploader-bot"
|
||
"/home/uploader-bot"
|
||
"/home/myuploader/my-uploader-bot"
|
||
"/root/uploader-bot"
|
||
"/root/my-uploader-bot"
|
||
"/opt/uploader-bot"
|
||
"/opt/my-uploader-bot"
|
||
"/var/www/uploader-bot"
|
||
"/var/www/my-uploader-bot"
|
||
"$(pwd)"
|
||
"$(pwd)/../uploader-bot"
|
||
"$(pwd)/../my-uploader-bot"
|
||
)
|
||
|
||
PROJECT_DIR=""
|
||
COMPOSE_FILE=""
|
||
|
||
echo "🔍 Поиск проекта в стандартных местах..."
|
||
for dir in "${PROJECT_LOCATIONS[@]}"; do
|
||
if [ -d "$dir" ]; then
|
||
for compose in "docker-compose.production.yml" "docker-compose.yml" "docker-compose.new.yml"; do
|
||
if [ -f "$dir/$compose" ]; then
|
||
PROJECT_DIR="$dir"
|
||
COMPOSE_FILE="$compose"
|
||
echo "✅ Проект найден: $PROJECT_DIR"
|
||
echo "✅ Compose файл: $COMPOSE_FILE"
|
||
break 2
|
||
fi
|
||
done
|
||
fi
|
||
done
|
||
|
||
if [ -z "$PROJECT_DIR" ]; then
|
||
echo "🔍 Глобальный поиск проекта..."
|
||
FOUND_PROJECTS=$(find / -name "docker-compose*.yml" -path "*/uploader-bot*" 2>/dev/null | head -3)
|
||
if [ -n "$FOUND_PROJECTS" ]; then
|
||
echo "Найдены проекты:"
|
||
echo "$FOUND_PROJECTS"
|
||
FIRST_FOUND=$(echo "$FOUND_PROJECTS" | head -1)
|
||
PROJECT_DIR=$(dirname "$FIRST_FOUND")
|
||
COMPOSE_FILE=$(basename "$FIRST_FOUND")
|
||
echo "✅ Выбран: $PROJECT_DIR"
|
||
else
|
||
echo "❌ Проект не найден автоматически!"
|
||
read -p "📝 Введите полный путь к директории проекта: " PROJECT_DIR
|
||
if [ ! -d "$PROJECT_DIR" ]; then
|
||
echo "❌ Директория не существует: $PROJECT_DIR"
|
||
exit 1
|
||
fi
|
||
# Найти compose файл
|
||
for compose in "docker-compose.production.yml" "docker-compose.yml" "docker-compose.new.yml"; do
|
||
if [ -f "$PROJECT_DIR/$compose" ]; then
|
||
COMPOSE_FILE="$compose"
|
||
break
|
||
fi
|
||
done
|
||
if [ -z "$COMPOSE_FILE" ]; then
|
||
echo "❌ Docker compose файл не найден в $PROJECT_DIR"
|
||
exit 1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
cd "$PROJECT_DIR"
|
||
echo "📁 Работаю в: $(pwd)"
|
||
|
||
# ===========================
|
||
# УСТАНОВКА ЗАВИСИМОСТЕЙ
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 2. УСТАНОВКА СИСТЕМНЫХ ЗАВИСИМОСТЕЙ ==="
|
||
|
||
# Обновление системы
|
||
echo "📦 Обновление системы..."
|
||
sudo apt update && sudo apt upgrade -y
|
||
|
||
# Установка основных пакетов
|
||
echo "📦 Установка базовых пакетов..."
|
||
sudo apt install -y curl wget git nginx ufw fail2ban htop nano net-tools
|
||
|
||
# Установка Docker
|
||
if ! command -v docker &> /dev/null; then
|
||
echo "🐳 Установка Docker..."
|
||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||
sudo sh get-docker.sh
|
||
sudo usermod -aG docker $USER
|
||
rm get-docker.sh
|
||
else
|
||
echo "✅ Docker уже установлен: $(docker --version)"
|
||
fi
|
||
|
||
# Установка Docker Compose
|
||
if ! command -v docker-compose &> /dev/null; then
|
||
echo "🐳 Установка Docker Compose..."
|
||
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||
sudo chmod +x /usr/local/bin/docker-compose
|
||
else
|
||
echo "✅ Docker Compose уже установлен: $(docker-compose --version)"
|
||
fi
|
||
|
||
# ===========================
|
||
# НАСТРОЙКА БЕЗОПАСНОСТИ
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 3. НАСТРОЙКА БЕЗОПАСНОСТИ ==="
|
||
|
||
# Настройка UFW
|
||
echo "🔥 Настройка файрвола..."
|
||
sudo ufw --force reset
|
||
sudo ufw default deny incoming
|
||
sudo ufw default allow outgoing
|
||
sudo ufw allow 22/tcp
|
||
sudo ufw allow 80/tcp
|
||
sudo ufw allow 443/tcp
|
||
sudo ufw --force enable
|
||
|
||
# Настройка fail2ban
|
||
echo "🛡️ Настройка fail2ban..."
|
||
sudo systemctl enable fail2ban
|
||
sudo systemctl start fail2ban
|
||
|
||
# ===========================
|
||
# ОЧИСТКА И ПОДГОТОВКА
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 4. ОЧИСТКА СТАРЫХ КОНТЕЙНЕРОВ ==="
|
||
|
||
echo "🛑 Останавливаю все контейнеры..."
|
||
docker stop $(docker ps -aq) 2>/dev/null || true
|
||
|
||
echo "🗑️ Удаляю старые контейнеры..."
|
||
docker rm $(docker ps -aq) 2>/dev/null || true
|
||
|
||
echo "🧹 Очистка системы Docker..."
|
||
docker system prune -af --volumes
|
||
|
||
# ===========================
|
||
# ПОДГОТОВКА ФАЙЛОВ
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 5. ПОДГОТОВКА КОНФИГУРАЦИИ ==="
|
||
|
||
# Создание .env файла если нет
|
||
if [ ! -f ".env" ]; then
|
||
echo "📝 Создание .env файла..."
|
||
if [ -f "env.example" ]; then
|
||
cp env.example .env
|
||
else
|
||
cat > .env << 'EOF'
|
||
# Database Configuration
|
||
DATABASE_URL=postgresql://myuser:mypassword@postgres:5432/mydb
|
||
POSTGRES_USER=myuser
|
||
POSTGRES_PASSWORD=mypassword
|
||
POSTGRES_DB=mydb
|
||
|
||
# Redis Configuration
|
||
REDIS_URL=redis://redis:6379
|
||
|
||
# Application Configuration
|
||
API_HOST=0.0.0.0
|
||
API_PORT=3000
|
||
DEBUG=false
|
||
|
||
# Security
|
||
SECRET_KEY=your-secret-key-here
|
||
|
||
# Telegram Bot (if needed)
|
||
BOT_TOKEN=your-bot-token
|
||
WEBHOOK_URL=https://your-domain.com
|
||
EOF
|
||
fi
|
||
echo "✅ .env файл создан"
|
||
fi
|
||
|
||
# Проверка requirements.txt
|
||
REQUIREMENTS_FILE="requirements.txt"
|
||
if [ ! -f "$REQUIREMENTS_FILE" ]; then
|
||
if [ -f "requirements_new.txt" ]; then
|
||
REQUIREMENTS_FILE="requirements_new.txt"
|
||
elif [ -f "requirements.compatible.txt" ]; then
|
||
REQUIREMENTS_FILE="requirements.compatible.txt"
|
||
fi
|
||
fi
|
||
echo "✅ Используется файл зависимостей: $REQUIREMENTS_FILE"
|
||
|
||
# ===========================
|
||
# NGINX КОНФИГУРАЦИЯ
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 6. НАСТРОЙКА NGINX ==="
|
||
|
||
cat > /tmp/nginx_universal.conf << 'EOF'
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
|
||
# Максимальный размер загружаемых файлов
|
||
client_max_body_size 100M;
|
||
|
||
# API проксирование
|
||
location /api/ {
|
||
proxy_pass http://localhost:3000/api/;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_connect_timeout 60s;
|
||
proxy_send_timeout 60s;
|
||
proxy_read_timeout 60s;
|
||
proxy_buffering off;
|
||
}
|
||
|
||
# Health check
|
||
location /health {
|
||
proxy_pass http://localhost:3000/api/health;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# Альтернативные порты
|
||
location /api5000/ {
|
||
proxy_pass http://localhost:5000/;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# WebSocket поддержка (если нужна)
|
||
location /ws/ {
|
||
proxy_pass http://localhost:3000/ws/;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# Статические файлы (если есть web2-client)
|
||
location / {
|
||
try_files $uri $uri/ @app;
|
||
}
|
||
|
||
# Fallback на приложение
|
||
location @app {
|
||
proxy_pass http://localhost:3000/;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
|
||
# Gzip сжатие
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_min_length 1024;
|
||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||
}
|
||
EOF
|
||
|
||
sudo mv /tmp/nginx_universal.conf /etc/nginx/sites-available/default
|
||
sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
|
||
|
||
# Удаление дефолтной страницы nginx
|
||
sudo rm -f /var/www/html/index.nginx-debian.html
|
||
|
||
echo "✅ Nginx конфигурация создана"
|
||
|
||
# ===========================
|
||
# ЗАПУСК ПРИЛОЖЕНИЯ
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 7. ЗАПУСК ПРИЛОЖЕНИЯ ==="
|
||
|
||
echo "🚀 Запуск Docker Compose..."
|
||
|
||
# Стратегия запуска: сначала базовые сервисы, потом приложение
|
||
echo "📊 Запуск базы данных и Redis..."
|
||
if docker-compose -f "$COMPOSE_FILE" up -d postgres redis 2>/dev/null; then
|
||
echo "✅ База данных запущена"
|
||
else
|
||
echo "⚠️ Ошибка запуска БД, пробую альтернативные имена сервисов..."
|
||
docker-compose -f "$COMPOSE_FILE" up -d db database mysql mariadb redis 2>/dev/null || true
|
||
fi
|
||
|
||
echo "⏳ Ждем запуска БД (15 секунд)..."
|
||
sleep 15
|
||
|
||
echo "🚀 Запуск основного приложения..."
|
||
if docker-compose -f "$COMPOSE_FILE" --profile main-node up -d 2>/dev/null; then
|
||
echo "✅ Main-node профиль запущен"
|
||
elif docker-compose -f "$COMPOSE_FILE" up -d app 2>/dev/null; then
|
||
echo "✅ Приложение запущено"
|
||
else
|
||
echo "⚠️ Пробую запустить все сервисы..."
|
||
docker-compose -f "$COMPOSE_FILE" up -d
|
||
fi
|
||
|
||
echo "⏳ Ждем запуска приложения (30 секунд)..."
|
||
sleep 30
|
||
|
||
# ===========================
|
||
# СОЗДАНИЕ SYSTEMD SERVICE
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 8. СОЗДАНИЕ SYSTEMD SERVICE ==="
|
||
|
||
cat > /tmp/mynetwork.service << EOF
|
||
[Unit]
|
||
Description=MY Network Service
|
||
After=docker.service
|
||
Requires=docker.service
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
RemainAfterExit=yes
|
||
WorkingDirectory=$PROJECT_DIR
|
||
ExecStart=/usr/bin/docker-compose -f $COMPOSE_FILE up -d
|
||
ExecStop=/usr/bin/docker-compose -f $COMPOSE_FILE down
|
||
TimeoutStartSec=300
|
||
User=root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
sudo mv /tmp/mynetwork.service /etc/systemd/system/
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable mynetwork
|
||
|
||
echo "✅ SystemD service создан и активирован"
|
||
|
||
# ===========================
|
||
# ФИНАЛЬНАЯ ПРОВЕРКА
|
||
# ===========================
|
||
echo ""
|
||
echo "=== 9. ФИНАЛЬНАЯ ПРОВЕРКА ==="
|
||
|
||
# Перезапуск nginx
|
||
sudo nginx -t && sudo systemctl restart nginx
|
||
echo "✅ Nginx перезапущен"
|
||
|
||
# Проверка статуса
|
||
echo "📊 Статус контейнеров:"
|
||
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
|
||
|
||
echo ""
|
||
echo "🔍 Тестирование соединений:"
|
||
sleep 10
|
||
|
||
# Тест локальных портов
|
||
for port in 3000 5000 8080; do
|
||
if timeout 5 curl -s http://localhost:$port/api/health > /dev/null 2>&1; then
|
||
echo "✅ localhost:$port/api/health - РАБОТАЕТ"
|
||
else
|
||
echo "❌ localhost:$port/api/health - НЕ РАБОТАЕТ"
|
||
fi
|
||
done
|
||
|
||
# Тест nginx proxy
|
||
if timeout 5 curl -s http://localhost/api/health > /dev/null 2>&1; then
|
||
echo "✅ nginx proxy (/api/health) - РАБОТАЕТ"
|
||
else
|
||
echo "❌ nginx proxy (/api/health) - НЕ РАБОТАЕТ"
|
||
fi
|
||
|
||
if timeout 5 curl -s http://localhost/health > /dev/null 2>&1; then
|
||
echo "✅ nginx proxy (/health) - РАБОТАЕТ"
|
||
else
|
||
echo "❌ nginx proxy (/health) - НЕ РАБОТАЕТ"
|
||
fi
|
||
|
||
# ===========================
|
||
# РЕЗУЛЬТАТ
|
||
# ===========================
|
||
echo ""
|
||
echo "=================================================="
|
||
echo "🎉 УСТАНОВКА ЗАВЕРШЕНА!"
|
||
echo "=================================================="
|
||
|
||
echo ""
|
||
echo "📊 ИНФОРМАЦИЯ О СИСТЕМЕ:"
|
||
echo "Проект: $PROJECT_DIR"
|
||
echo "Compose: $COMPOSE_FILE"
|
||
echo "Внешний IP: $(curl -s ifconfig.me 2>/dev/null || echo "неизвестно")"
|
||
|
||
echo ""
|
||
echo "🌐 ТЕСТИРОВАНИЕ:"
|
||
EXTERNAL_IP=$(curl -s ifconfig.me 2>/dev/null || echo "YOUR_SERVER_IP")
|
||
echo "curl -I http://$EXTERNAL_IP/api/health"
|
||
echo "curl -I http://$EXTERNAL_IP/health"
|
||
|
||
echo ""
|
||
echo "🔍 ДИАГНОСТИКА (если нужна):"
|
||
echo "docker ps"
|
||
echo "docker logs \$(docker ps --format \"{{.Names}}\" | grep app | head -1)"
|
||
echo "sudo systemctl status mynetwork"
|
||
echo "sudo journalctl -u nginx -f"
|
||
|
||
echo ""
|
||
echo "🛠️ УПРАВЛЕНИЕ:"
|
||
echo "Запуск: sudo systemctl start mynetwork"
|
||
echo "Остановка: sudo systemctl stop mynetwork"
|
||
echo "Перезапуск: sudo systemctl restart mynetwork"
|
||
echo "Статус: sudo systemctl status mynetwork"
|
||
|
||
echo ""
|
||
echo "✅ MY Network готов к работе!" |