Проход по операциям, которые делают не то, что обещает их имя. P0. Удаление bootstrap-admin-peer не было отзывом доступа. Признаком «создавать пир или нет» служило наличие строки в таблице, а HY2XS_ADMIN_CON_PASS продолжает жить в /etc/hy2xs/hy2xs.env — его читает systemd-юнит. Оператор удалял пира, доступ исчезал, и ближайший restart возвращал того же пира с тем же секретом. Молча. Признаком стала отметка BOOTSTRAP_PEER_SEEDED в таблице config: «создавался когда-либо», а не «существует сейчас». Отметка и пир пишутся одной транзакцией. P1. Резервная копия с includeSecrets=true проглатывала и ошибку расшифровки, и отсутствие шифртекста, отдавая пира с пустым secret и успешный ответ. Теперь недоступный секрет любого пира отклоняет весь запрос с указанием имени. P1. DecryptPeerSecret возвращала содержимое колонки как расшифрованный секрет, если оно не начиналось с v1: — остаток поколения с открытыми секретами. P1. doctor перезапускал hysteria-server и hy2xs-admin: диагностика подозрения на проблему обрывала все живые соединения. P1. Админка сама генерировала HYSTERIA2_TRAFFIC_STATS_SECRET, записать который в /etc/hysteria/config.yaml она не может. Сервис объявлял себя здоровым, а machine auth переставал совпадать. P1. Обходы проверки зависимостей (accepted-risk/skipped) не могли произвести артефакт: приёмка требует dependency_security_gate=true. Удалены из сборки и документации, отсутствие проверяется приёмкой. P2. UPDATE по отсутствующей строке config считался успехом, и cron перепланировался при несохранённом значении. Решение по RowsAffected. P2. Слой данных не отличал «записи нет» от «база не ответила»: sentinel-значения ErrPeerNotFound / ErrAdminUserNotFound / ErrConfigNotFound / ErrStorage. P2. Удалены алиасы /:id/client-url и /:id/qr. Контракт разработки: apps/go.mod объявляет toolchain go1.26.7 (директива go — языковой baseline, а не выбор компилятора), tools/dev/doctor.sh|.ps1 сверяют среду с versions.env.
16 KiB
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 работает только поверх полностью
успешной установки.
Сервер установился, но 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
- что используется совместимый клиентский конфиг
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 провайдером.
Что делать:
- сверить фактический адрес сервера:
ip -4 addr show scope global; - обновить A-запись у DNS-провайдера;
- дождаться истечения TTL;
- повторить
hy2xs-orchestrator doctor.
doctor безопасно запускать на работающем сервере: он не перезапускает
сервисы и живые соединения не рвёт. Раньше это было не так — команда звала
общий smoke, который начинается с systemctl restart hysteria-server hy2xs-admin, и диагностика подозрения на проблему сама создавала обрыв у всех
подключённых клиентов.
Вариант 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_CON_PASS относится к пиру установщика.
Его секрет продублирован в bootstrap-admin.secret, откуда его читает проверка
machine-auth, поэтому придуманный секрет разошёлся бы с файлом и первая же
проверка подключения провалилась бы.
Забыт пароль администратора
systemctl stop hy2xs-admin
set -a; . /etc/hy2xs/hy2xs.env; set +a
"$HY2XS_INSTALL_DIR/hy2xs-admin" reset-admin
systemctl start hy2xs-admin
Runtime env подключается намеренно: из него берутся пути к базе и журналу
(HY2XS_DATA_DIR, HY2XS_LOG_DIR) — те же, с которыми работает юнит.
Команда печатает новые логин и пароль в консоль и требует смены пароля при первом входе. Работает поверх существующей установки; на машине без базы она осмысленно откажет — это инструмент восстановления, а не установки.
Автоматический сброс трафика не срабатывает
Проверьте сохранённое расписание:
journalctl -u hy2xs-admin | grep RESET_TRAFFIC_CRON
Невалидное выражение теперь отклоняется API до записи в базу, поэтому попасть в
это состояние можно только правкой базы в обход продукта. Планировщик в таком
случае поднимается без джобы сброса и пишет ERROR — старт сервиса при этом не
прерывается намеренно: на панели висит /internal/hysteria/auth, и её отказ
положил бы подключения пользователей.
Починка — сохранить корректное значение в разделе настроек панели; оно применяется сразу, без перезапуска сервиса. Пустое значение — легальное и означает «автоматический сброс выключен».
Правила эксплуатации
- Не править сервер как будто на нём есть builder.
- Не считать bundled UI источником install-policy.
- Не считать
post-install.envавтоматическим механизмом применения изменений. - Не расширять install-only baseline до lifecycle-manager без отдельного проектного решения.
- Не смешивать install baseline и access/bot platform в одной документации.
- Не включать IPv6 в runtime-политике HY2XS (проект IPv4-only).