Files
HY2XS_flamy/docs/operations/12-operations-and-troubleshooting.md
T

36 KiB
Raw Blame History

Operations and troubleshooting

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

Зафиксировать минимальный operational контур после установки.

Что должен помнить оператор

0. Target prerequisites обязательны

На target-хосте install-flow сам обеспечивает системные зависимости (deps stage):

apt-get update
apt-get install -y sudo ca-certificates curl iproute2 tar openssl nftables systemd

sudo обязателен для smoke-проверок прав от имени runtime-пользователей (hysteria, hy2xs-admin), но его не нужно ставить вручную заранее: на clean-host он устанавливается на deps-стадии до smoke.

Важно: packaged baseline использует HY2XS_SSH_PORT=2323 по умолчанию. На target-хосте это значение обязательно нужно привести к фактическому рабочему SSH-порту оператора в /etc/hy2xs/hy2xs.env и применить через reconfigure --apply.

1. Builder и target — разные миры

Если нужно изменить состав install package, это делается в локальном builder layer, а не на target server.

2. UI приезжает из нашего пакета

Если проблема в UI, сначала смотреть:

  • какой HY2XS_ADMIN_SOURCE
  • какой HY2XS_ADMIN_BUILD_ID
  • тот ли пакет вообще стоит на сервере

3. Hysteria приходит из upstream

Если проблема в ядре Hysteria, сначала смотреть:

  • какую фактическую версию оркестратор установил
  • что записано в HY2_VERSION
  • не связано ли поведение со свежим upstream release
  • какая версия Hysteria зафиксирована в metadata установленного пакета

Для обновления бинарника Hysteria2 используйте новый release install package. Изменение runtime env не обновляет бинарник Hysteria2.

4. Оркестратор — Bun/TypeScript, но target не билдит его

Если проблема в install flow, сначала смотреть:

  • какой ORCH_BUILD_ID
  • какой ORCH_ENTRYPOINT
  • не подменён ли install package вручную

Базовые команды проверки

Проверка сервисов:

systemctl status hysteria-server
systemctl status hy2xs-admin

Проверка порта:

ss -uln

Проверка firewall:

nft list ruleset

Проверка post-install.env:

cat /etc/hysteria/post-install.env

Проверка логов через journald:

journalctl -u hysteria-server.service -n 100 --no-pager
journalctl -u hy2xs-admin.service -n 100 --no-pager

Источник логов в UI:

  • Страница «Логи Hysteria» читает записи из journald unit hysteria-server.service.
  • Экспорт «Логи Hysteria» также формируется из journald (journalctl), а не из отдельного файла hysteria2.log.

Проверка install-state marker:

cat /var/lib/hy2xs/install-state.json

Если reconfigure сообщает об отсутствии marker, нужно повторно выполнить чистый install и только потом применять runtime-изменения.

Auth endpoint fail checklist

systemctl status hysteria-server
systemctl status hy2xs-admin

sudo -u hy2xs-admin test -r /etc/hysteria/config.yaml

curl -sS -X POST \
  -H 'Content-Type: application/json' \
  --data '{"addr":"127.0.0.1:12345","auth":"invalid","tx":0}' \
  http://127.0.0.1:8080/internal/hysteria/auth

curl -sS \
  -H "Authorization: <trafficStatsSecret>" \
  http://127.0.0.1:36712/online

Типовые проблемы

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

Отказ происходит в PHASE 0, до любой мутации. Сервер остался в том состоянии, в котором был: ни /usr/local/lib/hy2xs, ни /var/lib/hy2xs/install-state.json, ни работающие службы не тронуты.

В тексте отказа перечислены конкретные найденные маркеры. Порядок действий — 14-legacy-cleanup.md: сохранить данные, посмотреть план tools/legacy/purge-v0.sh, выполнить очистку, установить заново.

Проверить хост, ничего не устанавливая:

./orchestrator/hy2xs-orchestrator preflight-install --package-dir "$(pwd)"

reconfigure/repair отказываются: маркер чужого поколения

Маркер установки /var/lib/hy2xs/install-state.json не относится к текущему
поколению HY2XS.

installed: true сам по себе ничего не доказывает: такой же маркер мог остаться от 0.x. Обе команды проверяют product, release_line и config_schema_version.

