cf094f6e6f
Проход по операциям, которые делают не то, что обещает их имя. 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.
209 lines
9.8 KiB
Markdown
209 lines
9.8 KiB
Markdown
# HY2XS production runbook
|
|
|
|
## 1. Supported target
|
|
|
|
- clean Debian 13 amd64
|
|
- single host install profile
|
|
- IPv4-only runtime model
|
|
|
|
## 2. Required prerequisites
|
|
|
|
```bash
|
|
apt-get update
|
|
apt-get install -y sudo ca-certificates curl iproute2 tar openssl nftables systemd
|
|
```
|
|
|
|
`sudo` обязателен для permission smoke-checks от имени runtime-пользователей.
|
|
|
|
Предварительная ручная установка `sudo` до запуска `./install.sh` не требуется: на clean-host install-flow ставит его на стадии deps до выполнения smoke-checks.
|
|
|
|
## 3. Required open ports
|
|
|
|
- UDP `${HY2XS_HYSTERIA_PORT}`
|
|
- TCP `${HY2XS_UI_PORT}` (обычно localhost bind)
|
|
- TCP `${HY2XS_SSH_PORT}`
|
|
- TCP 80/443 для ACME (в зависимости от типа challenge)
|
|
|
|
## 4. Clean host assumptions
|
|
|
|
- нет legacy-конфликта по runtime-users (`hysteria`, `hy2xs-admin`)
|
|
- нет конфликтующего не-HY2XS nftables entrypoint
|
|
- install запускается от root
|
|
|
|
## 5. Install command
|
|
|
|
```bash
|
|
./install.sh --non-interactive
|
|
```
|
|
|
|
Важно: packaged baseline использует `HY2XS_SSH_PORT=2323` по умолчанию.
|
|
На target-хосте оператор обязан выставить свой рабочий SSH-порт в `/etc/hy2xs/hy2xs.env`
|
|
и применить изменения через `reconfigure --apply`.
|
|
|
|
## 6. Post-install verification
|
|
|
|
```bash
|
|
systemctl status hysteria-server
|
|
systemctl status hy2xs-admin
|
|
ss -H -lun | grep ':443'
|
|
ss -H -ltn | grep ':8080'
|
|
nft list ruleset
|
|
cat /var/lib/hy2xs/install-state.json
|
|
```
|
|
|
|
## 7. Permission verification
|
|
|
|
```bash
|
|
ls -l /etc/hy2xs/hy2xs.env
|
|
ls -l /etc/hysteria/config.yaml
|
|
|
|
sudo -u hysteria test -r /etc/hysteria/config.yaml
|
|
sudo -u hy2xs-admin test -r /etc/hysteria/config.yaml
|
|
sudo -u hy2xs-admin test ! -w /etc/hysteria/config.yaml
|
|
sudo -u hy2xs-admin test ! -r /etc/hy2xs/hy2xs.env
|
|
```
|
|
|
|
## 8. Firewall recovery
|
|
|
|
Если `install`/`reconfigure` падают после firewall apply:
|
|
|
|
- rollback guard не должен отменяться до успешного smoke;
|
|
- для recovery использовать вывод оркестратора и перезапускать apply только после устранения root-cause.
|
|
|
|
## 9. Reconfigure flow
|
|
|
|
```bash
|
|
hy2xs-orchestrator reconfigure --package-dir /usr/local/lib/hy2xs/package --config /etc/hy2xs/hy2xs.env --dry-run
|
|
hy2xs-orchestrator reconfigure --package-dir /usr/local/lib/hy2xs/package --config /etc/hy2xs/hy2xs.env --apply
|
|
```
|
|
|
|
## 10. Admin bootstrap credentials
|
|
|
|
- `HY2XS_ADMIN_INITIAL_PASSWORD` и `HY2XS_ADMIN_CON_PASS` — install-only bootstrap поля.
|
|
- изменение значений в `/etc/hy2xs/hy2xs.env` после install не выполняет автоматическую ротацию существующих credentials.
|
|
|
|
## 11. IPv4/IPv6 policy
|
|
|
|
- HY2XS работает в IPv4-only режиме.
|
|
- если IPv6 включён на хосте/провайдере — это вне baseline и должно быть отдельно управляемо оператором.
|
|
- `HY2XS_DNS_AAAA_POLICY` управляет реакцией preflight на DNS AAAA:
|
|
- `strict` (default) — install/reconfigure прекращается при наличии AAAA;
|
|
- `warn` — выводится warning и выполнение продолжается;
|
|
- `off` — AAAA-проверка игнорируется.
|
|
|
|
## 11a. Публичный endpoint
|
|
|
|
- preflight проверяет, что A-записи `HY2XS_PUBLIC_HOST` (и `HY2XS_DOMAIN`, если
|
|
он отличается) ведут на публичные IPv4 **этого** сервера;
|
|
- проверка работает в `install`, `reconfigure` и `doctor`;
|
|
- адрес сервера определяется локально по интерфейсам, без обращения к внешним
|
|
сервисам определения IP;
|
|
- `HY2XS_PUBLIC_ENDPOINT_POLICY` управляет строгостью:
|
|
- `strict` (default) — расхождение останавливает операцию;
|
|
- `warn` — warning и продолжение (NAT, floating IP, anycast);
|
|
- `off` — сравнение не выполняется;
|
|
- отсутствие A-записи остаётся фатальным при любом значении политики.
|
|
|
|
Типичный сценарий, ради которого это сделано: провайдер принудительно сменил
|
|
IPv4, DNS остался старым. До v1 `doctor` в такой ситуации отвечал успехом, а
|
|
клиентская ссылка отправляла людей на чужую машину.
|
|
|
|
## 12. Validation command
|
|
|
|
```bash
|
|
hy2xs-orchestrator doctor --package-dir /usr/local/lib/hy2xs/package --config /etc/hy2xs/hy2xs.env
|
|
```
|
|
|
|
Команда выполняет preflight + smoke как post-install/post-reboot validation.
|
|
|
|
`doctor` **не перезапускает сервисы**: он диагностирует работающую установку.
|
|
Раньше он собирал контекст с параметрами по умолчанию и звал общий smoke, а тот
|
|
первым же действием выполняет `systemctl restart hysteria-server hy2xs-admin` —
|
|
то есть команда, которую этот раздел предлагает запускать при подозрении на
|
|
проблему, гарантированно обрывала все живые VPN-соединения, включая случай,
|
|
когда с сервисом всё в порядке. Диагностика, меняющая то, что диагностирует,
|
|
отвечает не на заданный вопрос: после рестарта проверяется уже другое состояние.
|
|
|
|
Остальные проверки smoke выполняются полностью — слушатели, права и владельцы
|
|
файлов, machine auth (включая негативные случаи), семантика
|
|
`/etc/hysteria/config.yaml` против production-профиля, версия установленного
|
|
бинаря. Состояние сервера ни одна из них не меняет.
|
|
|
|
Перезапуск сервисов остаётся операцией `install`, `reconfigure --apply` и
|
|
`repair` — там он является частью применения изменений, а не проверкой.
|
|
|
|
## 13. Admin UI access via SSH tunnel
|
|
|
|
Production policy: UI остаётся loopback-only (`HY2XS_UI_BIND_HOST=127.0.0.1`), внешний доступ к `8080/tcp` не открывается.
|
|
Операторский доступ выполняется через SSH local forwarding.
|
|
|
|
Windows tunnel command:
|
|
|
|
```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
|
|
```
|
|
|
|
Open in browser: `http://127.0.0.1:8080/#/login`.
|
|
|
|
Если туннель падает с `administratively prohibited`, проверить effective sshd-конфиг:
|
|
|
|
```bash
|
|
sshd -T | grep -E '^(port|allowtcpforwarding|permitopen|gatewayports|passwordauthentication|permitrootlogin) '
|
|
```
|
|
|
|
Recommended sshd hardening fragment:
|
|
|
|
```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
|
|
```
|
|
|
|
## 14. Secret-safe config sharing
|
|
|
|
Для передачи конфигов в тикеты/чаты используйте встроенную redaction-команду:
|
|
|
|
```bash
|
|
hy2xs-orchestrator redact-config --config /etc/hy2xs/hy2xs.env --out /root/hy2xs.redacted.env
|
|
hy2xs-orchestrator redact-config --config /etc/hysteria/post-install.env --out /root/post-install.redacted.env
|
|
hy2xs-orchestrator redact-config --config /etc/hysteria/config.yaml --out /root/hysteria-config.redacted.yaml --format yaml
|
|
```
|
|
|
|
Инварианты:
|
|
- команда не выводит исходные секреты в stdout;
|
|
- требуется выбрать ровно один режим: `--in-place` или `--out <path>`;
|
|
- `--format auto` пытается определить формат по имени файла, при неоднозначности используйте `--format env|yaml`;
|
|
- YAML редактируется структурно (документ разбирается и обходится как дерево),
|
|
поэтому вложенные секреты вроде `auth.http.url?access_token=…` не переживают
|
|
редакцию, а результат остаётся валидным YAML;
|
|
- в env-файлах секрет вырезается и из URL-значения, даже если имя ключа
|
|
несекретное — например, `HY2_AUTH_URL` в `post-install.env`.
|
|
|
|
Та же редакция применяется к diagnostics-бандлу
|
|
(`hy2xs-orchestrator diagnostics collect`), который собирается автоматически при
|
|
неудачной установке или реконфигурации. Бандл предназначен для передачи наружу,
|
|
поэтому попадающие в него `hy2xs.env`, `post-install.env` и `config.yaml`
|
|
редактируются перед упаковкой.
|
|
|
|
При отказе **до** начала применения изменений (`fatal_pre_apply`) бандл не
|
|
собирается: его сбор сам создал бы каталоги в `/var/log/hy2xs` на сервере,
|
|
который мы обещали не трогать.
|
|
|