Skip to content

About

Установщик одной командой для VPS-ноды Remnawave: nginx + Let's Encrypt, XHTTP-профиль Xray, сайт-заглушка и переустановка Remnawave Node

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

66 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

node-setup

Установщик одной командой для VPS-ноды на Remnawave: TLS-фронт на nginx для XHTTP-профиля Xray, сайт-заглушка и переустановка Remnawave Node в Docker.

One command to turn a fresh Debian/Ubuntu VPS into a Remnawave node behind nginx + Let's Encrypt, with an XHTTP Xray profile and a static site on every other path.

Текущая версия: 1.6.0 — публичный HTTPS-порт теперь свой (случайный свободный, не 443; --https-port N), вместе с установкой ставится Psiphon (egress для Gemini, --no-psiphon — пропустить), в правило Gemini профиля добавлены 5 доменов. Установки до 1.6.0 остаются на 443. Подробности — в CHANGELOG.md.


Быстрый старт

На VPS, от root (нужны Debian или Ubuntu):

bash <(curl -fsSL https://raw.githubusercontent.com/goji-app/goji-node-setup/main/xhttp-tls/install.sh)

Скрипт сам спросит всё нужное:

Вопрос Что ввести
Домен сервера домен, A-запись которого уже указывает на этот VPS
SECRET_KEY ноды ключ из Remnawave: Nodes → ваша нода (при переустановке Enter оставит текущий)
NODE_PORT порт API ноды для панели, по умолчанию 2222
IP панели с него будет разрешён доступ к NODE_PORT (Enter — не создавать правило файрвола)
E-mail для Let's Encrypt (можно пропустить)

Все ответы можно передать флагами, тогда вопросов не будет:

bash install.sh node.example.com --secret-key '...' --node-port 2222 --panel-ip 203.0.113.10 --email me@example.com

Перед запуском: нода добавлена в панели, домен указывает на сервер, порт 80 свободен для nginx. Порт 443 не нужен: HTTPS-порт скрипт выбирает сам (случайный свободный), его можно задать --https-port N.


Как это работает

flowchart LR
    C[Клиент] -- "TLS 1.2/1.3, h2, :HTTPS-порт" --> N[nginx]
    N -- "/случайный/путь/  (h2c)" --> X["Xray XHTTP<br/>127.0.0.1:10443"]
    N -- "любой другой путь" --> S[Статический сайт-заглушка]
    N -. "чужой SNI / голый IP" .-> D[обрыв рукопожатия]
    P[Панель Remnawave] -- "NODE_PORT, только с IP панели" --> R[Remnawave Node]
    R --- X
Loading
  • nginx держит публичный HTTPS-порт (случайный свободный в диапазоне 20000–32000, не 443; хранится в /etc/goji-node/install.conf) и сертификат Let's Encrypt, а Xray слушает только 127.0.0.1. Порт 80 остаётся для проверки Let's Encrypt и редиректа (на https://домен:порт).
  • Путь XHTTP проксируется в Xray, все остальные пути отдают статический сайт. На каждой новой установке путь случайный (вида /assets/sync/3f9a1c0b7d2e/), при переустановке сохраняется прежний; задать свой — --path, сменить на новый случайный — --path random (после этого обновите профиль и хост в Remnawave). Общий путь /api/v2/telemetry/ из старых версий goji-node check помечает предупреждением: по нему ноду можно найти одним запросом.
  • Запрос с неизвестным именем сервера или по голому IP получает обрыв TLS-рукопожатия.
  • Remnawave Node запускается в Docker с network_mode: host, чтобы Xray и nginx видели друг друга на 127.0.0.1.

Что делает скрипт

Шаг Действие
1. Вопросы домен, SECRET_KEY, порт API, IP панели, e-mail, выбор сайта-заглушки из меню — самый первый вопрос (если не задан --template). Работает и через curl … | bash: ввод читается с терминала
2. Пакеты nginx, certbot, curl и зависимости из репозиториев дистрибутива
3. Проверка DNS предупреждает, если домен указывает не на этот сервер, иначе сертификат не выпустится
4. Заглушка разворачивает выбранный шаблон сайта в /var/www/decoy; все шаблоны остаются в /usr/share/goji-node/templates для смены заглушки без переустановки
5. nginx :80 отвечает на проверку Let's Encrypt, всё остальное перенаправляет на HTTPS (с номером порта); при активном ufw открывает 80 и HTTPS-порт
6. Сертификат выпуск через webroot и автопродление с перезагрузкой nginx, после чего выполняется проверка certbot renew --dry-run. Если папка сертификата осталась без конфигурации продления, её старые файлы переносятся в /root/letsencrypt-backup-…
7. Remnawave Node ставит Docker при необходимости, сохраняет старый docker-compose.yml в .bak-<дата>, пишет новый, скачивает образ remnawave/node:latest, закрепляет его по digest (image: remnawave/node@sha256:…) и запускает
8. Ожидание профиля ждёт, пока в панели профиль ноды переключат на XHTTP (Xray слушает 127.0.0.1:10443, HTTPS-порт свободен). До этого nginx на HTTPS-порту не включается, а старый профиль продолжает работать
9. nginx, HTTPS-порт включает TLS-фронт
10. Самопроверка заглушка отвечает кодом 200, Xray слушает внутренний порт
11. Профиль для Remnawave выводит готовый JSON профиля (с вашими портом и путём) для копирования в Remnawave → Config Profiles; он же сохраняется в /etc/goji-node/remnawave-profile.json. Если профиль ещё не применён, JSON выводится до ожидания, чтобы его можно было вставить сразу

Скрипт можно запускать повторно: уже выпущенный и автопродляемый сертификат он не трогает, установленная заглушка остаётся прежней.

Флаги

Флаг По умолчанию Назначение
<домен> спросит домен ноды (первый аргумент)
--email — e-mail для Let's Encrypt
--secret-key спросит SECRET_KEY ноды
--node-port 2222 порт API ноды для панели
--panel-ip — IP панели; для NODE_PORT в ufw создаётся правило только для него, а оставшееся от прежней установки правило «всем» (ALLOW Anywhere) снимается
--xray-port 10443 внутренний порт Xray на 127.0.0.1
--https-port случайный свободный (20000–32000) публичный HTTPS-порт nginx. Не 80, не порты Xray/ноды/SSH. При переустановке остаётся прежний (у установок до 1.6.0 — 443); смена порта требует обновить host в Remnawave. --https-port 443 — вернуть стандартный
--psiphon / --no-psiphon ставит на новой установке vps-psiphon: Psiphon-туннель в Docker как egress для доменов Gemini (SOCKS5 на адресе docker0, порт случайный, HTTP-прокси не публикуется). Уже установленный vps-psiphon скрипт не трогает; --psiphon переустановит. Сбой Psiphon установку не прерывает
--psiphon-args — дополнительные параметры для vps-psiphon в кавычках, например --psiphon-args "--region DE --bulk-test-mb 0"
--path случайный путь XHTTP, начинается и заканчивается на /; random — новый случайный; без флага при переустановке остаётся прежний
--template меню / random заглушка: random, analytics, blog, docs, saas, freelancer, resume, creative, grayscale, new-age, agency, livecams. Без флага на терминале показывается меню выбора, без терминала берётся случайная
--wait 900 сколько секунд ждать переключения профиля в панели
--skip-node — не трогать Remnawave Node, настроить только nginx и сертификат
--skip-hardening — не применять тюнинг и защиту (BBR/fq, tc, ZRAM, UFW, Fail2ban, ICMP)
--icmp-drop — полностью блокировать входящий ping (по умолчанию лимит 5/сек)
--traffic-control / --no-traffic-control спросить блокировка сетей сканеров по публичным спискам (nftables), по желанию
--admin-ip IP SSH-сессии IP администратора, исключённый из блокировок Traffic Control, флаг можно повторять
--upgrade-os / --no-upgrade-os спросить обновить пакеты текущего релиза ОС (apt upgrade) перед установкой; план с удалениями отклоняется
--check — отчёт «компонент — статус» (то же: goji-node check)
--fix — найти ошибки и исправить безопасные автоматически (то же: goji-node fix [--dry-run])
--uninstall — меню удаления компонентов установки (сайт, сертификат, нода, защита, тюнинг, SSH, Fail2ban, правила UFW, goji-node); подробности в INSTALL.md
--settings — показать настройки, с которыми сервер был установлен (то же: goji-node settings). На уже настроенном сервере запуск без параметров сначала предлагает меню: проверка, настройки, goji-node, переустановка
--resume — повторить установку с сохранёнными параметрами
--version — версия установщика
--update / --check-update — скачать новую версию с GitHub / только проверить (то же: goji-node update)
--no-update-check — отключить проверку и уведомления об обновлениях
--ssh-port определяется порт SSH для UFW и Fail2ban
--ssh-keys-only / --no-ssh-keys-only спросить вход по SSH только по ключу: отключает пароль и keyboard-interactive, root по паролю → только по ключу. Включается, только если у пользователя сессии есть ключи в authorized_keys и сама сессия вошла не по паролю
--allow-port — дополнительный порт для UFW (8443, 8443/udp), флаг можно повторять

Профиль Xray для Remnawave

xhttp-tls/xray-node-profile.json — универсальный профиль, его достаточно один раз создать в панели и назначить нодам:

  • inbound XHTTP-TLS: 127.0.0.1:10443, VLESS, транспорт xhttp, security: none (TLS заканчивается на nginx);
  • блокируются: QUIC (UDP 443), исходящий SMTP на порт 25, BitTorrent, частные адреса и домены, реклама и трекеры;
  • outbound psiphon-out (SOCKS5 Psiphon) и balancer для доменов Gemini и связанных сервисов Google AI (в том числе geminiweb-pa, waa-pa, appsgenaiserver-pa, signaler-pa, ogads-pa на clients6.google.com) с автоматическим переключением на DIRECT, если прокси не отвечает; адрес и порт Psiphon установщик подставляет сам при показе профиля (goji-node profile);
  • журнал доступа выключен.

Если Psiphon не установлен (--no-psiphon), трафик для этих доменов просто пойдёт напрямую. Psiphon не принимает UDP; QUIC (UDP 443) в профиле блокируется, поэтому до Psiphon доходит только TCP.

Хост в Remnawave

Поле Значение
Адрес / порт <домен> / HTTPS-порт из вывода установщика (goji-node profile; у установок до 1.6.0 — 443)
Network xhttp
Path путь из вывода установщика / goji-node profile (без пробела в конце)
Mode auto
Security tls
SNI <домен>
ALPN h2
Fingerprint firefox или chrome
Flow пусто (Vision с XHTTP не используется)

Путь должен совпадать на сервере и в хосте символ в символ. Лишний пробел в конце поля Path в панели не виден, но клиент после этого получает «недоступен». Лучше набирать путь вручную, а не копировать.


Заглушки

Скрипт разворачивает один из шаблонов из xhttp-tls/templates/:

Имя Что это Источник и лицензия
analytics Quillmetric — сервис веб-аналитики: график, источники, тарифы написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
blog Lantern & Road — тревел-блог: 6 статей с фото, страница «О блоге» написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
docs Postline — документация API: боковое меню, поиск, примеры кода написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
saas Stackpulse — лендинг сервиса мониторинга: панель, тарифы, отзывы написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
freelancer Maren Holt — портфолио фотографа: 12 фото, лайтбокс написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
resume Daniel Okafor — резюме backend-разработчика написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
creative Oak & Ledger — магазин изделий ручной работы с корзиной написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
grayscale Fjellro — горные домики в Норвегии, запрос брони написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
new-age Habitual — лендинг приложения-трекера привычек написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
agency Fieldstone — студия брендинга и веб-дизайна: услуги, работы, команда написан для этого репозитория; фото: THIRD-PARTY-NOTICES (MIT)
livecams сайт «Open Window»: 24 YouTube-трансляции (камеры городов, МКС и NASA, зоопарки, аквариумы, дикая природа, новости); плеер на странице, при недоступном эфире переключается на следующий написан для этого репозитория

Заглушку можно выбрать в меню при установке или флагом --template; без терминала выбирается случайная. При повторном запуске сохраняется выбранный шаблон, сменить его позже: goji-node decoy (меню) или goji-node decoy <имя>. Шаблоны Start Bootstrap взяты из dist/ репозиториев, изображения пересжаты, рекламные тексты и ссылки на сайт-источник заменены, скрипт стороннего сервиса форм удалён. Часть шаблонов подгружает Bootstrap-скрипт, шрифты и иконки с публичных CDN (jsDelivr, Google Fonts, Font Awesome), как и оригиналы. Лицензии сторонних шаблонов лежат рядом с ними и отдаются как LICENSE.txt.

Свой шаблон: положите папку в xhttp-tls/templates/<имя>/ и выполните python xhttp-tls/build.py. Он заново встроит шаблоны в install.sh, чтобы скрипт оставался одним самодостаточным файлом.


Замена заглушки без переустановки

goji-node decoy                 # меню выбора среди установленных шаблонов
goji-node decoy blog            # поставить конкретную (или random)
goji-node decoy --list          # список шаблонов, текущая отмечена
goji-node decoy --pull          # скачать свежие шаблоны из репозитория (codeload.github.com)
goji-node decoy --from ~/mysite # свой сайт: каталог, .tar.gz/.zip или https-ссылка на архив
goji-node decoy --undo          # вернуть предыдущий сайт

Свой сайт должен содержать index.html (в корне или в единственной вложенной папке). Он сохраняется как custom-<имя>, переживает install.sh --resume и не затрагивается --pull. Архивы с путями ../абсолютными отклоняются, ссылки удаляются, максимум 200 МБ. Перед каждой заменой делается резервная копия в /var/backups/goji-node/ (5 последних). --pull обновляет только шаблоны сайтов, не сам скрипт и не настройки сервера. После install.sh --resume версии стандартных шаблонов возвращаются к встроенным в скрипт.

Обновление установщика

Скрипт сам проверяет, вышла ли новая версия в этом репозитории (файл xhttp-tls/VERSION), и сообщает об этом: в меню goji-node, в конце goji-node check, при запуске install.sh и при входе root по SSH. Проверка идёт не чаще раза в сутки (раз в сутки обновляет кэш cron), запрос только к raw.githubusercontent.com.

goji-node update            # показать, что изменилось, скачать новый install.sh и предложить применить
goji-node update --check    # только проверить (код выхода 10, если есть обновление)
goji-node update --notes    # только список изменений
goji-node update --yes      # без вопросов
goji-node update --no-apply # скачать, но не применять
bash install.sh --update    # то же, если goji-node ещё не установлен
goji-node update --off      # отключить проверки и уведомления (--on — включить снова)

Скачанный файл проверяется (размер, bash -n, версия внутри, sha256 из install.sh.sha256) и сохраняется как /usr/share/goji-node/install.sh; предыдущая версия — install.sh.prev. «Применить» — это повторный проход install.sh --resume --wait 0 с сохранёнными настройками. Контрольная сумма лежит в том же репозитории, поэтому защищает от повреждённой загрузки, но не от подмены самого репозитория. Версии до 1.4.0 команды update не имеют: один раз скачайте новый install.sh вручную и запустите bash install.sh --resume.


Состав репозитория

CHANGELOG.md              история версий
xhttp-tls/
├── install.sh            готовый установщик (шаблоны встроены, один файл)
├── install.template.sh   исходник установщика
├── VERSION, install.sh.sha256   версия и контрольная сумма (для goji-node update; создаёт build.py)
├── build.py              встраивает templates/ в install.template.sh -> install.sh
├── templates/            сайты-заглушки (+ THIRD-PARTY-NOTICES.md)
├── psiphon/              vps-psiphon (MIT) без изменений: вшивается в install.sh, README с источником и SHA-256
├── nginx-template.conf   эталон конфига nginx, который собирает скрипт
├── xray-node-profile.json  универсальный профиль Xray для Remnawave
└── INSTALL.md            краткая памятка

Требования

  • сервер с Debian или Ubuntu (используется apt), root-доступ;
  • домен с A-записью на сервер, порт 80 свободен (443 не нужен);
  • установленная панель Remnawave и добавленная в ней нода (нужен SECRET_KEY);
  • на ноде ничего не должно слушать порт 80 и выбранный HTTPS-порт; 443 можно оставить старому профилю.
  • Psiphon нужен Docker (ставится вместе с нодой) и зарубежный сервер: на сервере внутри страны, чьи ограничения вы обходите, его ставить нельзя. Образ swarupsengupta2007/psiphon:latest сторонний и не закреплён по версии; примерно 35 ГБ трафика в месяц на проверки (--psiphon-args "--bulk-test-mb 0" отключает).

Если что-то пошло не так

Симптом Причина и решение
live directory exists for … от certbot старая папка сертификата без конфигурации продления: скрипт переносит её в /root/letsencrypt-backup-… и выпускает сертификат заново, запустите его ещё раз
Xray падает с address already in use на HTTPS-порту nginx занял порт, который нужен профилю (бывает при --https-port 443, пока работает старый профиль): скрипт включает nginx на HTTPS-порту только после появления Xray на 127.0.0.1:10443. Если это уже случилось, уберите /etc/nginx/conf.d/xhttp-tls.conf и выполните systemctl reload nginx
Клиенты не подключаются после смены порта в host Remnawave остался старый порт: возьмите новый из goji-node profile
Клиент пишет «недоступен» проверьте путь в хосте (пробел в конце), ALPN h2, пустой Flow
Сертификат не выпускается домен указывает не на этот сервер, либо порт 80 закрыт файрволом

Что стоит знать

  • Скрипт переустанавливает контейнер Remnawave Node на этой машине: нода будет недоступна около минуты. Старый compose-файл сохраняется как /opt/remnanode/docker-compose.yml.bak-<дата>, но подключённые папки и соседние сервисы из него в новый не переносятся, сверьте их.
  • SECRET_KEY записывается в /opt/remnanode/docker-compose.yml с правами только для root.
  • Установщик настраивает только описанное выше. Остальная конфигурация сервера (SSH, файрвол, сеть) остаётся на вас.
  • Это установщик инфраструктуры. Его не запускали на всех поддерживаемых версиях ОС; прежде чем раскатывать на все ноды, проверьте на одной.
  • Репозиторий не содержит ключей, UUID пользователей и адресов реальных нод. Не добавляйте их в публичный репозиторий.

Лицензия

MIT, © 2026 goji-app. Сторонние шаблоны в xhttp-tls/templates/ распространяются под своими лицензиями (тоже MIT), их тексты лежат в папках шаблонов.

About

Установщик одной командой для VPS-ноды Remnawave: nginx + Let's Encrypt, XHTTP-профиль Xray, сайт-заглушка и переустановка Remnawave Node

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages