founder 219bb364bc docs: сделать проверку типов frontend release gate и убрать известное ограничение
bundle_ui запускает `pnpm run typecheck` перед сборкой bundle. И наличие шага,
и его порядок закреплены приёмкой — вместе с требованием vue-tsc версии 3 и
выше и с запретом снова совмещать сборку и проверку в build:prod.

Из docs/02 убран раздел «Известное ограничение: проверка типов frontend почти
ничего не проверяет» и заменён описанием действующего контракта. Прогноз в нём
был близок, но неточен: ошибок оказалось 142, а не ~155, и класс DefaultRow/
PeerVo на Element Plus 2.3 не существовал вовсе — он появился вместе с
обновлением Element Plus.

docs/04 получил описание модели отображения (третий слой рядом с типизированной
моделью и сырым YAML) и раздел о том, что страница Hysteria теперь read-only на
всех уровнях, а не только визуально.

docs/11: команды проверки frontend и dev doctor в раздел запуска, семь новых
пунктов приёмки.
2026-08-30 07:44:51 +05:00

HY2XS Core

HY2XS logo

HY2XS — production‑установщик Hysteria2‑сервера с локальной HY2XS admin‑панелью, systemd‑юнитами, nftablesfirewall и воспроизводимой моделью release‑пакета для чистого Debian 13.

Что это · Возможности · Быстрый старт · Конфигурация · Версии · Сборка · Changelog · Лицензия

Target OS Architecture Firewall Runtime License


Что это

HY2XS — это install‑only пакет для развёртывания Hysteria2‑узла на чистом Debian 13 amd64. Проект разделяет сборку и установку: разработчик один раз собирает release‑архив на Debian 13 build‑хосте, а целевой сервер получает уже готовый пакет и запускает install.sh без git clone, go build, bun install, pnpm install и сборки frontend‑ассетов.

HY2XS подходит для сценария, где нужен один production‑сервер с Hysteria2, локальной админ‑панелью, управляемым firewall и предсказуемой конфигурацией. Проект не является универсальным server manager, update manager или панелью для любых Linux‑дистрибутивов.

Ключевая идея: на target‑сервере выполняется только установка готового пакета. Вся тяжёлая сборочная часть остаётся на build‑машине.

Возможности

HY2XS release‑пакет разворачивает и настраивает:

  • официальный upstream‑бинарник Hysteria2: последняя стабильная версия выбирается при сборке пакета, закрепляется в его metadata и проверяется по SHA256;
  • HY2XS admin — встроенную админ‑панель для управления users/peers, трафиком, конфигурацией, логами и состоянием сервера;
  • systemd‑юнит hysteria-server для Hysteria2;
  • systemd‑юнит hy2xs-admin для админ‑панели;
  • runtime‑конфиг /etc/hy2xs/hy2xs.env;
  • Hysteria2‑конфиг /etc/hysteria/config.yaml;
  • postinstall snapshot /etc/hysteria/post-install.env;
  • bootstrap‑секреты администратора в /etc/hy2xs/bootstrap-admin.secret;
  • nftables‑правила с staged apply и rollback guard;
  • smoke‑проверки после установки;
  • команды диагностики, статуса, реконфигурации и сбора supportbundle.

HY2XS admin запускается локально по умолчанию на 127.0.0.1:8080. Наружу публикуется Hysteria2‑транспорт, а доступ к панели выполняется через SSH local port forwarding.

Архитектура