Посмотреть, что видит оркестратор:

hy2xs-orchestrator status --package-dir /usr/local/lib/hy2xs/package \
  | grep -o '"install_state_generation":"[^"]*"'

"current" — маркер текущего поколения; "foreign" — требуется чистая переустановка; "absent" — установки нет.

Незавершённая установка текущего поколения

Если установка упала после начала применения изменений, полная очистка не нужна:

hy2xs-orchestrator repair \
  --package-dir /usr/local/lib/hy2xs/package \
  --config /etc/hy2xs/hy2xs.env \
  --allow-partial-state

Флаг обязателен и осознан: без него repair работает только поверх полностью успешной установки.

Операция отказывает: уже выполняется другая

another HY2XS operation is already in progress: reconfigure (pid 4242, started at …)

install, reconfigure, repair и doctor сериализованы замком /run/lock/hy2xs-orchestrator.lock. Это не перестраховка: production paths — /etc/hysteria/config.yaml, unit-файлы, /etc/nftables.conf, /var/lib/hy2xs/install-state.json — общие, и две одновременные операции записывают их поверх друг друга, после чего откат одной «восстанавливает» состояние поверх изменений другой.

Отказ происходит до первой мутации, поэтому сервер не тронут. Что делать:

# кто держит замок
cat /run/lock/hy2xs-orchestrator.lock

# что делает держатель
ps -o pid,etime,cmd -p "$(sed -n 's/.*"pid": *\([0-9]*\).*/\1/p' /run/lock/hy2xs-orchestrator.lock)"

Дождитесь завершения. Замок снимается сам при любом завершении держателя, включая Ctrl+C, SIGTERM и обрыв SSH, а мёртвого держателя следующая операция обнаруживает и переиспользует замок самостоятельно.

Удалять файл руками нужно ровно в одном случае — если оркестратор сообщил, что содержимое замка не является корректной записью:

operation lock … exists but is not a valid HY2XS lock record

Такой замок сознательно не снимается автоматически: непонятый файл не доказывает, что операции нет.

status и diagnostics collect замок не берут и работают во время операции. В отчёте status при этом появляется поле operation_in_progress — читайте состояние как снимок незавершённой транзакции, а не как итог.

Операция отказывает: guard предыдущей операции ещё вооружён

previous HY2XS operation is no longer running, but its firewall rollback guard
is still armed: hy2xs-fw-rollback-<op-id>.timer (active/waiting)

Предыдущая операция умерла аварийно после применения firewall. Её процесса уже нет — замка может не быть тоже, — но rollback guard это отдельный объект systemd, и он переживает свой процесс. Если начать новую операцию сейчас, guard сработает посреди неё и вернёт firewall, существовавший до предыдущей операции.

Ничего делать не нужно, кроме как подождать: окно guard — 45 секунд с момента применения firewall плюс точность таймера (AccuracySec=1s), то есть не больше 46 секунд.

# сколько ещё ждать и что именно висит
systemctl list-units --all --plain 'hy2xs-fw-rollback-*'
hy2xs-orchestrator status --package-dir /usr/local/lib/hy2xs/package

--plain здесь не для красоты: у юнита в состоянии failed systemctl печатает первой колонкой маркер , и без флага его легко не заметить в списке.

Когда guard сработает, отработавший таймер выгрузится (RemainAfterElapse=no), и операция пройдёт. Состояние failed у сервиса покою не мешает: оно означает, что откат отработал не полностью, и это как раз повод запустить repair, а не ждать дальше — подробности в journalctl -u 'hy2xs-fw-rollback-*'. Такой failed-юнит остаётся загруженным до systemctl reset-failed, но операцию не блокирует.

Операция отказывает: состояние guard'а не удалось выяснить

unable to verify firewall rollback guard state; systemd query failed,
refusing to start a lifecycle operation: systemctl list-units failed: …

Это не «guard вооружён», и ждать здесь нечего. Барьер обязан доказать, что у предыдущей операции не осталось исполнителей, способных изменить firewall; systemctl не ответил, доказательства нет, и операция отказывает до первой мутации.

