Files
HY2XS_flamy/docs/02-build-layer-and-package.md
T
founder ddf0ddf71e feat(v1): Gecko-обфускация, latest-stable Hysteria на сборке и forward-compatible admin
Сквозная миграция HY2XS на современную Hysteria (2.12.2) и переход на v1.

Build:
- версия Hysteria резолвится на этапе сборки из HyNetworks/hysteria и
  замораживается в metadata пакета (version + immutable url + sha256);
- compatibility gate: реальный бинарник должен принять канонический конфиг
  HY2XS для gecko и salamander до создания пакета;
- сборка прогоняет тесты оркестратора и админки.

Конфигурационный контракт:
- HY2XS_CONFIG_SCHEMA_VERSION=2, чужая схема отклоняется fail-fast;
- obfs стал настоящим union gecko|salamander, gecko — default;
- obfs-блок рендерится оркестратором целиком, два подтипа одновременно
  структурно невозможны;
- современный baseline: congestion bbr/standard, disableLossCompensation=false,
  disableStatelessReset=false, полный quic-блок.

Исправления:
- share URI для gecko: генератор был завязан на Obfs.Salamander.Password и
  выдавал нерабочую ссылку при любой другой обфускации;
- SNI брался только из ACME-блока и уходил пустым при HY2XS_TLS_MODE=file;
- экспорт конфига выносил trafficStats.secret, access_token и obfs-пароль;
- экспорт терял неизвестные upstream-поля при round-trip через типизированную
  модель;
- renderRuntimeEnv печатал тип обфускации литералом, расходясь с конфигом;
- namedotcom удалён из ACME-реестра (нет в Hysteria с 2.11.0).

Тесты:
- 95 тестов оркестратора: env, рендер, семантика профиля, резолвер, rollover;
- тесты URI и экспорта в Go;
- tools/test/e2e-hysteria.sh с реальным клиентом Hysteria.

UX:
- подсказки и примеры в форме создания пира.

Прочее: CHANGELOG.md, .gitattributes (LF для target-side файлов),
документация на русском.
2026-08-27 08:15:02 +05:00

9.6 KiB
Raw Blame History

Build layer and package

Цель документа

Зафиксировать локальный слой сборки и формат итогового install package.

Базовое решение

В baseline builder остаётся shell-first для packaging-слоя.

То есть:

  • основной packaging pipeline — sh/bash
  • оркестратор при этом пишется на Bun + TypeScript
  • builder локально компилирует оркестратор в готовый install-артефакт
  • target machine не должна сама собирать или доустанавливать JS/TS toolchain

Причина простая: packaging можно держать простым, а оркестратор — typed и модульным.

Где работает builder

Production builder работает на отдельном build host:

  • Debian 13
  • amd64 / x86_64
  • bash
  • доступ к интернету для apt и скачивания toolchain

В текущей production-модели сборка выполняется на Debian 13 amd64, а не на Windows/macOS dev-машине.

Builder не является частью target install flow: на target server приезжает уже готовый install package, без JS/TS/Go build step.

Что хранится в репозитории проекта

Минимум:

  • исходники оркестратора на Bun + TypeScript
  • shell packaging scripts
  • шаблоны конфигов
  • systemd unit templates
  • docs
  • исходный код HY2XS admin
  • шаблоны для post-install.env
  • package metadata

Что делает builder

  1. Проверяет структуру проекта.
  2. Прогоняет тесты и типы оркестратора.
  3. Разрешает upstream-версию Hysteria и проходит compatibility gate.
  4. Компилирует оркестратор из Bun/TypeScript в install-артефакт.
  5. Собирает / подготавливает HY2XS admin.
  6. Прогоняет тесты HY2XS admin (после сборки frontend: go:embed all:dist требует готовых ассетов).
  7. Копирует артефакты UI в package staging directory.
  8. Кладёт entrypoint, templates, docs и service files.
  9. Формирует итоговый install package.
  10. Считает manifest/checksum.
  11. Проверяет архив и прогоняет acceptance-проверки.
  12. Выдаёт один переносимый результат для target machine.

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

  • не ставит Hysteria2 на локальной машине «для продакшена»
  • не превращается в CI/CD платформу
  • не генерирует update pipeline
  • не делает uninstall manifests
  • не готовит миграции между старыми инсталляциями

Рекомендуемая структура

project/
├── tools/
│   └── build/
│       ├── build.sh
│       ├── README.md
│       └── lib/
├── orchestrator/
│   ├── package.json
│   ├── bun.lock
│   ├── tsconfig.json
│   └── src/
├── package/
│   ├── install.sh
│   ├── orchestrator/
│   ├── templates/
│   └── systemd/
├── ui/
│   └── hy2xs-admin/
├── docs/
└── dist/

Формат итогового пакета

Итоговый пакет должен содержать:

  • install-only orchestrator artifact
  • bundled HY2XS admin
  • unit templates
  • config templates
  • docs / examples
  • manifest версии проекта

Итоговый пакет не должен содержать:

  • builder scripts
  • исходную локальную build-среду
  • временные каталоги сборки
  • мусор CI
  • target-side dependency install step для оркестратора

Production builder bootstrap

tools/build/build.sh должен быть самодостаточным для Debian 13 amd64:

  1. Проверяет ОС и архитектуру.
  2. Проверяет структуру репозитория и lock-файлы.
  3. Доставляет отсутствующие системные build-зависимости через apt-get.
  4. Проверяет версии Go, Bun, Node.js и pnpm.
  5. При несовпадении версий скачивает управляемый локальный toolchain в .toolchain/.
  6. Собирает только Linux amd64 артефакты.
  7. Записывает версии toolchain в metadata пакета.

Отношение к Hysteria2

Сам бинарь Hysteria2 не вендорится в install package как baseline-правило.

Причина:

  • ядро Hysteria рассматривается как stable upstream component;
  • целевая установка скачивает его с official upstream, но строго по замороженным координатам.

Разрешение версии на сборке

SOURCE
    │
    ▼
resolve latest stable  (HyNetworks/hysteria, только теги app/vX.Y.Z)
    │
    ▼
resolve exact release asset  (hysteria-linux-amd64)
    │
    ▼
download + compute SHA-256
    │
    ▼
compatibility gate  (реальный бинарник принимает канонический конфиг HY2XS)
    │
    ▼
PACKAGE METADATA
    version = vX.Y.Z
    exact_url = <immutable release asset>
    sha256 = <...>
    resolution = latest-stable | pinned | override
    │
    ▼
TARGET SERVER
    скачивает уже конкретный неизменяемый артефакт

Так одновременно выполняются оба требования: «по умолчанию брать последнюю стабильную» и «production-установка должна быть детерминированной и проверяемой».

Переменные builder:

Переменная Значение по умолчанию Назначение
HYSTERIA_CHANNEL stable stable — разрешить последнюю стабильную через upstream API; pinned — взять tools/build/hysteria-lock.env без сети
HYSTERIA_VERSION_OVERRIDE пусто Закрепить конкретную версию vX.Y.Z
HYSTERIA_COMPAT_GATE true Compatibility gate; для release-сборок обязателен
HYSTERIA_WRITE_LOCK false Записать разрешённые значения обратно в tools/build/hysteria-lock.env
GITHUB_TOKEN пусто Опционально, чтобы не упереться в anonymous rate limit

Дополнительно:

  • версия, URL и SHA256 фиксируются в metadata install package (metadata/hysteria.version, metadata/hysteria.url, metadata/hysteria.sha256);
  • способ выбора версии фиксируется в metadata/hysteria.resolution и metadata/package.env;
  • runtime reconfigure не обновляет и не откатывает бинарник Hysteria2;
  • install flow валидирует SHA256 и фактическую версию установленного бинарника;
  • install-time код не обращается к upstream API и не использует moving latest — это проверяется тестами и acceptance-шагом сборки.

Compatibility gate

Gate защищает от ситуации, когда upstream меняет схему конфигурации, а builder молча собирает неработающий HY2XS.

Порядок:

  1. скачать артефакт и сверить SHA-256;
  2. сверить hysteria version с разрешённой версией;
  3. отрендерить канонический конфиг HY2XS тем же кодом, что работает на target (orchestrator/tools/render-canonical-config.ts);
  4. запустить реальный бинарник Hysteria с этим конфигом — для Gecko и для Salamander;
  5. только после этого собирать release package.

При несовместимости ломается сборка:

BUILD FAILED: unsupported Hysteria stable v2.13.0

Это осознанно: ошибка должна проявиться на build machine, а не на сервере оператора.

Инварианты

Система считается правильной, если:

  1. builder запускается на Debian 13 amd64 build host, не как target-side build step
  2. пакет можно перенести на чистый Debian 13
  3. на сервере нет отдельного build step
  4. bundled UI уже находится внутри пакета
  5. оркестратор authored as Bun/TypeScript, но на target приходит как готовый install-артефакт
  6. Hysteria2 подтягивается install layer'ом с upstream по замороженным координатам, а не собирается на target из исходников
  7. выход новой версии Hysteria после сборки не меняет содержимое уже собранного пакета
  8. несовместимый upstream ломает сборку, а не установку у пользователя