graph LR
  operator[Оператор на Windows/Linux/macOS] -->|SSH 2323/tcp| ssh[sshd на target]
  operator -->|SSH tunnel 127.0.0.1:8080| ui[HY2XS admin 127.0.0.1:8080]
  internet[Интернет] -->|443/udp| hy2[Hysteria2 server]
  letsencrypt[Let's Encrypt] -->|80/tcp при ACME http| acme[ACME challenge]
  hy2 -->|HTTP auth localhost + machine token| ui
  ui -->|trafficStats localhost| hy2
  hy2 --> cfg["/etc/hysteria/config.yaml"]
  ui --> env["/etc/hy2xs/hy2xs.env"]
  fw[nftables] --> ssh
  fw --> hy2
  fw --> acme

В production‑профиле проект работает как IPv4only stack. IPv6 намеренно не входит в текущий baseline. Если у домена есть AAAA‑запись и включён строгий режим HY2XS_DNS_AAAA_POLICY=strict, установка останавливается до применения конфигурации.

Поддерживаемые платформы

Target‑сервер

Компонент Поддерживается
ОС Debian 13
Архитектура amd64 / x86_64
Init system systemd
Firewall nftables
Сетевой профиль IPv4only
Hysteria2 target linuxamd64
Admin UI локальный bind по умолчанию: 127.0.0.1:8080

Build‑машина

Компонент Поддерживается
ОС Debian 13
Архитектура amd64 / x86_64
Git tree обязателен
Dirty tree запрещён по умолчанию
Интернет нужен для apt, Go, Bun, Node.js, pnpm/npm registry, GitHub и upstream Hysteria2

Windows и macOS можно использовать для разработки, редактирования кода и работы с GitHub, но production‑архив должен собираться на Debian 13 amd64.

Что HY2XS не делает

Это важные границы проекта:

  • не собирает проект на target‑сервере;
  • не поддерживает Debian 12, Ubuntu, CentOS, Alpine и другие ОС;
  • не поддерживает arm64 в текущем release‑профиле;
  • не включает IPv6production baseline;
  • не настраивает sshd автоматически;
  • не предоставляет полноценный uninstall/update framework;
  • не обновляет Hysteria2 на уже работающем сервере: reconfigure намеренно не является Hysteria updater;
  • не мигрирует установки 0.x на 1.0.0 — переход выполняется чистой установкой, см. CHANGELOG;
  • не выполняет сложную миграцию старых неизвестных состояний сервера;
  • не реализует Telegram‑бота, port hopping и универсальный accessdelivery workflow;
  • не предназначен для установки поверх давно используемого сервера с неизвестными firewall/systemd‑правками.

Release‑пакет

Production‑сборка создаёт один архив:

hy2xs-install-<version>.tar.gz

Внутри архива находятся:

hy2xs-install/
├── install.sh
├── orchestrator/hy2xs-orchestrator
├── ui/hy2xs-admin/hy2xs-admin
├── config/hy2xs.env
├── templates/
├── systemd/
├── docs/
└── metadata/

При запуске install.sh пакет проверяет metadata/checksums.txt и выполняет readonly cleanhost preflight из распакованного архива. После этого он передаёт управление installonly orchestrator через exec — и больше не делает ничего: сам install.sh не изменяет на сервере ни одного файла.

Всю раскладку выполняет уже оркестратор: ставит себя в /usr/local/lib/hy2xs/hy2xs-orchestrator, создаёт symlink /usr/local/bin/hy2xs-orchestrator, копирует package assets в /usr/local/lib/hy2xs/package и продолжает установку. Это сделано ради одного свойства: у изменений сервера ровно один владелец, поэтому при любом отказе известно, что именно было создано и что откатывать.

Сетевая модель по умолчанию

Назначение Значение по умолчанию
SSH оператора 2323/tcp
Hysteria2 443/udp
ACME HTTP challenge 80/tcp, если HY2XS_TLS_MODE=acme и HY2XS_ACME_TYPE=http
HY2XS admin 127.0.0.1:8080
TrafficStats Hysteria2 127.0.0.1:36712
Firewall mode takeover в packaged baseline
Hysteria2 auth http через локальный HY2XS admin
Hysteria2 obfs gecko (512/1200); salamander доступен как режим совместимости
Congestion fallback bbr, профиль standard
QUIC stateless reset включён

Важно: HY2XS_SSH_PORT нужен HY2XS для nftables‑правил и проверки доступности SSH‑порта. Сам sshd проект не перенастраивает. SSH на 2323 и вход только по ключу нужно настроить до запуска ./install.sh.

Версионная политика Hysteria2

HY2XS не привязан к конкретному номеру версии Hysteria.

Источник по умолчанию берёт последний стабильный релиз Hysteria, доступный на момент сборки пакета. Разрешённая версия, URL артефакта и контрольная сумма замораживаются в получившемся install‑пакете.

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

build machine                                     target server
─────────────                                     ─────────────
определить последнюю стабильную      ─┐
взять ожидаемый SHA-256 из            │
upstream hashes.txt                   │
скачать артефакт и сверить его        ├─►  release‑пакет  ──►  скачать ровно
проверить, что бинарник принимает     │    version + url        этот артефакт,
канонический конфиг HY2XS             │    + sha256             сверить SHA-256
заморозить version/url/sha256        ─┘                         и `hysteria version`

Контрольная сумма берётся из upstream‑ассета hashes.txt, а не считается только локально: локальный пересчёт подтверждает, что файл не изменился после скачивания, но не доказывает, что скачан именно ожидаемый upstream artifact.

Что это даёт:

  • новая установка получает актуальную Hysteria без ручного обновления version lock;
  • если между сборкой пакета и его установкой выйдет новая версия, содержимое установки не изменится;
  • повторная установка старого пакета поставит ту же версию, что и в день сборки;
  • несовместимый upstream ломает сборку, а не сервер оператора.

Переопределения при сборке:

# по умолчанию: последняя стабильная
./tools/build/build.sh

# закрепить конкретную версию
HYSTERIA_VERSION_OVERRIDE=v2.12.2 ./tools/build/build.sh

# офлайн-сборка по закоммиченному tools/build/hysteria-lock.env
HYSTERIA_CHANNEL=pinned ./tools/build/build.sh

Фактически установленная версия видна в /etc/hysteria/post-install.env (HY2_VERSION), а способ её выбора — в HY2_RESOLUTION.

Обновление Hysteria на уже работающем сервере в текущем релизе не поддерживается: reconfigure намеренно не является Hysteria updater. Это сохраняет immutable‑контракт развёртывания.

Обфускация

Новые установки HY2XS используют Gecko.

Gecko помечен upstream как experimental. Он достраивается поверх Salamander: помимо scramble он дополнительно фрагментирует QUIC handshake на пакеты случайного размера. HY2XS использует upstream‑defaults размеров пакетов 512/1200 как проверенный production‑профиль.

Salamander остаётся поддержанным режимом совместимости. Смена типа обфускации требует соответствующих изменений на клиенте: это изменение wire‑совместимости, а не косметическая настройка.

Gecko Salamander
Статус upstream experimental stable
Роль в HY2XS default для новых установок режим совместимости
Параметр HY2XS_HYSTERIA_OBFS_TYPE=gecko HY2XS_HYSTERIA_OBFS_TYPE=salamander
В клиентской ссылке obfs=gecko obfs=salamander

Экспериментальность upstream остаётся контролируемым риском, потому что одновременно выполняются три условия: Salamander доступен как fallback, каждая разрешённая версия проходит compatibility gate до выпуска пакета, и существующие серверы никогда не переводятся на Gecko молча.

Размеры пакетов Gecko не выносятся в конфигурацию: официальная схема hysteria2:// не умеет их передавать, поэтому нестандартные значения сделали бы клиентскую ссылку неполной.

Быстрый старт для нового сервера

Ниже приведён полный путь для оператора, который работает с Windows и ставит HY2XS на чистый Debian 13 сервер.

В примерах используются условные значения:

Параметр Пример
IP сервера SERVER_IP
Домен сервера vpn.example.com
Email для ACME admin@example.com
Release‑архив hy2xs-install-0.2.2.tar.gz
SSH‑ключ id_ed25519_hy2xs

Замените эти значения на свои.

1. Проверьте DNS и внешние порты

До установки домен должен указывать A‑записью на IPv4‑адрес target‑сервера:

vpn.example.com -> SERVER_IP

Для стандартной установки с HY2XS_TLS_MODE=acme и HY2XS_ACME_TYPE=http снаружи должны быть доступны:

Порт Протокол Назначение
2323 TCP SSH оператора
80 TCP ACME HTTP challenge
443 UDP Hysteria2

Если у домена есть AAAA‑запись, при строгой политике HY2XS_DNS_AAAA_POLICY=strict установка будет остановлена, потому что текущий production‑профиль HY2XS является IPv4only.

A‑запись должна указывать именно на этот сервер, а не просто существовать. Preflight сверяет её с публичными IPv4, назначенными интерфейсам машины, и останавливает установку при расхождении:

DNS IPv4 mismatch for HY2XS_PUBLIC_HOST vpn.example.com:
  DNS A records:       185.xxx.xxx.10
  server public IPv4:  185.xxx.xxx.27

Update the DNS A record before using this server.

Та же проверка выполняется в reconfigure и doctor, поэтому принудительная смена IPv4 провайдером не остаётся незамеченной. Адрес сервера определяется локально, без обращения к внешним сервисам определения IP.

Если сервер работает за NAT или на floating IP — это топология вне текущего baseline; осознанное решение оформляется значением HY2XS_PUBLIC_ENDPOINT_POLICY=warn.

2. Создайте SSH‑ключ на Windows

Откройте PowerShell:

ssh-keygen -t ed25519 -a 100 -f "$env:USERPROFILE\.ssh\id_ed25519_hy2xs" -C "hy2xs-target-1"

Выведите публичный ключ:

type "$env:USERPROFILE\.ssh\id_ed25519_hy2xs.pub"

Скопируйте всю строку вида:

ssh-ed25519 AAAA... hy2xs-target-1

Именно её нужно добавить на сервер в /root/.ssh/authorized_keys.

3. Войдите на сервер по паролю провайдера

Первый вход обычно выполняется по временному root‑паролю от провайдера:

ssh root@SERVER_IP

На сервере установите базовые пакеты:

apt-get update
apt-get install -y openssh-server sudo ca-certificates curl tar

4. Добавьте публичный ключ на сервер

На сервере замените пример ключа на свой реальный публичный ключ:

install -d -m 700 -o root -g root /root/.ssh

cat > /root/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAA_REPLACE_WITH_YOUR_PUBLIC_KEY hy2xs-target-1
EOF

chmod 600 /root/.ssh/authorized_keys
chown -R root:root /root/.ssh

5. Переведите SSH на порт 2323 и отключите парольный вход

Не закрывайте текущую SSH‑сессию, пока не проверите новый вход по ключу.

Сначала посмотрите, какие SSH‑директивы уже заданы провайдером:

grep -RniE '^[[:space:]]*(Include|Port|PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|ChallengeResponseAuthentication|PubkeyAuthentication|AllowTcpForwarding|PermitOpen|GatewayPorts|Match)\b' \
  /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null || true

OpenSSH для многих параметров использует первое найденное значение. Поэтому поздний файл вида 99-*.conf может не перекрыть ранний provider‑конфиг. Безопаснее сначала закомментировать конфликтующие директивы, затем создать ранний 00-hy2xs-operator.conf.

for f in /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf; do
  [ -f "$f" ] || continue
  cp -a "$f" "$f.bak.$(date +%Y%m%d-%H%M%S)"
  sed -i -E 's/^[[:space:]]*(Port|PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|ChallengeResponseAuthentication|PubkeyAuthentication|AllowTcpForwarding|PermitOpen|GatewayPorts|X11Forwarding|AllowAgentForwarding|MaxAuthTries|LoginGraceTime|ClientAliveInterval|ClientAliveCountMax)[[:space:]]+/# disabled-by-hy2xs-hardening: &/' "$f"
done

cat > /etc/ssh/sshd_config.d/00-hy2xs-operator.conf <<'EOF'
Port 2323

PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PermitRootLogin prohibit-password

AllowTcpForwarding local
PermitOpen 127.0.0.1:8080 localhost:8080
GatewayPorts no

X11Forwarding no
AllowAgentForwarding no
MaxAuthTries 3
LoginGraceTime 20
ClientAliveInterval 300
ClientAliveCountMax 2
EOF

sshd -t
systemctl reload ssh || systemctl restart ssh

Проверьте effective‑конфиг:

sshd -T | grep -E '^(port|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|allowtcpforwarding|permitopen|gatewayports) '
ss -H -ltn | grep -E ':(22|2323) '

Ожидаемо:

port 2323
permitrootlogin without-password
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
gatewayports no
allowtcpforwarding local
permitopen 127.0.0.1:8080 localhost:8080

В списке listen‑портов должен остаться 2323, а 22 не должен слушаться.

6. Проверьте вход по ключу

В новом PowerShell‑окне:

ssh -p 2323 -i "$env:USERPROFILE\.ssh\id_ed25519_hy2xs" root@SERVER_IP

Проверьте, что парольный вход запрещён:

ssh -p 2323 -o PreferredAuthentications=password -o PubkeyAuthentication=no root@SERVER_IP

Правильный результат:

Permission denied (publickey).

После этого можно дополнительно заблокировать пароль root на уровне Linux‑аккаунта:

passwd -l root
passwd -S root

Это не ломает вход по SSH‑ключу, но защищает от случайного возврата парольной SSH‑аутентификации в будущем.

7. Скопируйте release‑архив на сервер

С Windows:

scp -P 2323 -i "$env:USERPROFILE\.ssh\id_ed25519_hy2xs" .\hy2xs-install-0.2.2.tar.gz root@SERVER_IP:/root/

На сервере:

cd /root
tar -xzf hy2xs-install-0.2.2.tar.gz
cd /root/hy2xs-install

8. Создайте конфиг для своего сервера

Не редактируйте исходный шаблон внутри пакета без необходимости. Создайте отдельный source‑config:

cp config/hy2xs.env /root/hy2xs-target.env
nano /root/hy2xs-target.env

Минимально проверьте и измените:

HY2XS_DOMAIN=vpn.example.com
HY2XS_PUBLIC_HOST=vpn.example.com
HY2XS_ACME_EMAIL=admin@example.com
HY2XS_SSH_PORT=2323
HY2XS_UI_BIND_HOST=127.0.0.1
HY2XS_UI_PORT=8080
HY2XS_HYSTERIA_PORT=443
HY2XS_FIREWALL_MODE=takeover
HY2XS_FIREWALL_STAGED_APPLY=true

Для стандартной production‑установки оставьте:

HY2XS_IPV6_ENABLED=false
HY2XS_TLS_MODE=acme
HY2XS_ACME_TYPE=http
HY2XS_HYSTERIA_AUTH_MODE=http
HY2XS_HYSTERIA_OBFS_TYPE=gecko
HY2XS_UI_PUBLIC_ACCESS=false

Если нужен режим совместимости со старыми клиентами, укажите HY2XS_HYSTERIA_OBFS_TYPE=salamander. Подробнее — в разделе Обфускация.

9. Запустите установку

./install.sh --config /root/hy2xs-target.env --non-interactive

Установка идёт в две фазы с жёсткой границей между ними.

PHASE 0 — только чтение. До её успешного завершения на сервере не изменяется ни один файл, включая /usr/local/lib/hy2xs:

  1. проверит, что запущено от root;
  2. проверит checksums release‑пакета;
  3. запустит cleanhost preflight из распакованного архива: платформа Debian 13 amd64, отсутствие предыдущей установки, валидность конфигурации.

PHASE 1 — применение изменений. Её целиком выполняет оркестратор, которому install.sh передал управление через exec:

  1. установит сам себя в /usr/local/lib/hy2xs и разложит runtime‑пакет;
  2. создаст runtime‑каталоги и service users;
  3. запишет /etc/hy2xs/hy2xs.env;
  4. разложит bundled HY2XS admin;
  5. скачает закреплённый в пакете Hysteria2 binary из upstream, проверит SHA256 и фактическую версию;
  6. создаст /etc/hysteria/config.yaml;
  7. установит systemd‑юниты;
  8. применит nftables‑правила;
  9. выполнит smokechecks;
  10. зафиксирует успешное состояние в /var/lib/hy2xs/install-state.json.

Если PHASE 0 не прошла, установщик завершается с ошибкой и сервер остаётся в том же состоянии, в котором был. HY2XS v1 не устанавливается поверх предыдущего поколения и не мигрирует его состояние: очистка старой установки — отдельная явная операция, см. docs/14-legacy-cleanup.md.

10. Получите bootstrap‑пароль админки

cat /etc/hy2xs/bootstrap-admin.secret

Файл содержит:

ADMIN_USER=...
ADMIN_INITIAL_PASSWORD=...
ADMIN_CON_PASS=...

ADMIN_INITIAL_PASSWORD нужен для первого входа в HY2XS admin. После первого входа смените пароль через интерфейс.

ADMIN_CON_PASS — bootstrap‑секрет Hysteria2 peer/auth слоя. Не публикуйте этот файл и не отправляйте его в issue/log без редактирования.

11. Откройте HY2XS admin через SSH‑туннель

На локальной машине:

ssh -p 2323 `
  -i "$env:USERPROFILE\.ssh\id_ed25519_hy2xs" `
  -N `
  -L 127.0.0.1:8080:127.0.0.1:8080 `
  root@SERVER_IP

Пример для Linux/macOS (одной строкой):

ssh -p 2323 -i ~/.ssh/id_ed25519_hy2xs -N -L 8080:127.0.0.1:8080 root@SERVER_IP

После этого откройте в браузере:

http://127.0.0.1:8080/

Если порт 8080 на локальной машине занят, можно пробросить другой локальный порт:

ssh -p 2323 `
  -i "$env:USERPROFILE\.ssh\id_ed25519_hy2xs" `
  -N `
  -L 127.0.0.1:18080:127.0.0.1:8080 `
  root@SERVER_IP

И открыть:

http://127.0.0.1:18080/

12. Проверьте установку

На сервере:

systemctl status hysteria-server --no-pager
systemctl status hy2xs-admin --no-pager

ss -H -lun | grep ':443'
ss -H -ltn | grep ':8080'
ss -H -ltn | grep ':2323'

nft list ruleset
cat /var/lib/hy2xs/install-state.json

Выполните doctor‑проверку:

hy2xs-orchestrator doctor \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env

Проверьте сводный статус:

hy2xs-orchestrator status \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env

Конфигурация hy2xs.env

После установки основным редактируемым файлом является:

/etc/hy2xs/hy2xs.env

Менять runtime‑параметры нужно через этот файл и затем применять reconfigure. Редактирование post-install.env не меняет runtime‑состояние.

Основные параметры

Переменная Назначение Значение по умолчанию в packaged baseline
HY2XS_CONFIG_SCHEMA_VERSION Версия схемы конфигурации HY2XS. Конфигурация другой схемы отклоняется fail‑fast 2
HY2XS_IPV6_ENABLED IPv6‑режим. В production baseline должен быть false false
HY2XS_DOMAIN Домен для ACME и deploy‑профиля fi.api.withen.pro
HY2XS_DNS_AAAA_POLICY Поведение при наличии AAAA‑записи: strict, warn, off strict
HY2XS_PUBLIC_ENDPOINT_POLICY Строгость проверки того, что A‑записи публичного endpoint ведут на IPv4 этого сервера: strict, warn, off strict
HY2XS_PUBLIC_HOST Публичный host без схемы, порта и path fi.api.withen.pro
HY2XS_PUBLIC_PORT Публичный порт Hysteria2 endpoint 443
HY2XS_SSH_PORT SSH‑порт, который будет разрешён firewall‑правилами 2323
HY2XS_FIREWALL_MODE Режим управления nftables: managed, takeover, external, off takeover
HY2XS_FIREWALL_STAGED_APPLY Включает staged apply и rollback guard firewall true
HY2XS_UI_BIND_HOST IPv4 bind HY2XS admin 127.0.0.1
HY2XS_UI_PUBLIC_ACCESS Флаг публичного UI‑доступа. В baseline оставляйте false false
HY2XS_UI_PORT Порт HY2XS admin 8080
HY2XS_ADMIN_USER Bootstrap‑логин администратора hy2xsadmin
HY2XS_ADMIN_INITIAL_PASSWORD Bootstrap‑пароль администратора; __GENERATE__ генерируется при install __GENERATE__
HY2XS_ADMIN_CON_PASS Bootstrap‑секрет peer/auth слоя; __GENERATE__ генерируется при install __GENERATE__
HY2XS_FORCE_PASSWORD_CHANGE Принудительная смена пароля. UX‑flow пока не включён в production baseline false
HY2XS_ALLOW_SELF_SIGNED_DEV Разрешает self_signed_dev TLS‑режим false
HY2XS_TLS_MODE TLS‑режим: acme, file, self_signed_dev acme
HY2XS_ACME_TYPE ACME challenge: http, tls, dns; dns пока не поддержан production‑профилем http
HY2XS_ACME_EMAIL Email для ACME admin@withen.pro
HY2XS_TLS_CERT_PATH Путь к cert при file/self_signed_dev /etc/hysteria/server.crt
HY2XS_TLS_KEY_PATH Путь к key при file/self_signed_dev /etc/hysteria/server.key
HY2XS_HYSTERIA_BIND_HOST Bind Hysteria2. В production profile фиксируется на 0.0.0.0 0.0.0.0
HY2XS_HYSTERIA_PORT UDP‑порт Hysteria2 443
HY2XS_HYSTERIA_AUTH_MODE Auth mode Hysteria2. Фиксированное значение production‑профиля http
HY2XS_HYSTERIA_TRAFFIC_STATS_HOST Host trafficStats API 127.0.0.1
HY2XS_HYSTERIA_TRAFFIC_STATS_PORT Порт trafficStats API 36712
HY2XS_HYSTERIA_TRAFFIC_STATS_SECRET Secret для trafficStats и machine auth __GENERATE__
HY2XS_HYSTERIA_OBFS_TYPE Тип обфускации: gecko или salamander. Смена меняет wire‑совместимость gecko
HY2XS_HYSTERIA_OBFS_PASSWORD Пароль обфускации; __GENERATE__ генерируется при install __GENERATE__
HY2XS_HYSTERIA_BANDWIDTH_UP Hysteria2 upstream bandwidth 50 mbps
HY2XS_HYSTERIA_BANDWIDTH_DOWN Hysteria2 downstream bandwidth 50 mbps
HY2XS_HYSTERIA_IGNORE_CLIENT_BANDWIDTH Игнорировать bandwidth клиента false
HY2XS_HYSTERIA_CONFIG_PATH Путь Hysteria2 config. В production baseline фиксирован /etc/hysteria/config.yaml
HY2XS_INSTALL_DIR Каталог установки HY2XS admin /opt/hy2xs-admin
HY2XS_DATA_DIR Data‑каталог HY2XS admin /var/lib/hy2xs-admin
HY2XS_LOG_DIR Log‑каталог HY2XS /var/log/hy2xs

Режимы firewall

Режим Поведение
managed HY2XS управляет nftables, но останавливается при обнаружении чужого /etc/nftables.conf
takeover HY2XS явно берёт управление nftables на себя
external HY2XS не меняет nftables; оператор сам отвечает за firewall
off Firewall‑слой HY2XS отключён

При managed и takeover генерируется nftables‑конфигурация с default drop policy, разрешением loopback, established/related, SSH‑порта, ACME challenge‑порта, Hysteria2 UDP‑порта и ICMP echorequest.

Реконфигурация

После изменения /etc/hy2xs/hy2xs.env сначала выполните dry‑run:

hy2xs-orchestrator reconfigure \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env \
  --dry-run

Если ошибок нет, примените изменения:

hy2xs-orchestrator reconfigure \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env \
  --apply

reconfigure --apply выполняет backup, генерирует конфиги, обновляет systemd‑юниты, применяет firewall, выполняет smoke‑checks и при ошибке пытается откатить изменённое состояние.

Важно: HY2XS_ADMIN_INITIAL_PASSWORD и HY2XS_ADMIN_CON_PASS являются installonly bootstrap‑полями. Их изменение в /etc/hy2xs/hy2xs.env после первичной установки не ротирует уже созданные credentials в SQLite автоматически.

Команды управления

Команда Назначение
hy2xs-orchestrator preflight-install Read‑only проверка чистоты хоста; ничего не меняет
hy2xs-orchestrator status Показать состояние платформы, сервисов, firewall и install marker
hy2xs-orchestrator doctor Выполнить preflight и smokechecks текущей установки; сервисы не перезапускает
hy2xs-orchestrator reconfigure --dry-run Проверить конфиг без применения
hy2xs-orchestrator reconfigure --apply Применить runtime‑конфигурацию
hy2xs-orchestrator repair --allow-partial-state Довести до конца незавершённую установку текущего поколения
hy2xs-orchestrator diagnostics collect Собрать diagnostic bundle в /var/log/hy2xs/diagnostics
hy2xs-orchestrator redact-config Отредактировать секреты в env/yaml перед публикацией логов

repair без --allow-partial-state работает только поверх полностью успешной установки. В обоих режимах он сначала проверяет, что /var/lib/hy2xs/install-state.json принадлежит текущему поколению продукта (product, release_line, config_schema_version), и отказывается работать поверх чужого состояния.

Пример сбора диагностики:

hy2xs-orchestrator diagnostics collect \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env

Проверка безопасности после установки

Минимальный набор проверок:

# SSH слушает только ожидаемый порт
ss -H -ltn | grep -E ':(22|2323) '

# password auth отключён
sshd -T | grep -E '^(port|permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|allowtcpforwarding|permitopen) '

# UI не слушает публичный 0.0.0.0
ss -H -ltn | grep ':8080'

# Hysteria2 слушает UDP-порт
ss -H -lun | grep ':443'

# nftables-конфиг валиден
nft -c -f /etc/nftables.conf

# сервисы активны
systemctl is-active hysteria-server hy2xs-admin

Ожидаемые SSH‑значения:

port 2323
permitrootlogin without-password
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
allowtcpforwarding local
permitopen 127.0.0.1:8080 localhost:8080

Troubleshooting

Установка отказывается: обнаружена предыдущая установка

[hy2xs] ERROR: На сервере обнаружена предыдущая или посторонняя установка.
HY2XS v1 не поддерживает установку поверх и не мигрирует состояние 0.x.
Ни один файл на сервере не изменён.

Это ожидаемое поведение, а не сбой. Отказ происходит в PHASE 0, до любой мутации: сервер остался в том состоянии, в котором был.

Что делать:

  1. сохраните нужные данные (база пиров, конфиг) — см. docs/14-legacy-cleanup.md;
  2. посмотрите план очистки: sudo ./purge-v0.sh;
  3. выполните очистку: sudo ./purge-v0.sh --apply --yes-i-know;
  4. повторите установку.

Отдельный случай — отказ вида HY2XS_CONFIG_SCHEMA_VERSION отсутствует в конфигурации. Он означает, что переданный --config относится к предыдущему поколению: до v1 этого поля не существовало. Создайте конфиг заново по разделу «Создайте конфиг для своего сервера».

Если установка HY2XS v1 упала после начала применения изменений, полная очистка не нужна — используйте hy2xs-orchestrator repair --allow-partial-state.

Установка падает на DNS AAAA

Причина: домен имеет IPv6 AAAA‑запись, а HY2XS production profile является IPv4only.

Решения:

  1. удалить AAAA‑запись у домена;
  2. либо временно установить HY2XS_DNS_AAAA_POLICY=warn, если оператор осознанно принимает риск клиентских IPv6‑маршрутов вне текущего baseline.

DNS IPv4 mismatch: DNS ведёт не на этот сервер

Причина: A‑запись публичного endpoint указывает на адрес, которого нет среди публичных IPv4 этого сервера. Типичный случай — провайдер принудительно сменил IP, а DNS остался старым: сервисы на машине живы, но клиентская ссылка отправляет людей на другой адрес.

Решения:

  1. сверить фактический адрес сервера и обновить A‑запись:
ip -4 addr show scope global
  1. дождаться истечения TTL и повторить hy2xs-orchestrator doctor;
  2. если в строке server public IPv4: пусто — на интерфейсах нет публичного IPv4 (сервер за NAT). Это вне baseline; при осознанном решении установите HY2XS_PUBLIC_ENDPOINT_POLICY=warn.

Если A‑записей несколько и среди них есть посторонняя, проверка тоже отказывает: HY2XS — single‑host профиль, и второй backend за тем же именем означает, что часть клиентов попадёт не на этот сервер.

Установка падает на проверке SSH‑порта

HY2XS firewall‑слой проверяет, что порт из HY2XS_SSH_PORT уже слушается. Если указано 2323, но sshd продолжает слушать только 22, установка остановится.

Проверьте:

ss -H -ltn | grep -E ':(22|2323) '
sshd -T | grep '^port '

Вход по паролю всё ещё работает

Проверьте ранние provider‑конфиги:

grep -RniE '^[[:space:]]*(PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|PubkeyAuthentication)\b' \
  /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf

Если есть ранний файл с PasswordAuthentication yes, он может применяться раньше вашего hardening‑файла. Закомментируйте конфликтующие директивы и создайте 00-hy2xs-operator.conf, как показано в quick start.

UI не открывается в браузере

Проверьте, что SSH‑туннель запущен и сервис слушает localhost:

systemctl status hy2xs-admin --no-pager
ss -H -ltn | grep ':8080'
curl -sS http://127.0.0.1:8080/healthz

На локальной машине проверьте, что порт не занят другим приложением. При необходимости используйте локальный порт 18080 вместо 8080.

Нужно отправить логи без секретов

Соберите диагностику:

hy2xs-orchestrator diagnostics collect \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env

Перед публикацией отдельных env/yaml файлов используйте redaction:

hy2xs-orchestrator redact-config \
  --config /etc/hy2xs/hy2xs.env \
  --out /root/hy2xs.env.redacted \
  --format env

Сборка release‑пакета

Обычному пользователю не нужно собирать проект из исходников. Этот раздел нужен maintainer’у, который готовит release‑архив.

Перед работой: сверьте среду с контрактом

./tools/dev/doctor.sh          # Linux/macOS
.\tools\dev\doctor.ps1         # Windows (PowerShell 7+)
HY2XS development environment
contract: versions.env (HY2XS 1.0.0, release line 1)

Go:
  required: 1.26.7
  found:    1.25.6
  FAIL — локальный Go собирает не ту stdlib, что уедет в релиз; поставьте 1.26.7

Node:
  required: 24.20.0
  found:    24.20.0
  OK

Скрипт ничего не устанавливает и не меняет — он отвечает на один вопрос: совпадает ли эта машина с контрактом сборки.

Раньше versions.env был контрактом только для сборки: она скачивает Go, Node и Bun ровно тех версий, что там записаны, сверяя контрольные суммы, а машина разработчика не проверялась никак. Расхождение обнаруживалось на Debian, внутри release‑сборки, и выглядело как «у меня работало».

Расхождение не гипотетическое. Директива go в apps/go.mod — это языковой baseline модуля, а не выбор компилятора, поэтому локальный Go другой минорной линии собирал проект успешно, пока релизный бинарь компилировался на 1.26.7 и наследовал её stdlib: проверялся не тот код, который уезжает в production. Поэтому go.mod теперь объявляет toolchain явно, а doctor показывает расхождение до сборки, а не после.

Сборка поддерживается на Debian 13 amd64 из чистого git work tree.

apt-get update
apt-get install -y git ca-certificates curl unzip tar xz-utils build-essential pkg-config bash coreutils findutils grep sed gawk openssl

git clone <repo-url>
cd <repo-dir>
git status --short

Подготовьте build env:

Версии и контрольные суммы toolchain не задаются переменными окружения: они объявлены в корневом versions.env, и сборка берёт их оттуда. Раньше их приходилось передавать снаружи, из-за чего воспроизводимая сборка в чистой Debian‑среде требовала предварительного знания четырёх SHA‑256.

export BUILD_ID=prod-$(date -u +%Y%m%dT%H%M%SZ)

# Для переносимости между x86_64-серверами без AVX2 предпочтителен baseline artifact.
# Ожидаемый digest выбирается автоматически: в versions.env зафиксированы обе суммы.
export BUN_FLAVOR=x64-baseline

# Опционально: снимает anonymous rate limit при разрешении upstream-релиза.
export GITHUB_TOKEN=<token>

PACKAGE_VERSION тоже приходит из versions.env (HY2XS_VERSION). Шаг verify_versions_contract роняет сборку, если версия продукта, схема конфигурации, целевая платформа или packageManager в package.json разошлись с контрактом.

Запустите сборку:

./tools/build/build.sh

Сборка последовательно:

  1. проверяет контракт versions.env (verify_versions_contract);
  2. прогоняет тесты и типы оркестратора (bun test, tsc --noEmit);
  3. определяет последнюю стабильную версию Hysteria, берёт ожидаемый SHA‑256 из upstream hashes.txt и сверяет с ним скачанный артефакт;
  4. проходит compatibility gate: реальный бинарник Hysteria должен принять канонический конфиг HY2XS для Gecko и для Salamander;
  5. собирает orchestrator, frontend и backend, проставляя версию админки из контракта;
  6. прогоняет go vet и go test для HY2XS admin;
  7. проверяет граф зависимостей на известные уязвимости (govulncheck ./... и pnpm audit --prod);
  8. формирует архив и прогоняет acceptance‑проверки.

Любой сбой на шагах 1–7 останавливает сборку до создания пакета.

Переменные, управляющие выбором версии Hysteria:

Переменная По умолчанию Назначение
HYSTERIA_CHANNEL из versions.env (stable) stable — разрешить последнюю стабильную; pinned — офлайн‑сборка по tools/build/hysteria-lock.env
HYSTERIA_VERSION_OVERRIDE пусто Закрепить конкретную версию vX.Y.Z
HYSTERIA_COMPAT_GATE true Compatibility gate; для release‑сборок обязателен
HYSTERIA_VERIFY_UPSTREAM_HASHES true Сверять артефакт с upstream hashes.txt; отключение — только break‑glass
HYSTERIA_WRITE_LOCK false Записать разрешённые значения обратно в lock‑файл

Проверка зависимостей переменными не управляется: у неё нет аварийного выхода. Релизный артефакт HY2XS невозможно собрать с непройденным гейтом, и поле dependency_security_gate в metadata/package.env принимает единственное значение true.

Раньше здесь были описаны два способа выпустить релиз, зная об уязвимости. Ими они не являлись: финальная приёмка архива требует буквально dependency_security_gate=true, поэтому сборка с любым из них проходила весь цикл и падала на последнем шаге. Документированная операция, которую продукт сам же запрещает, — хуже отсутствующей.

Если advisory вышло в неудачный момент, чинится это обновлением графа (apps/go.sum, apps/frontend/pnpm-lock.yaml) или версии toolchain в versions.env. Для локальной работы обходить нечего: go test ./..., govulncheck ./... и pnpm audit запускаются напрямую и tarball не создают.

Проверка versions‑контракта и проверка зависимостей отвечают на разные вопросы. Первая следит, что зафиксированные версии согласованы между собой; вторая — что про эти версии не стало известно плохого. Зафиксированный граф не стареет только на бумаге: advisory по нему выходят и после фиксации, а сборка релиза — единственный момент, когда это расхождение ловится дёшево.

Полный E2E с реальным клиентом Hysteria запускается отдельно (нужен Go: ссылка берётся из production‑генератора, а не из отдельной реализации внутри теста):

HYSTERIA_BIN=/usr/local/bin/hysteria ./tools/test/e2e-hysteria.sh

Результат:

dist/hy2xs-install-<version>.tar.gz

Проверьте архив:

ls -lh dist/hy2xs-install-*.tar.gz
sha256sum dist/hy2xs-install-*.tar.gz

tar -tzf dist/hy2xs-install-1.0.0.tar.gz | grep -E \
'^(hy2xs-install/install.sh|hy2xs-install/orchestrator/hy2xs-orchestrator|hy2xs-install/ui/hy2xs-admin/hy2xs-admin|hy2xs-install/metadata/checksums.txt)$'

Подробная документация по сборочному слою находится в tools/build/README.md.

Структура репозитория

.
├── apps/                 # HY2XS admin: Go backend + Vue/Vite frontend
├── orchestrator/         # install-only orchestrator на Bun + TypeScript
├── package/              # skeleton будущего install package
├── tools/build/          # production builder и packaging pipeline
├── tools/dev/            # doctor: сверка среды разработки с versions.env
├── tools/test/           # end-to-end проверки с реальным клиентом Hysteria
├── tools/legacy/         # purge-v0.sh: очистка сервера от предыдущего поколения
├── docs/                 # спецификации baseline, тестов и эксплуатации
├── versions.env          # контракт продукта, платформы и toolchain
├── CHANGELOG.md
├── README.md
└── LICENSE

Каталог dist/ создаётся builder’ом и не должен храниться в git.

Для кого этот проект

HY2XS рассчитан на операторов, которым нужен воспроизводимый способ поставить Hysteria2‑сервер с локальной панелью управления, не собирая проект на production‑сервере и не открывая admin UI наружу.

Проект особенно полезен, если важны:

  • строгая target‑платформа;
  • установка из одного release‑архива;
  • локальный UI через SSH‑туннель;
  • systemd/nftables baseline;
  • проверяемая установка со smoke‑checks;
  • понятная диагностика при сбоях.

Лицензия

HY2XS распространяется на условиях GNU Affero General Public License v3.0 only (AGPL-3.0-only).

Полный текст лицензии находится в LICENSE.

Сторонние библиотеки и зависимости сохраняют собственные лицензии.


Разработано во Flamy Studio.

S
Description
No description provided
Readme AGPL-3.0 2.7 MiB
v1.0.0 Latest
2026-09-08 00:55:49 +00:00
Languages
Go 46.6%
TypeScript 32.9%
Shell 14.5%
Vue 5.6%
PowerShell 0.2%
Other 0.2%