Отсутствие ответа не равно отсутствию guard'а: systemd мог быть жив, а взведённый таймер — существовать. Разрешить операцию в этой ситуации означало бы допустить срабатывание старого таймера поверх новой операции.

systemctl status
systemctl list-units --all --plain 'hy2xs-fw-rollback-*'
journalctl -u 'hy2xs-fw-rollback-*' --no-pager

Разбирайтесь с systemd/D-Bus и повторяйте операцию. Отдельно ускорять ничего не нужно: systemd-run требуется в preflight, поэтому без работающего systemd операция всё равно не прошла бы — барьер лишь сообщает об этом раньше и точнее.

Установка отказала с firewall_guard_fired

automatic firewall rollback has already fired
phase: firewall_guard_fired

Это означает: автоматический откат firewall сработал раньше, чем операция успела снять guard. Сервер жив и доступен, но работает на прежнем firewall, а не на том, который сгенерировала операция. Именно поэтому фиксация успеха запрещена, даже если smoke успел сойтись, — иначе сервер считался бы настроенным с чужими правилами, что особенно дорого при смене порта Hysteria, SSH или ACME.

Окно guard — 45 секунд (плюс точность таймера, AccuracySec=1s), и оно не обязано покрывать smoke. Причину ищите в том, почему проход в него не уложился:

journalctl -u 'hy2xs-fw-rollback-*' --no-pager
journalctl -u hysteria-server -u hy2xs-admin --since '-10 min' --no-pager

Обычная причина — медленный старт одного из сервисов. После устранения root-cause операция запускается заново; откат уже вернул сервер в исходное состояние.

Сервер установился, но UI не работает

Проверить:

  • разложился ли bundled UI
  • корректен ли unit hy2xs-admin
  • совпадает ли HY2XS_ADMIN_INSTALL_DIR с реальностью
  • не сломан ли bind host / port

Admin UI access via SSH tunnel

Production-модель для UI: HY2XS_UI_BIND_HOST=127.0.0.1, внешний доступ к 8080/tcp не открывается. Доступ оператора выполняется через SSH local forwarding.

Windows-команда туннеля:

ssh -p 2323 \
  -i C:\Users\kirap\.ssh\id_ed25519_uk1 \
  -N \
  -L 127.0.0.1:8080:127.0.0.1:8080 \
  root@185.156.108.141

После запуска открыть http://127.0.0.1:8080/#/login.

Если SSH-туннель не поднимается (administratively prohibited), проверить effective SSH policy:

sshd -T | grep -E '^(port|allowtcpforwarding|permitopen|gatewayports|passwordauthentication|permitrootlogin) '

Рекомендуемый фрагмент hardening sshd_config:

Port 2323
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication 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

Hysteria скачалась, но не стартует

Проверить:

  • валиден ли config
  • совпадают ли listen port и firewall rule
  • домен / SNI / TLS policy
  • реальную установленную версию Hysteria

Тестовый клиент не подключается

Проверить:

  • server_name
  • порт
  • obfs.password
  • auth material
  • что используется совместимый клиентский конфиг

Ни один пир не проходит авторизацию

Симптом резкий: подключения перестают устанавливаться у всех сразу, в журнале админки — device limit unavailable.

Лимит устройств проверяется fail-closed: без ответа /online админка не знает, сколько устройств уже на связи, и пускать подключения не имеет права. Значит вопрос ровно один — почему недоступен Traffic Stats API.

# 1. что записано в конфиге
grep -A2 '^trafficStats:' /etc/hysteria/config.yaml

# 2. отвечает ли API по этому адресу
curl -sS -H "Authorization: <trafficStatsSecret>" http://127.0.0.1:36712/online

# 3. что говорит сама админка
journalctl -u hy2xs-admin -n 100 --no-pager | grep -i 'traffic stats'

Частая причина — правка trafficStats.listen руками. Админка обращается к Traffic Stats API только по loopback, поэтому адрес вроде 192.168.1.10 разводит Hysteria и панель по разным адресам: сама Hysteria работает, туннели существующих клиентов живут, но лимит устройств, учёт трафика и принудительное отключение выключаются разом. С таким конфигом админка отказывает явно:

trafficStats.listen слушает 192.168.1.10, а админка обращается к Traffic Stats
API только по loopback. ...Верните 127.0.0.1 через `hy2xs-orchestrator reconfigure`

