#!/usr/bin/env bash set -euo pipefail ################################# # DEBUG TRAP ################################# trap 'echo -e "\033[1;31m[ERROR]\033[0m Ошибка в строке $LINENO"; exit 1' ERR ################################# # HELPER FUNCTIONS ################################# log() { echo -e "\033[1;32m[INFO]\033[0m $1"; } die() { echo -e "\033[1;31m[ERROR]\033[0m $1"; exit 1; } need_root() { [[ $EUID -eq 0 ]] || die "Запускать только от root" } validate_url() { [[ "$1" =~ ^https?://[^/]+:[0-9]+/.+ ]] } ################################# # CHECKS ################################# need_root # Check OS and set release variable . /etc/os-release if [[ "$ID" != "ubuntu" && "$ID" != "debian" ]]; then die "Этот скрипт поддерживает только Ubuntu или Debian: $ID" fi if ! x-ui status >/dev/null 2>&1; then echo "❌ Панель 3x-ui не найдена или не работает." echo " Чтобы установить, выполните:" echo "bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)" exit 1 fi echo "✔ Панель 3x-ui найдена и работает" ################################# # ASCII-баннер ################################# echo "===================================================" echo " ____ ____ _ ___ _ " echo " / __ \___ ____ / __ \(_) (_)___ ______(_)___ ___ " echo " / / / / _ \/ __ \/ /_/ / / / / __ \/ ___/ / __ \`__ \ " echo " / /_/ / __/ / / / ____/ / / / /_/ / / / / / / / / /" echo "/_____/\___/_/ /_/_/ /_/_/_/\__, /_/ /_/_/ /_/ /_/ " echo " /____/ " echo "" echo " 3DP-MANAGER FOR 3X-UI " echo "===================================================" echo "" ################################# # INPUT / USER DATA ################################# # Function to get panel URL from 3x-ui get_xui_url() { local output=$(x-ui settings 2>/dev/null || true) echo "$output" | sed 's/\x1b\[[0-9;]*m//g' | grep "Access URL:" | grep -oE 'https?://[^[:space:]]+' | head -n1 || true } echo "Определяем URL панели 3x-ui..." UI_URL=$(get_xui_url) if [[ -z "$UI_URL" ]]; then echo "Не удалось автоматически получить URL" read -rp "Введите URL панели 3x-ui вручную: " UI_URL fi UI_URL=$(echo "$UI_URL" | sed -E 's/[[:space:]]*$//; s|/*$||') # Validate URL correctness validate_url "$UI_URL" || die "Некорректный URL панели 3x-ui: $UI_URL" echo "URL панели 3x-ui: $UI_URL" read -rp "Логин 3x-ui: " UI_LOGIN read -rsp "Пароль 3x-ui: " UI_PASSWORD echo [[ -z "$UI_LOGIN" || -z "$UI_PASSWORD" ]] && die "Логин/пароль обязательны" # Check login if ! command -v curl >/dev/null 2>&1; then echo "❌ curl не установлен. Установите curl и повторите попытку" echo " sudo apt install -y curl" exit 1 fi LOGIN_RESPONSE=$(curl -s -X POST "$UI_URL/login" -H "Content-Type: application/json" -d "{\"username\":\"$UI_LOGIN\",\"password\":\"$UI_PASSWORD\"}" || true) if ! echo "$LOGIN_RESPONSE" | grep -q '"success":true'; then echo "Не удалось залогиниться в 3x-ui. Проверьте URL, логин и пароль." exit 1 fi echo "✔ Успешный логин в 3x-ui" # Parse UI_URL UI_HOST=$(echo "$UI_URL" | awk -F[/:] '{print $4}') # domain or IP UI_PROTO=$(echo "$UI_URL" | awk -F: '{print $1}') # http or https if [[ "$UI_PROTO" == "https" ]]; then log "HTTPS панель обнаружена, проверяем SSL сертификаты" DEFAULT_CERT="/etc/letsencrypt/live/$UI_HOST/fullchain.pem" DEFAULT_KEY="/etc/letsencrypt/live/$UI_HOST/privkey.pem" if [[ -f "$DEFAULT_CERT" && -f "$DEFAULT_KEY" ]]; then CERT_PATH="$DEFAULT_CERT" KEY_PATH="$DEFAULT_KEY" log "Найдены сертификаты Let's Encrypt для $UI_HOST" else log "⚠ Сертификаты Let's Encrypt для $UI_HOST не найдены" read -rp "Введите полный путь к SSL сертификату (fullchain.pem): " CERT_PATH read -rp "Введите полный путь к SSL ключу (privkey.pem): " KEY_PATH [[ -f "$CERT_PATH" ]] || die "Файл сертификата не найден: $CERT_PATH" [[ -f "$KEY_PATH" ]] || die "Файл ключа не найден: $KEY_PATH" fi fi # Input rotation interval read -rp "Интервал генерации инбаундов в минутах (от 10, по умолчанию 30): " ROTATE_INTERVAL ROTATE_INTERVAL="${ROTATE_INTERVAL:-30}" # Check that it's a number and ≥10 if ! [[ "$ROTATE_INTERVAL" =~ ^[0-9]+$ ]] || [ "$ROTATE_INTERVAL" -lt 10 ]; then echo "Неверное значение. Используется значение по умолчанию 30 минут." ROTATE_INTERVAL=30 fi echo "Интервал ротации установлен: $ROTATE_INTERVAL минут" PROJECT_DIR="/opt/3dp-manager" log "Используется директория проекта: $PROJECT_DIR" mkdir -p "$PROJECT_DIR" cd "$PROJECT_DIR" ################################# # Get country flag ################################# REPO_BASE="https://raw.githubusercontent.com/denpiligrim/3dp-manager/dp-fix" COUNTRY_FLAG="" # Get countryCode IP_JSON=$(curl -s --fail http://ip-api.com/json/ || true) [ -z "$IP_JSON" ] && exit 0 if ! command -v jq >/dev/null 2>&1; then echo "❌ Не найден jq. Для работы скрипта необходимо установить jq." echo " sudo apt install -y jq" exit 1 fi COUNTRY_CODE=$(echo "$IP_JSON" | jq -r '.countryCode // empty' 2>/dev/null || true) [ -z "$COUNTRY_CODE" ] && exit 0 # Flags JSON URL FLAGS_JSON_URL="$REPO_BASE/app/assets/flags.json" FLAGS_JSON=$(curl -s "$FLAGS_JSON_URL" || true) [ -z "$FLAGS_JSON" ] && exit 0 # emoji COUNTRY_FLAG=$(echo "$FLAGS_JSON" | jq -r --arg code "$COUNTRY_CODE" '.[] | select(.code == $code) | .emoji // empty' 2>/dev/null | head -n1) ################################# # Whitelist ################################# if curl -fsSL "$REPO_BASE/whitelist.txt" -o whitelist.txt; then log "whitelist.txt скопирован" else log "⚠ Не удалось скачать whitelist.txt" fi ################################# # TOKEN GENERATION ################################# SUB_TOKEN=$(date +%s%N | sha256sum | cut -c1-16) log "Сгенерирован токен подписки" ################################# # DOCKER ################################# log "Проверка Docker" if command -v docker >/dev/null 2>&1; then log "Docker уже установлен" else log "Docker не найден, будет установлен из официального репозитория" # Add Docker's official GPG key: sudo apt update sudo apt install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings if [[ "$ID" == "ubuntu" ]]; then curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc || die "Ошибка добавления ключа Docker" else curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc || die "Ошибка добавления ключа Docker" fi sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: CODENAME=${UBUNTU_CODENAME:-$VERSION_CODENAME} sudo tee /etc/apt/sources.list.d/docker.sources < .env < docker-compose.yml < nginx.conf < docker-compose.yml < nginx.conf </dev/null || die "Backend не запущен" docker compose ps | grep nginx >/dev/null || die "Nginx не запущен" ################################# # RESULT ################################# log "✔ Установка завершена" echo echo "URL подписки:" echo "$SUB_URL"