Release 6.6.0 — panel/node 3.3.0, subscription-page 8.0.0, resilient self-update
Release 6.6.0
Совместимость с panel 3.3.0 и node 3.3.0 (вышли 18.08.2026), поддержка subscription-page 8.0.0 и отказоустойчивое самообновление скриптов.
Версии в этом релизе: remnawave.sh v6.6.0 · remnanode.sh v4.5.0
⚠️ Главное: нода 3.3.0+ работает только с панелью 3.3.0+
Начиная с 3.3.0 нода поднимает HTTPS-листенер с SNICallback, который отклоняет любой TLS-handshake, если SNI ≠ deriveSni(caCert, jwtPublicKey) (node@3.3.0/src/main.ts). Клиентская половина — deriveSni() в backend/src/common/utils/certs/generate-servername.util.ts — появилась только в 3.3.0 (на теге 3.2.3 файла ещё нет).
Итог:
| Панель | Нода | Результат |
|---|---|---|
| 3.3.0+ | 3.3.0+ | ✅ |
| 3.3.0+ | ≤ 3.2.2 | ✅ (старая нода игнорирует SNI) |
| ≤ 3.2.3 | 3.3.0+ | ❌ unknown sni, нода числится офлайн |
Раньше remnanode.sh ставил и обновлял :latest без всякой проверки. Теперь:
- установка и
updateодин раз спрашивают, обновлена ли панель, и запоминают ответ в$APP_DIR/.panel-compat-ack; - появился
update --tag VERSION— можно вернуться на старую линию:remnanode update --tag 3.2.2; - гейт оценивает запрошенный тег и срабатывает до любых записей, поэтому отказ не меняет установку.
🚀 remnanode.sh 4.4.0 → 4.5.0
upиrestartбольше не делаютdocker pull. Это команды жизненного цикла, а не обновление: раньше простой рестарт молча переводил ноду на плавающем теге на свежий релиз. Образ тянется только при первом старте, когда локально его вообще нет.update --tag Xперепинивает уже установленную ноду: результатsedпроверяется, а контейнер пересоздаётся даже если нужный образ уже лежит локально (раньше это был тихий no-op).- Обновление также срабатывает, когда запущенный контейнер разошёлся с образом из
docker-compose.yml(например, прошлый апдейт прервали после pull). XTLS_API_PORTбольше не может сорвать установку. Переменную выпилили из схемы конфигурации ноды ещё в 2.8.0 (её заменил внутреннийXTLS_API_SOCKET_PATH), но занятый порт 61000 до сих пор ронялinstall --force. Теперь порт просто подбирается свободный.
🌊 remnawave.sh 6.5.0 → 6.6.0
Порт subscription-page был мёртвым
Генерировался маппинг '127.0.0.1:<host>:${APP_PORT:-3010}', но Compose подставляет ${APP_PORT} из проектного .env (панельного, APP_PORT=3000) и никогда из env_file сервиса. Проверка docker compose config показывала published: 3010 → target: 3000 — то есть http://127.0.0.1:3010 не отвечал. Проблема была не видна только тем, кто использует встроенный Caddy (он ходит в контейнер по docker-сети).
Теперь обе стороны фиксированные, а migrate_subpage_compose_ports чинит уже установленные панели, синхронизируя .env.subscription и SUB_PORT у Caddy.
/assets/* на одном домене больше не роняет панель
Панель и subscription-page обе отдают /assets/*. Старый блок с двумя апстримами и lb_policy first не мог сделать фолбэк: subscription-page 8.0.0 рвёт соединение (без HTTP-статуса) для /assets без валидной session-cookie, поэтому Caddy отдавал 502 на все ассеты панели.
Теперь запросы разделяются по Referer: панель отдаёт <meta name="referrer" content="no-referrer">, поэтому её ассеты приходят без Referer, а subscription-page присылает полный same-origin URL с /<префикс>/. migrate_caddyfile перегенерирует существующие Caddyfile (файл .env при этом только дополняется — учётные данные Caddy-security остаются валидными).
Остальное
- Апстримы и имя docker-сети у Caddy берутся из имени установки, а не захардкожены в
remnawave*— раньше всё ломалось на любой установке с--name. install-subpageписал.env.subscriptionбез обязательногоREMNAWAVE_PANEL_URLи с пустымREMNAWAVE_API_TOKEN, из-за чего контейнер не стартовал. Теперь файл полный, а без токена команда не продолжится.- Standalone-установка публикует порт, подбирает свободный, если 3010 занят, и тоже требует токен.
- Добавлен
TRUST_PROXY=1(в новые и существующие.env.subscription),CADDY_VERSION2.10.2 → 2.11.4.
🔄 Железобетонное самообновление (оба скрипта)
- Загрузка идёт по списку зеркал:
raw.githubusercontent, затем четыре CDN jsDelivr (cdn/fastly/gcore/testingcf). Актуально там, где GitHub заблокирован. - Файл принимается, только если у него есть shebang, строка версии, правдоподобный размер и он парсится через
bash -n. Страница капивного портала, ошибка CDN или оборванная закачка больше не могут заменить рабочий CLI. - Новая версия ставится без вопросов и скрипт перезапускается с исходными аргументами — больше никаких «обновились, запустите команду ещё раз».
- Даунгрейд запрещён, недоступный
/usr/local/binдаёт предупреждение и работу с текущей версией, защита от цикла re-exec.
Обновить только сам CLI (контейнеры не трогаются) — это команда install-script, а не install:
sudo remnawave install-script # или: sudo remnawave update-script
sudo remnanode install-script
# если GitHub заблокирован — то же самое через зеркало
sudo bash <(curl -Ls https://cdn.jsdelivr.net/gh/DigneZzZ/remnawave-scripts@main/remnawave.sh) @ install-script
sudo bash <(curl -Ls https://cdn.jsdelivr.net/gh/DigneZzZ/remnawave-scripts@main/remnanode.sh) @ install-scriptinstall разворачивает саму панель/ноду — для обновления скрипта она не нужна. Отдельно вызывать это обычно не приходится: update сам обновляет CLI перед всем остальным.
✅ Проверено
bash -nдля обоих скриптов.- Генерируемый compose проходит
docker compose config— и для обычной установки, и для--name. - Все четыре варианта Caddyfile проходят
caddy validateнаcaddy:2.11.4иremnawave/caddy-with-auth. - Разделение
/assetsпроверено на живом Caddy: без Referer → панель, Referer с/sub/→ subscription-page, устаревшая session-cookie → всё равно панель. - Миграции прогнаны под GNU sed в Linux-контейнере: корректны, идемпотентны, не трогают порты панели и БД.
- Фолбэк зеркал проверен на локальном сервере с 404 / HTML / обрезанным / несинтаксичным ответом; самообновление, re-exec, отказ от даунгрейда и недоступный таргет — все пути пройдены.
Full Changelog: 5.7.0...6.6.0