Страница конфигурации показывает тот же адрес и называет его состояние. Ответов три, и они означают разное:

адрес что показано что это значит
127.0.0.1:36712 без пометки канон production-профиля
0.0.0.0:36712, :36712 предупреждение API достижим, но опубликован на всех интерфейсах; при HY2XS_FIREWALL_MODE=external|off его не прикрывает ничто
127.0.0.5:36712 ошибка недостижим, см. ниже
192.168.1.10:36712 ошибка панель до него не достучится, доступ пиров уже не работает

Две детали, на которых легко ошибиться:

  • пустой хост в listen — это не loopback: в Go :36712 означает все интерфейсы, ровно как 0.0.0.0;

  • другой адрес loopback — это не «почти правильно». Слушатель на конкретном адресе принимает соединения только на него:

    bind 127.0.0.5:36712  →  dial 127.0.0.1:36712  →  connection refused
    

    Админка обращается к Traffic Stats API строго через 127.0.0.1, поэтому 127.0.0.5 ломает контур доступа так же, как LAN-адрес.

Дашборд показывает «состояние службы неизвестно»

Это не «Hysteria остановлена». Значение означает, что не удалось получить ответ systemctl is-active hysteria-server: сломанный или недоступный systemctl при живой Hysteria выглядит именно так.

Проверяется отдельно от туннеля:

systemctl is-active hysteria-server   # active | inactive | failed | ...

Доступность Traffic Stats API на дашборде — независимый факт, полученный фактическим обращением к API. Сочетание «состояние неизвестно» + «API доступен» означает исправно работающий туннель и сломанную диагностику службы; сочетание «служба активна» + «API недоступен» — предыдущий раздел.

Install/reconfigure падает на DNS AAAA

Проверить значение HY2XS_DNS_AAAA_POLICY в /etc/hy2xs/hy2xs.env:

  • strict (default): AAAA приводит к fail в IPv4-only профиле;
  • warn: warning + продолжение;
  • off: AAAA-check отключён.

Для production baseline рекомендуется strict.

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

Сообщение выглядит так:

DNS IPv4 mismatch for HY2XS_PUBLIC_HOST fi.api.withen.pro:
  DNS A records:       185.xxx.xxx.10
  server public IPv4:  185.xxx.xxx.27

Update the DNS A record before using this server.

Это не ложное срабатывание, а именно то, ради чего проверка сделана: сервисы на машине живы, но публичный endpoint ведёт куда-то ещё. Чаще всего — после принудительной смены IPv4 провайдером.

Что делать:

  1. сверить фактический адрес сервера: ip -4 addr show scope global;
  2. обновить A-запись у DNS-провайдера;
  3. дождаться истечения TTL;
  4. повторить hy2xs-orchestrator doctor.

doctor безопасно запускать на работающем сервере: он не перезапускает сервисы и живые соединения не рвёт. Раньше это было не так — команда звала общий smoke, который начинается с systemctl restart hysteria-server hy2xs-admin, и диагностика подозрения на проблему сама создавала обрыв у всех подключённых клиентов.

Безопасность здесь — инвариант рантайма, а не свойство текущего кода. doctor целиком выполняется под тем же read-only guard, что и PHASE 0 установки: любая запись в файл и любой мутирующий вызов под ним отказывают. Раньше от рестарта защищал один принудительный флаг, а остальные проверки smoke — чтение прав, владельцев и синтаксиса nftables — выполнялись мутирующими раннерами, поэтому настоящая мутация, случайно добавленная в smoke, была бы разрешена молча.

При этом диагностика не сужается: слушатели, healthz, права на файлы, machine auth, trafficStats, версия бинаря, семантика /etc/hysteria/config.yaml и синтаксис nft проверяются полностью.

Где проходит граница read-only

Guard действует внутри процесса оркестратора. Он не способен запретить побочный эффект, который вызвал бы HTTP-запрос в другом процессе, поэтому эта половина границы держится не им, а составом проб.

