# Operations and troubleshooting ## Цель документа Зафиксировать минимальный operational контур после установки. ## Что должен помнить оператор ### 0. Target prerequisites обязательны На target-хосте install-flow сам обеспечивает системные зависимости (deps stage): ```bash 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 вручную ## Базовые команды проверки Проверка сервисов: ```bash systemctl status hysteria-server systemctl status hy2xs-admin ``` Проверка порта: ```bash ss -uln ``` Проверка firewall: ```bash nft list ruleset ``` Проверка `post-install.env`: ```bash cat /etc/hysteria/post-install.env ``` Проверка логов через journald: ```bash 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: ```bash cat /var/lib/hy2xs/install-state.json ``` Если `reconfigure` сообщает об отсутствии marker, нужно повторно выполнить чистый install и только потом применять runtime-изменения. ## Auth endpoint fail checklist ```bash 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: " \ http://127.0.0.1:36712/online ``` ## Типовые проблемы ### Установка отказывается: обнаружена предыдущая установка Отказ происходит в **PHASE 0**, до любой мутации. Сервер остался в том состоянии, в котором был: ни `/usr/local/lib/hy2xs`, ни `/var/lib/hy2xs/install-state.json`, ни работающие службы не тронуты. В тексте отказа перечислены конкретные найденные маркеры. Порядок действий — [14-legacy-cleanup.md](14-legacy-cleanup.md): сохранить данные, посмотреть план `tools/legacy/purge-v0.sh`, выполнить очистку, установить заново. Проверить хост, ничего не устанавливая: ```bash ./orchestrator/hy2xs-orchestrator preflight-install --package-dir "$(pwd)" ``` ### `reconfigure`/`repair` отказываются: маркер чужого поколения ```text Маркер установки /var/lib/hy2xs/install-state.json не относится к текущему поколению HY2XS. ``` `installed: true` сам по себе ничего не доказывает: такой же маркер мог остаться от `0.x`. Обе команды проверяют `product`, `release_line` и `config_schema_version`. Посмотреть, что видит оркестратор: ```bash hy2xs-orchestrator status --package-dir /usr/local/lib/hy2xs/package \ | grep -o '"install_state_generation":"[^"]*"' ``` `"current"` — маркер текущего поколения; `"foreign"` — требуется чистая переустановка; `"absent"` — установки нет. ### Незавершённая установка текущего поколения Если установка упала **после** начала применения изменений, полная очистка не нужна: ```bash 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-команда туннеля: ```bash 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: ```bash sshd -T | grep -E '^(port|allowtcpforwarding|permitopen|gatewayports|passwordauthentication|permitrootlogin) ' ``` Рекомендуемый фрагмент hardening `sshd_config`: ```sshconfig 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 ведёт не на этот сервер Сообщение выглядит так: ```text 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 не задан» Означает, что учётной записи администратора в базе нет, а переменной, из которой её положено создать, — тоже. Придумывать пароль самостоятельно админка не будет: такой пароль не знал бы никто, кроме журнала, а раньше именно он туда и попадал открытым текстом. Сообщение говорит о повреждённом контракте запуска. Что проверять: ```bash 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, поэтому придуманный секрет разошёлся бы с файлом и первая же проверка подключения провалилась бы. ### Забыт пароль администратора ```bash 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`) — те же, с которыми работает юнит. Команда печатает новые логин и пароль в консоль и требует смены пароля при первом входе. Работает поверх существующей установки; на машине без базы она осмысленно откажет — это инструмент восстановления, а не установки. ### Автоматический сброс трафика не срабатывает Проверьте сохранённое расписание: ```bash 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).