v1.2.1.2: отказ сертификата на IP — с датой повтора; «без домена» продолжает установку вместо остановки

This commit is contained in:
2026-10-14 16:31:54 +03:00
parent b80c44077c
commit 1b85a4bb23
7 changed files with 49 additions and 7 deletions
+10
View File
@@ -1,3 +1,13 @@
## v1.2.1.2: сертификат на IP — с датой повтора; «без домена» продолжает установку
* **Отказ Let's Encrypt на IP теперь объясняется честно.** Как и для домена, при лимите в выводе дата,
после которой выпуск возможен, и прямо сказано, что порт 80 и файрвол тут не при чём. Раньше печатались
«частые причины» и человек шёл проверять хостера.
* **Пункт «без своего домена» больше не останавливает установку.** При отказе с сертификатом домена выбор
«3» продолжает работу сразу: маскировка берётся из соседей по подсети (или известный сайт, если соседей
нет), панель и подписка переключаются на IP, дальше установка идёт своим ходом. Перезапускать скрипт
и заново отвечать на вопросы не нужно.
## v1.2.1.1: сборка на новой базе автора (3X-UI KIT 1.2.1)
**Правило нумерации:** берём версию автора и через точку добавляем свою, начиная с 1. У автора 1.2.1 —
+1 -1
View File
@@ -1 +1 @@
1.2.1.1
1.2.1.2
+1 -1
View File
@@ -44,7 +44,7 @@
set -Eeuo pipefail
KIT_VERSION="1.2.1.1" # версия сборки форка; должна совпадать с VERSION релиза
KIT_VERSION="1.2.1.2" # версия сборки форка; должна совпадать с VERSION релиза
GITEA="${KIT_FORK_BASE:-https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS}"
NS="3x-ui-kit-release"
SIG_ID="releases@3x-ui-kit"
+20 -2
View File
@@ -39,7 +39,7 @@ wait_apt_idle() {
XUI_VERSION="v3.9.0"
# SHA256 установщика 3X-UI этой версии: тег могут передвинуть, а хеш – нет (проверено 2026-09-30).
XUI_INSTALL_SHA256="18616fe26c8f6c92db6daa2dcd7cd53c5143ee69ecfd26d8ea6dc9b2c78607a6"
KIT_VERSION="1.2.1.1"
KIT_VERSION="1.2.1.2"
# kit и kit-sub берём из того же релиза, что и этот скрипт, а не из меняющейся ветки main.
KIT_RAW="https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v$KIT_VERSION"
# Ядро Xray для панели. С 26.7.x клиенты на Mihomo и sing-box (Hiddify, FlClash,
@@ -451,11 +451,21 @@ issue_domain_cert() {
ip_cert_self_signed_fallback() {
local san="IP:$HOST"
[[ $HOST =~ ^[0-9.]+$ ]] || san="DNS:$HOST"
# Наш шов: если причина — лимит Let's Encrypt, говорим это прямо и с датой повтора, как для домена.
# Иначе человек читает «частые причины» и ищет проблему у хостера, которой нет.
local till
till=$(grep -rhoE 'retry after [0-9-]+ [0-9:]+ UTC' /var/log/3x-ui-install.log "$HOME"/.acme.sh/*/ca 2>/dev/null | tail -1 | sed 's/^retry after //')
if grep -rqsE 'rateLimited|too many certificates' /var/log/3x-ui-install.log 2>/dev/null; then
warn "Причина: лимит Let's Encrypt — на этот IP за 7 суток уже выпущено 5 сертификатов${till:+; повтор возможен после $till}. Это ограничение Let's Encrypt, а не вашего сервера: порт 80 и файрвол тут не при чём."
else
warn "Let's Encrypt не выдал сертификат на IP $HOST. Частые причины:"
{
echo " – лимит Let's Encrypt: 5 сертификатов в неделю на один IP;"
echo " – входящий порт 80 закрыт (у хостера или в файрволе);"
echo " – сбой у самого Let's Encrypt (лог: /var/log/3x-ui-install.log)."
} >&2
fi
{
echo " Можно продолжить с самоподписанным сертификатом: ссылки на подключения работают, браузер покажет"
echo " предупреждение, а подписка в приложениях может не открыться."
} >&2
@@ -1022,7 +1032,15 @@ kl_sni_menu() {
[[ -n $d ]] || continue
if domain_points_here "$d"; then DOMAIN=$d; SNI=$DOMAIN
else warn "оставляю прежний домен $DOMAIN — новый не указывает на этот сервер"; fi ;;
3) die "Установка остановлена по вашему выбору. Чтобы поставить без домена — перезапустите и выберите соседа по подсети или общедоступный сайт." ;;
3) # Наш шов: продолжаем без своего домена прямо здесь — маскировка соседом по подсети
# (или известным сайтом), панель и подписка по IP. Перезапускать установку не нужно.
local nb2
nb2=$(nearby_sites 2>/dev/null | shuf | head -1)
[[ -n $nb2 ]] || nb2=dl.google.com
DOMAIN=""; PANEL_ON=ip; LINK_HOST=$HOST
SNI=$nb2; SNI2=${SNI2:-$nb2}
ok "продолжаю без своего домена: маскировка ${B}$SNI${N}, панель и подписка — по IP"
break ;;
*) sleep 5 ;;
esac
done
+1 -1
View File
@@ -8,7 +8,7 @@
# Код выхода 1 при любом запуске (и при `__update_binary`) – старый `hy2 update` на нём
# останавливается и не заменяет команду hy2.
KIT_VERSION="1.2.1.1"
KIT_VERSION="1.2.1.2"
cat >&2 <<'MSG'
Отдельный установщик Hysteria2 больше не поддерживается.
+1 -1
View File
@@ -12,7 +12,7 @@
set -Eeuo pipefail
export LC_ALL=C.UTF-8 # ширина колонок по символам, а не байтам
KIT_VERSION="1.2.1.1"
KIT_VERSION="1.2.1.2"
KIT_RAW="https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main"
# Файлы новой версии берём из её тега, а не из меняющейся ветки main.
kit_ref_raw() { echo "https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v$1"; }
+15 -1
View File
@@ -289,6 +289,20 @@ def main():
' [[ $rc == 0 || $rc == 2 ]] || {\n # Наш шов: лимит Let\'s Encrypt — частая причина, и она не про сервер. Говорим прямо и с датой повтора.\n if grep -qE \'rateLimited|too many certificates\' "$log"; then\n local till\n till=$(grep -oE \'retry after [0-9-]+ [0-9:]+ UTC\' "$log" | tail -1 | sed \'s/^retry after //\')\n warn "Лимит Let\'s Encrypt: на имя ${B}$DOMAIN${N} за 7 суток уже выпущено 5 сертификатов${till:+ — повтор возможен после $till}. С вашим сервером всё в порядке: DNS, порты и ufw не при чём. Подождите до этой даты либо возьмите другое имя (например node3.…): лимит считается на точный набор имён."\n else\n warn "Let\'s Encrypt не выдал сертификат для $DOMAIN. Обычно дело в одном из трёх: A-запись ещё не обновилась, порт 80 закрыт у хостера или домен за проксированием Cloudflare. Лог: $log"\n fi\n return 1\n }\n',
'авто-шов: replace, строк 1',
),
(
'scripts/3x-ui.sh',
' local san="IP:$HOST"\n [[ $HOST =~ ^[0-9.]+$ ]] || san="DNS:$HOST"\n',
False,
' local san="IP:$HOST"\n [[ $HOST =~ ^[0-9.]+$ ]] || san="DNS:$HOST"\n # Наш шов: если причина — лимит Let\'s Encrypt, говорим это прямо и с датой повтора, как для домена.\n # Иначе человек читает «частые причины» и ищет проблему у хостера, которой нет.\n local till\n till=$(grep -rhoE \'retry after [0-9-]+ [0-9:]+ UTC\' /var/log/3x-ui-install.log "$HOME"/.acme.sh/*/ca 2>/dev/null | tail -1 | sed \'s/^retry after //\')\n if grep -rqsE \'rateLimited|too many certificates\' /var/log/3x-ui-install.log 2>/dev/null; then\n warn "Причина: лимит Let\'s Encrypt — на этот IP за 7 суток уже выпущено 5 сертификатов${till:+; повтор возможен после $till}. Это ограничение Let\'s Encrypt, а не вашего сервера: порт 80 и файрвол тут не при чём."\n else\n',
'авто-шов: insert, строк 2',
),
(
'scripts/3x-ui.sh',
' echo " – сбой у самого Let\'s Encrypt (лог: /var/log/3x-ui-install.log)."\n',
False,
' echo " – сбой у самого Let\'s Encrypt (лог: /var/log/3x-ui-install.log)."\n } >&2\n fi\n {\n',
'авто-шов: insert, строк 1',
),
(
'scripts/3x-ui.sh',
" _ _ _ _ _ _ _\n (_) |_ ___ _ __ ___ | |_| | ___ _| |__ _ __(_) ___| | __\n | | __/ __| '_ \\ / _ \\| __| |/ / | | | '_ \\| '__| |/ __| |/ /\n | | |_\\__ \\ | | | (_) | |_| <| |_| | |_) | | | | (__| <\n |_|\\__|___/_| |_|\\___/ \\__|_|\\_\\\\__,_|_.__/|_| |_|\\___|_|\\_\\\n",
@@ -356,7 +370,7 @@ def main():
'scripts/3x-ui.sh',
' issue_domain_cert || die "Без сертификата для $DOMAIN продолжать нельзя. Исправьте причину и запустите скрипт снова."\n',
False,
' # Наш шов: провал сертификата не обрывает установку. Человек может повторить попытку (DNS доехал,\n # лимит Let\'s Encrypt кончился) или ввести другое имя — установка продолжится с него же.\n while ! issue_domain_cert; do\n echo\n echo " ${B}Что делать дальше?${N}"\n echo " ${B}1${N} повторить попытку если ждали обновления A-записи или лимита Let\'s Encrypt"\n echo " ${B}2${N} ввести другой домен проверим, что он указывает на этот сервер, и повторим"\n echo " ${B}3${N} остановиться поставить без своего домена: перезапустите и выберите соседа по подсети"\n ask_tty " Выбор [1]: " || die "Сертификат для $DOMAIN не выпущен. Подробности: /var/log/kit-domain-cert.log"\n case ${REPLY//[[:space:]]/} in\n 2) ask_tty " адрес сайта (например vpn.example.com): " || continue\n local d=${REPLY//[[:space:]]/}\n [[ -n $d ]] || continue\n if domain_points_here "$d"; then DOMAIN=$d; SNI=$DOMAIN\n else warn "оставляю прежний домен $DOMAIN — новый не указывает на этот сервер"; fi ;;\n 3) die "Установка остановлена по вашему выбору. Чтобы поставить без домена — перезапустите и выберите соседа по подсети или общедоступный сайт." ;;\n *) sleep 5 ;;\n esac\n done\n',
' # Наш шов: провал сертификата не обрывает установку. Человек может повторить попытку (DNS доехал,\n # лимит Let\'s Encrypt кончился) или ввести другое имя — установка продолжится с него же.\n while ! issue_domain_cert; do\n echo\n echo " ${B}Что делать дальше?${N}"\n echo " ${B}1${N} повторить попытку если ждали обновления A-записи или лимита Let\'s Encrypt"\n echo " ${B}2${N} ввести другой домен проверим, что он указывает на этот сервер, и повторим"\n echo " ${B}3${N} остановиться поставить без своего домена: перезапустите и выберите соседа по подсети"\n ask_tty " Выбор [1]: " || die "Сертификат для $DOMAIN не выпущен. Подробности: /var/log/kit-domain-cert.log"\n case ${REPLY//[[:space:]]/} in\n 2) ask_tty " адрес сайта (например vpn.example.com): " || continue\n local d=${REPLY//[[:space:]]/}\n [[ -n $d ]] || continue\n if domain_points_here "$d"; then DOMAIN=$d; SNI=$DOMAIN\n else warn "оставляю прежний домен $DOMAIN — новый не указывает на этот сервер"; fi ;;\n 3) # Наш шов: продолжаем без своего домена прямо здесь — маскировка соседом по подсети\n # (или известным сайтом), панель и подписка по IP. Перезапускать установку не нужно.\n local nb2\n nb2=$(nearby_sites 2>/dev/null | shuf | head -1)\n [[ -n $nb2 ]] || nb2=dl.google.com\n DOMAIN=""; PANEL_ON=ip; LINK_HOST=$HOST\n SNI=$nb2; SNI2=${SNI2:-$nb2}\n ok "продолжаю без своего домена: маскировка ${B}$SNI${N}, панель и подписка — по IP"\n break ;;\n *) sleep 5 ;;\n esac\n done\n',
'авто-шов: replace, строк 1',
),
(