Существенный случай — machine-auth. Успешная авторизация пира заставляет админку выполнить UPDATE peer.last_connection_at, то есть диагностика изменила бы отображаемое «последнее подключение» у bootstrap-admin-peer. Поэтому проба с действующим паролем выполняется только в режиме install; doctor работает в режиме reconfigure и до неё не доходит. Полный happy-path авторизации проверяют установка и E2E, а не диагностика.

doctor отправляет только пробы, которые заведомо не проходят авторизацию (отсутствующий machine token, неверные учётные данные, некорректный тип поля) и читающие запросы (/healthz, trafficStats /online). Ни одна из них не изменяет данные.

Честная формулировка гарантии:

doctor не изменяет конфигурацию, состояние сервисов, firewall и данные.

Единственный след, который он оставляет, — записи в журнале админки: пробы проходят через обычный обработчик логирования, как любой запрос. Это не состояние системы, но и не «совсем ничего», поэтому сказано прямо.

Вариант server public IPv4: пустой означает, что на интерфейсах нет ни одного публичного маршрутизируемого IPv4 — сервер за NAT. Это топология вне baseline; осознанное решение оформляется через HY2XS_PUBLIC_ENDPOINT_POLICY=warn.

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

Скорость не соответствует ожиданиям

Проверить:

  • bandwidth.* на сервере
  • клиентские up_mbps/down_mbps
  • нет ли ложного ожидания, что один только host BBR решает speed policy

Изменили post-install.env, но runtime не изменился

Это ожидаемо.

post-install.env — reference file, а не autoreconcile engine.

Редактировать нужно /etc/hy2xs/hy2xs.env и затем запускать reconfigure --dry-run/--apply.

Изменили bootstrap-поля, но пароль admin не сменился

Это ожидаемо.

HY2XS_ADMIN_INITIAL_PASSWORD и HY2XS_ADMIN_CON_PASS используются только как bootstrap-данные при первичной установке. Для ротации существующих credentials нужен отдельный flow на уровне account-management.

hy2xs-admin не стартует: «HY2XS_ADMIN_INITIAL_PASSWORD не задан»

Означает, что учётной записи администратора в базе нет, а переменной, из которой её положено создать, — тоже.

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

Что проверять:

systemctl cat hy2xs-admin | grep EnvironmentFile
grep -c '^HY2XS_ADMIN_INITIAL_PASSWORD=' /etc/hy2xs/hy2xs.env
grep -c '^ADMIN_INITIAL_PASSWORD=' /etc/hy2xs/bootstrap-admin.secret

Починка — hy2xs-orchestrator repair --allow-partial-state: значения принадлежат оркестратору, он же приводит hy2xs.env и bootstrap-admin.secret в согласованное состояние.

hy2xs-admin не стартует: «HY2XS_ADMIN_INITIAL_PASSWORD не удовлетворяет контракту панели»

Значение задано, но панель его не приняла бы на форме входа, поэтому учётная запись администратора с ним не создаётся: установка иначе завершилась бы успешно, а войти было бы нельзя.

Контракт пароля — две границы в разных единицах и один запрет:

Требование Кто его ставит
6-64 символа Unicode форма входа и форма смены пароля
не более 72 байт в UTF-8 bcrypt (ErrPasswordTooLong)
валидный UTF-8 без NUL, U+FEFF, суррогатов и noncharacters документированный домен systemd EnvironmentFile=
без управляющих символов Unicode (Cc) политика HY2XS: значение должно воспроизводиться в однострочной форме входа

Границы независимы: у 64 символов длина от 64 до 256 байт. Пароль из 64 кириллических букв — это 128 байт, и он отвергается, хотя в границу символов укладывается. Практический предел: 36 кириллических букв или 18 эмодзи.

Набор символов не ограничен ничем сверх этого, а пробелы по краям являются частью пароля. Именно поэтому такое значение записывается в hy2xs.env в двойных кавычках:

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

Без кавычек пробелы по краям срежет systemd — файл объявлен EnvironmentFile= в юните, — и админка получит не то значение, которое вы записали.

Починка: исправьте значение в /etc/hy2xs/hy2xs.env и выполните hy2xs-orchestrator repair --allow-partial-state.

Как посмотреть bootstrap-пароль

/etc/hy2xs/bootstrap-admin.secret — файл того же формата KEY=VALUE, и значения в нём могут быть закавычены. Читать их cut -d= -f2- нельзя: кавычки уедут в пароль. source и eval тоже не годятся — shell выполнит подстановку команд внутри двойных кавычек, чего сам systemd не делает.

read_bootstrap_field() {
  sudo sed -n "s/^$1=//p" /etc/hy2xs/bootstrap-admin.secret | head -n1 \
    | sed -e 's/^"//' -e 's/"$//' -e 's/\\\(["\\]\)/\1/g'
}

read_bootstrap_field ADMIN_USER
read_bootstrap_field ADMIN_INITIAL_PASSWORD

Аналогичное сообщение про HY2XS_ADMIN_CON_PASS относится к пиру установщика. Его секрет продублирован в bootstrap-admin.secret, откуда его читает проверка machine-auth, поэтому придуманный секрет разошёлся бы с файлом и первая же проверка подключения провалилась бы.

Забыт пароль администратора

systemctl stop hy2xs-admin

# Значения читаются КАК ДАННЫЕ. Обоснование — ниже, оно существенно.
read_runtime_field() {
  sed -n "s/^$1=//p" /etc/hy2xs/hy2xs.env | head -n1 \
    | sed -e 's/^"//' -e 's/"$//' -e 's/\\\(["\\]\)/\1/g'
}

HY2XS_INSTALL_DIR="$(read_runtime_field HY2XS_INSTALL_DIR)"
HY2XS_DATA_DIR="$(read_runtime_field HY2XS_DATA_DIR)"
HY2XS_LOG_DIR="$(read_runtime_field HY2XS_LOG_DIR)"
export HY2XS_DATA_DIR HY2XS_LOG_DIR

"$HY2XS_INSTALL_DIR/hy2xs-admin" reset-admin
systemctl start hy2xs-admin

Пути к базе и журналу (HY2XS_DATA_DIR, HY2XS_LOG_DIR) берутся из runtime env намеренно: это те же значения, с которыми работает юнит.

Почему не set -a; . /etc/hy2xs/hy2xs.env. Здесь стояла именно эта строка, и она стала опасной ровно тогда, когда файл научился нести произвольные значения. Оператор задаёт HY2XS_ADMIN_INITIAL_PASSWORD, набор символов у пароля не ограничен, и запись в файле выглядит так:

HY2XS_ADMIN_INITIAL_PASSWORD="$(touch /tmp/pwn)"

Для systemd это буквальное значение: подстановки в EnvironmentFile= нет вовсе, $ там обычный символ. Но . (source) обрабатывает файл bash, а bash внутри двойных кавычек выполняет подстановку команд — и выполнил бы её от root, вместе с рецептом восстановления доступа.

То же правило действует и для /etc/hy2xs/bootstrap-admin.secret (см. «Как посмотреть bootstrap-пароль» выше): файлы этого формата читаются как ДАННЫЕ. Результат $(read_runtime_field …) повторно как код не исполняется — он становится значением переменной, и это принципиальная разница.

Команда печатает новые логин и пароль в консоль и требует смены пароля при первом входе. Работает поверх существующей установки; на машине без базы она осмысленно откажет — это инструмент восстановления, а не установки.

Автоматический сброс трафика не срабатывает

Проверьте сохранённое расписание:

journalctl -u hy2xs-admin | grep RESET_TRAFFIC_CRON

Невалидное выражение теперь отклоняется API до записи в базу, поэтому попасть в это состояние можно только правкой базы в обход продукта. Планировщик в таком случае поднимается без джобы сброса и пишет ERROR — старт сервиса при этом не прерывается намеренно: на панели висит /internal/hysteria/auth, и её отказ положил бы подключения пользователей.

Починка — сохранить корректное значение в разделе настроек панели; оно применяется сразу, без перезапуска сервиса. Пустое значение — легальное и означает «автоматический сброс выключен».

Правила эксплуатации

  1. Не править сервер как будто на нём есть builder.
  2. Не считать bundled UI источником install-policy.
  3. Не считать post-install.env автоматическим механизмом применения изменений.
  4. Не расширять install-only baseline до lifecycle-manager без отдельного проектного решения.
  5. Не смешивать install baseline и access/bot platform в одной документации.
  6. Не включать IPv6 в runtime-политике HY2XS (проект IPv4-only).