Files
HY2XS_flamy/docs/runtime/09-post-install-env.md
T

15 KiB
Raw Blame History

Runtime env и post-install snapshot

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

Зафиксировать двухслойную модель:

  • editable runtime env: /etc/hy2xs/hy2xs.env
  • generated deploy snapshot: /etc/hysteria/post-install.env

Зачем нужен файл

После первичной установки оператору нужны:

  1. runtime-файл, который оркестратор читает и валидирует;
  2. snapshot-файл фактического deploy-состояния.

В snapshot видно:

  • какой пакет был установлен
  • какой build артефакт использован
  • какой стек оркестратора применён
  • какая версия Hysteria реально установилась
  • какой build HY2XS admin разложен на target
  • какие базовые параметры сети и портов заданы

Именно для этого создаётся post-install.env.

Чего файл не делает

Этот файл:

  • не делает оркестратор update-manager'ом
  • не гарантирует автоматическое применение изменений
  • не заменяет runtime-конфиги
  • не превращает target в builder

Рекомендуемые пути

/etc/hy2xs/hy2xs.env
/etc/hysteria/post-install.env

/etc/hy2xs/hy2xs.env и /etc/hysteria/post-install.env должны иметь права 0600 root:root.

/etc/hysteria/config.yaml должен иметь права 0640 hysteria:hy2xs-admin (UI только читает).

Минимальный набор переменных

Deploy / package

  • DEPLOY_TARGET_OS
  • DEPLOY_TIMESTAMP (last apply timestamp)
  • PACKAGE_NAME
  • PACKAGE_BUILD_ID
  • PACKAGE_VERSION

Orchestrator

  • ORCH_SOURCE_STACK=bun-typescript
  • ORCH_BUILD_MODE
  • ORCH_BUILD_ID
  • ORCH_ENTRYPOINT

Общие

  • HY2XS_CONFIG_SCHEMA_VERSION
  • DEPLOY_DOMAIN
  • PUBLIC_HOST
  • PUBLIC_PORT
  • SSH_PORT
  • HY2XS_FIREWALL_MODE
  • HY2XS_FIREWALL_STAGED_APPLY
  • HY2XS_ADMIN_USER
  • HY2XS_FORCE_PASSWORD_CHANGE
  • HY2XS_ALLOW_SELF_SIGNED_DEV

Hysteria

  • HY2_SOURCE=official-upstream
  • HY2_VERSION — фактически установленная версия
  • HY2_RESOLUTION — как версия была выбрана при сборке: latest-stable, pinned или override
  • HY2_TLS_MODE
  • HY2_ACME_EMAIL
  • HY2_TLS_CERT_PATH
  • HY2_TLS_KEY_PATH
  • HY2_LISTEN_HOST
  • HY2_PORT
  • HY2_AUTH_MODE
  • HY2_AUTH_URL
  • HY2_TRAFFIC_STATS_LISTEN
  • HY2_OBFS_TYPEgecko или salamander
  • HY2_OBFS_PASSWORD
  • HY2_GECKO_MIN_PACKET_SIZE
  • HY2_GECKO_MAX_PACKET_SIZE
  • HY2_BANDWIDTH_UP
  • HY2_BANDWIDTH_DOWN
  • HY2_DISABLE_LOSS_COMPENSATION
  • HY2_IGNORE_CLIENT_BANDWIDTH
  • HY2_CONGESTION_TYPE
  • HY2_BBR_PROFILE
  • HY2_DISABLE_STATELESS_RESET
  • HY2_CONFIG_PATH

HY2XS admin

  • HY2XS_ADMIN_ENABLED
  • HY2XS_ADMIN_SOURCE
  • HY2XS_ADMIN_BUILD_ID
  • HY2XS_ADMIN_BIND_HOST
  • HY2XS_ADMIN_PORT
  • HY2XS_ADMIN_INSTALL_DIR
  • HY2XS_ADMIN_DATA_DIR
  • HY2XS_ADMIN_LOG_DIR

Как работать с файлами

Правильная модель:

  1. оркестратор создаёт hy2xs.env и post-install.env при установке;
  2. оператор редактирует только hy2xs.env;
  3. оператор запускает reconfigure --dry-run, затем reconfigure --apply;
  4. оркестратор обновляет runtime и перезаписывает snapshot.

Политики проверок DNS

В /etc/hy2xs/hy2xs.env есть две независимые политики, обе по умолчанию strict:

Переменная Что проверяет
HY2XS_DNS_AAAA_POLICY наличие AAAA-записи при IPv4-only профиле
HY2XS_PUBLIC_ENDPOINT_POLICY что A-записи публичного endpoint ведут на публичные IPv4 этого сервера

HY2XS_PUBLIC_ENDPOINT_POLICY принимает strict / warn / off. Ослаблять её имеет смысл только для топологий вне baseline: сервер за NAT, floating IP, anycast. Отсутствие A-записи фатально при любом значении.

Обе политики применяются в install, reconfigure и doctor, потому что живут в общем preflight.

Сетевая идентичность админки

HY2XS_UI_PORT, HY2XS_UI_BIND_HOST, HY2XS_DATA_DIR и HY2XS_LOG_DIR — единственный источник истины для этих величин. Админка читает их из окружения юнита и не хранит собственных копий в SQLite.

Важно:

  • HY2XS_ADMIN_INITIAL_PASSWORD используется только для первичного bootstrap seed;
  • HY2XS_ADMIN_CON_PASS — отдельная runtime-сущность для Hysteria auth/smoke;
  • bootstrap secret хранится в том же формате KEY=VALUE (ADMIN_USER, ADMIN_INITIAL_PASSWORD, ADMIN_CON_PASS), права 0600; значения с пробелами по краям, кавычками или обратными слешами записываются в двойных кавычках — читать файл следует парсером формата, а не cut -d= -f2-;
  • HY2XS_FORCE_PASSWORD_CHANGE в production baseline установлен в false (forced UX-flow пока не реализован);
  • после первичного seed перезапуски hy2xs-admin не должны переопределять пароль admin и con_pass.

В санитизированной диагностике корректное значение true/false у HY2XS_FORCE_PASSWORD_CHANGE остаётся видимым: это boolean состояния, а не пароль. Исключение применяется только к точному имени ключа и допустимому boolean; неизвестное значение скрывается fail-closed. HY2XS_ADMIN_INITIAL_PASSWORD, HY2XS_ADMIN_CON_PASS, пароль obfs, traffic-stats secret и похожие ключи продолжают редактироваться.

Учётные данные администратора проверяются при разборе окружения

HY2XS_ADMIN_USER и HY2XS_ADMIN_INITIAL_PASSWORD — это значения, которые потом принимает форма входа в панель. Оркестратор проверяет их против того же контракта, что и админка (apps/credential/admin.go):

Переменная Требование Значение по умолчанию
HY2XS_ADMIN_USER 6-32 символа из набора a-z A-Z 0-9 !@#$%^&*()_+,-./:;<= hy2xsadmin
HY2XS_ADMIN_INITIAL_PASSWORD 6-64 символа Unicode и не более 72 байт в UTF-8; документированный транспортный домен systemd, включая запрет U+FEFF; набор не ограничен, кроме Cc генерируется

Значение вне контракта роняет установку с явным текстом, называющим границы и набор. Так и должно быть: отказ, пришедший установщику, чинится одной строкой в hy2xs.env, а неработающий вход на готовом сервере — переустановкой.

Проверяется и сгенерированный пароль, а не только заданный оператором: генератор — такой же источник значения.

Границ у пароля две, и они в разных единицах. Предел в 72 байта ставит bcrypt: GenerateFromPassword отвечает ErrPasswordTooLong на пароль длиннее 72 байт, а у 64 символов длина от 64 до 256 байт в зависимости от алфавита. Пока байтовой границы здесь не было, HY2XS_ADMIN_INITIAL_PASSWORD из 64 кириллических букв (128 байт) проходил установку целиком, а первая учётная запись администратора не создавалась вовсе — админка падала при старте. Подробно границы описаны в docs/admin/15-ui-contracts.md.

Окружающие пробелы у HY2XS_ADMIN_USER снимаются. Иначе они уезжали бы в имя учётной записи в SQLite, и вход отказывал бы «неверным логином или паролем» — отказом, который невозможно связать с причиной.

У HY2XS_ADMIN_INITIAL_PASSWORD пробелы по краям, наоборот, являются частью пароля и не снимаются нигде — ни оркестратором, ни админкой, ни хешированием. Чтобы такое значение пережило запись и чтение, оно записывается в двойных кавычках с экранированием \ и ":

HY2XS_ADMIN_INITIAL_PASSWORD="пароль с пробелом на конце "

Кавычки здесь не украшение. Файл читает не только оркестратор, но и systemd — он объявлен EnvironmentFile= в юните hy2xs-admin, — а у незакавыченного значения systemd срезает пробелы по краям и трактует \ как escape. Если вы правите hy2xs.env руками и в пароле есть пробел по краям, кавычка или обратный слеш, закавычьте значение тем же способом. Обычные значения (порты, пути, домены) кавычек не требуют и записываются как раньше.

Есть два ограничения набора символов, и они разного происхождения.

Домен systemd. Значение обязано быть загружаемым из EnvironmentFile=: валидный UTF-8 из Unicode scalar values, без NUL, U+FEFF, суррогатов и noncharacters (U+FDD0..U+FDEF и все *FFFE/*FFFF). Это не наше правило — systemd прогоняет значение через utf8_is_valid и отвечает -EINVAL, то есть файл окружения не загружается и юнит не стартует. Оркестратор проверяет домен на каждом значении файла, а не только на пароле: HY2XS_ADMIN_CON_PASS или obfs-пароль сломали бы загрузку юнита ровно так же.

Политика HY2XS. Сверх этого запрещены управляющие символы Unicode (категория Cc). Формат их несёт, но ввести такой пароль в однострочное поле формы входа всё равно нельзя.

Ограничение U+FEFF берётся из публичной документации systemd. В реализации v257.13 он случайно проходит через unichar_is_valid из-за маски; HY2XS не делает эту ошибку версии частью собственного контракта.

Отказ по любому из двух правил приходит при разборе конфигурации, то есть до первой необратимой операции над хостом: preflight-install и install видят его одинаково.

Значение по умолчанию совпадает в трёх местах и обязано совпадать: package/config/hy2xs.env, orchestrator/src/config/env.ts и запасное значение в apps/dao/sqlite.go. Раньше оркестратор писал admin — пять символов при минимуме панели в шесть, — и установка завершалась INSTALL EXIT CODE: 0, оставляя панель, в которую невозможно войти.

Backlog: секреты в окружении

Документация systemd отдельно рекомендует не передавать секреты через переменные окружения и предлагает для них LoadCredential= / LoadCredentialEncrypted=: окружение процесса видно шире, чем файл с правами 0600.

HY2XS v1 этим не пользуется, и это осознанное решение по срокам, а не недосмотр: переход затрагивает модель секретов всего продукта (машинный токен Hysteria, obfs-пароль, con_pass), а не только пароль администратора. Действующая защита — права 0600, владелец root:root и отсутствие доступа у служебных пользователей (hy2xs-admin и hysteria файл прочитать не могут, что проверяет smoke). Пункт остаётся в backlog как отдельная работа.

Immutable-bootstrap контракт

  • /etc/hy2xs/bootstrap-admin.secret создаётся оркестратором только при первичной установке.
  • На reconfigure --apply bootstrap secret не пересоздаётся и не ротируется автоматически.
  • Изменения HY2XS_ADMIN_INITIAL_PASSWORD в runtime env после первичной установки не должны менять фактический пароль admin.
  • HY2XS_ADMIN_CON_PASS используется как bootstrap-значение при первичной установке; после создания admin account изменение этого значения в /etc/hy2xs/hy2xs.env не пересоздаёт и не обновляет существующий con_pass в SQLite.
  • Ротация con_pass выполняется через account-management слой UI/БД, а bootstrap snapshot остаётся неизменным.

Что нельзя делать

  • сваливать туда временный мусор
  • считать, что edit env автоматически меняет runtime без reconfigure --apply
  • использовать файл как замену настоящей конфигурации сервисов

Пример

Используйте canonical runtime-файл package/config/hy2xs.env как базовый шаблон значений и переносите его параметры в /etc/hy2xs/hy2xs.env.