docs: FORK.md под новую установку одной командой и все команды kit local
CI / check (push) Canceled after 0s

This commit is contained in:
2026-10-12 19:57:46 +03:00
parent b61a3225d8
commit 619b2120ce
+148 -75
View File
@@ -1,108 +1,181 @@
# Форк 3X-UI KIT (hacker07)
# Форк 3X-UI KIT (hacker07) — своя сборка и свой канал обновлений
Это личный форк [3X-UI KIT](https://github.com/itsnotkubrick/3X-UI_KIT): наш код живёт рядом с
кодом автора и не ломается, когда автор обновляет свой. Здесь описано, как это устроено и что
делать после каждого обновления автора.
Коротко: это [3X-UI KIT](https://github.com/itsnotkubrick/3X-UI_KIT) со своими доработками. Наш код
живёт рядом с кодом автора и не ломается, когда автор выпускает новую версию, а серверы ставятся и
обновляются **из этого репозитория** — релизы подписываются нашим ключом.
## С чего начать: новый VPS
1. Если нужен свой домен для маскировки — заранее направьте его A-запись на IP сервера и освободите
порт 80 (иначе Let's Encrypt не выпустит сертификат). Без домена этот шаг пропускается.
2. Одна команда на сервере (от root):
```bash
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui-local.sh) --domain vpn.example.com
```
3. Скрипт делает всё сам: проверяет сервер → скачивает наш релиз и **проверяет подпись `SHA256SUMS`
и SHA256 установщика** → запускает установщик автора (панель 3X-UI, протоколы на 443,
сайт-заглушка, маскировка, сертификат, подписка, ufw) → закрывает ответ на ping, включает
обновления безопасности, делает `kit fix` → в конце показывает `kit check` и сводку
`kit local hardening`.
4. Забрать ссылки и подписку: `kit user link admin` (или адрес подписки из вывода установки).
Сомневаетесь в канале — сначала ничего не меняющие режимы:
```bash
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --verify-only # только проверка подписи релиза
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --dry-run --domain vpn.example.com # план установки
```
### Флаги установки
| Флаг | Что делает |
|---|---|
| `--domain домен` | свой домен для маскировки: сайт и REALITY маскируются под него (A-запись на сервер, свободный 80) |
| `--sni сайт.com` | маскировка под чужой сайт вместо домена |
| `--panel-on domain\|ip` | где открывать панель и подписку |
| `--ssh-port N` | добавить второй порт SSH (прежний продолжает работать; закрытие — отдельным шагом) |
| `--no-harden` | не закрывать ответ на ping и не включать автообновления безопасности |
| `--no-time` / `--no-check` | не запускать `kit fix` / `kit check` |
| `--verify-only` / `--dry-run` | проверить релиз / показать план и ничего не менять |
| остальные | передаются установщику автора как есть: `--host`, `--user`, `--port`, `--protocols`, `--restore`, `--multi-port`, `--cert`/`--key`, `--panel-ssl` |
Чего скрипт **не** делает (сознательно): `apt full-upgrade` (тянет систему вперёд и может сломать
закреплённые панель 3X-UI 3.9.0 и ядро Xray 26.6.27 — вместо него обновления безопасности),
автоматическую перезагрузку и смену пароля root (в однострочник пароль не подставляем, он попал бы
в список процессов — для этого есть `kit local passwd`).
### Как проверить, что установка удалась
```bash
kit check # без ❌: службы, порт 443 (nginx), подписка, маскировка, сертификат
kit local hardening # сводка: порты SSH, ответ на ping: deny, ufw активен, автообновления: включены
kit local channel # источник — этот репозиторий, ключей в KIT_SIGNERS: 1 (наш)
kit local version # версия сборки: 1.2.5 или новее
ping <IP сервера> # с домашней машины — таймаут: ответ на ping закрыт, это ожидаемо
kit user link admin # ссылка подписки; откройте её в браузере
```
Если ставили с доменом, в `kit check` должны быть строки «свой домен … указывает на этот сервер» и
«сайт маскировки … отвечает по TLS 1.3 и HTTP/2»; предупреждения про известный сайт на чужом IP
быть не должно (это касалось бы вспомогательного XHTTP, у REALITY должен быть ваш домен).
## Команды форка (`kit local`)
```bash
kit local help # справка по всем командам форка
kit local version # версия, источник обновлений, дата сборки нашего файла
kit local channel # откуда берутся обновления и чем проверяется подпись
kit local seams # какие швы форка сейчас в установленном /usr/local/bin/kit
kit local masking # состояние маскировки (у REALITY должен быть свой домен)
kit local hardening # сводка по защите сервера
```
Защита сервера (поведение взято из проекта `StressOzz/vps-setup`, реализация своя и безопаснее):
| Команда | Что делает |
|---|---|
| `kit local ssh 2222` | добавить порт SSH (прежние продолжают работать; порт сначала открывается в ufw, конфиг проверяется через `sshd -t`) |
| `kit local ssh --status` | какие порты SSH слушаются сейчас |
| `kit local ssh --close-old 2222` | закрыть прежние порты после того, как новый проверен из второго окна |
| `kit local ping off\|on\|status` | ответ на ICMP echo: закрыть/вернуть/показать (правилом ufw, видно в `ufw status`) |
| `kit local passwd [юзер]` | сменить пароль (спросит дважды, в историю команд не попадёт) |
| `kit local passwd --generate` | сгенерировать пароль и показать один раз |
| `kit local upgrades on\|off\|status` | автообновления безопасности (только security, без перезагрузки) |
К любой правке можно добавить `--dry-run` — покажет план и ничего не изменит. Копии изменённых
файлов складываются в `/root/kit-local-backup-<дата>/` (не в `/tmp`).
Что `ping off` затрагивает: только ICMP echo. Подписка (HTTPS), панель, REALITY/XHTTP (TCP 443),
Hysteria2 (UDP 443) работают как работали; исходящий ping с самого сервера тоже остаётся. Если
сервер есть в вашем мониторинге — пробу до него делайте по HTTPS/TCP, а не по ICMP.
## Что где лежит
| Что | Где | Правит |
|---|---|---|
| Наши доработки (команды, хуки) | `scripts/kit-local.sh` | только мы |
| Установка одной командой (обёртка) | `scripts/3x-ui-local.sh` | только мы |
| Описание «швов» в коде автора | `tools/fork_apply.py` | только мы |
| Синхронизация с автором и проверки | `tools/fork-sync.sh` | только мы |
| Записи о наших версиях | `FORK-CHANGELOG.md` | только мы |
| Файлы автора (`scripts/kit.sh`, `scripts/3x-ui.sh`, …) | как есть | только автор |
Ключевая идея: **в файлах автора мы правим только «швы»** — несколько констант и одну строку
подключения. Всё, что мы дописываем по существу, лежит в нашем файле, которого автор не знает.
Ключевая идея: в файлах автора мы правим только «швы» — несколько констант, одну строку подключения
и нормализацию сумм в релизном скрипте. Всё, что мы дописываем по существу, лежит в наших файлах.
Швы описаны в одном месте (`tools/fork_apply.py`) и накатываются только на чистое дерево автора;
если автор изменил нужную строку — инструмент останавливается и говорит об этом, а не делает
полу-патч.
## Ветки
## Ветки и релизы
- `upstream` — точная копия ветки автора (`main`), только вперёд.
- `dev` — наша сборка: `upstream` + швы + наш файл. Из неё делаются релизы.
- релизы — теги `v<номера>`; номер = `<версия автора>.<наш уровень>` (например, автор 1.2 → наш
первый релиз 1.2.1, следующий наш — 1.2.2, после релиза автора 1.3 — 1.3.1).
- `dev` — наша сборка: `upstream` + швы + наши файлы; из неё делаются релизы.
- `main` — то же состояние плюс документация после релиза (по нему считается «последняя версия»).
- релизы — теги `v<номера>`; номер = `<версия автора>.<наш уровень>` (автор 1.2 → наш 1.2.1; после
релиза автора 1.3 → 1.3.1). Номер обязан строго расти: `kit update` не принимает откат назад.
Номер обязан строго расти: на серверах `kit update` не принимает откат назад.
## Обновление сервера и канал
## Обновление автора (по шагам)
```bash
kit update --force && kit check # тянет наш релиз из этого репозитория, проверяет нашу подпись
```
Источник файлов — `KIT_RAW` / `kit_ref_raw()` в `scripts/kit.sh` (наш Gitea и наш тег), подпись
проверяется ключом из `KIT_SIGNERS` (там только ключ форка). Ночной `kit-update.timer` (03:00) делает
то же автоматически — поэтому сервер и должен смотреть в этот репозиторий: иначе наши доработки
исчезнут в первую же ночь.
Вернуться на канал автора: скачать `scripts/kit.sh` из релиза автора с GitHub в `/usr/local/bin/kit`,
затем `kit update --force`.
## Обновление от автора (с рабочей станции)
```bash
cd H:/My_Proj/Fork_3X-UI_KIT
bash tools/fork-sync.sh # подтянуть автора, перенести наши правки, прогнать проверки
# при конфликте — разобрать его вручную, инструмент сам ничего не публикует
# при конфликте — разобрать вручную: инструмент сам ничего не публикует
bash tools/release.sh ~/.ssh/3x-ui-kit-fork/release_key # SHA256SUMS + подпись нашим ключом
git add -A && git commit -m "Релиз v$(cat VERSION): швы форка + подпись"
git tag v$(cat VERSION)
git add -A && git commit -m "Релиз v$(cat VERSION): …" && git tag v$(cat VERSION)
git push origin dev v$(cat VERSION) upstream
```
## Установка и обновление из этого репозитория
```bash
# установка одной командой: наш релиз, подпись проверяется до запуска установщика,
# в конце — закрытие ping, автообновления безопасности, kit fix и kit check
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui-local.sh) --domain vpn.example.com
# «а что вы вообще собираетесь запускать?» — проверка подписи релиза без установки
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --verify-only
# план установки без изменений
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --dry-run --domain vpn.example.com
# то же, но без защиты (--no-harden) и с добавлением второго порта SSH
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --sni dl.google.com --no-harden --ssh-port 2222
# только установщик автора, без наших дополнений
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui.sh)
# обновление уже стоящего сервера (тянет наш релиз и проверяет нашу подпись)
kit update --force && kit check
```
Внутри `kit` источником файлов служит `KIT_RAW`/`kit_ref_raw()` — они указывают на этот
репозиторий, а подпись релиза проверяется ключом из `KIT_SIGNERS` (только ключ форка).
## Подпись релизов
- Открытая часть ключа — `tools/fork-signer.pub` и в `KIT_SIGNERS` (в `scripts/kit.sh`).
- Закрытая часть — только на рабочей станции владельца (`~/.ssh/3x-ui-kit-fork/release_key`),
с паролем; в репозиторий, CI и на серверы не попадает. Кто получит ключ — получит root на всех
серверах, которые обновляются из этого репозитория.
- Смена ключа: подпиши новый релиз старым ключом, иначе серверы его не примут.
## Наши команды
```bash
kit local help # справка по дополнениям форка
kit local version # версия, источник обновлений, дата сборки нашего файла
kit local channel # откуда берутся обновления и чем проверяется подпись
kit local seams # какие швы форка сейчас в установленном /usr/local/bin/kit
kit local masking # состояние маскировки
kit local hardening # сводка по защите сервера
# защита сервера (поведение из StressOzz/vps-setup, сделано безопаснее)
kit local ssh 2222 # добавить порт SSH (прежние продолжают работать)
kit local ssh --close-old 2222 # закрыть прежние порты после проверки
kit local ping off # не отвечать на ping (правилом ufw)
kit local upgrades on # автообновления безопасности
kit local passwd --generate # сменить пароль root и показать его один раз
```
У любой правки можно добавить `--dry-run` — покажет план и ничего не изменит.
- Открытая часть ключа — `tools/fork-signer.pub` и в `KIT_SIGNERS` (в `scripts/kit.sh`); она же
вшита в `scripts/3x-ui-local.sh`, чтобы проверять подпись до запуска установщика.
- Закрытая часть — только на рабочей станции владельца (`~/.ssh/3x-ui-kit-fork/release_key`).
В репозиторий, CI и на серверы не попадает: кто получит ключ — получит root на всех серверах,
которые обновляются из этого репозитория. Пароль на ключ пока не установлен
(`ssh-keygen -p -f ~/.ssh/3x-ui-kit-fork/release_key`).
- Смена ключа: новый релиз подписывается **старым** ключом, иначе серверы его не примут.
## Грабли, о которых стоит помнить
1. **Ночное автообновление** (`kit-update.timer`, 03:00) перезаписывает `/usr/local/bin/kit`
подписанным релизом из настроенного репозитория. Поэтому канал обновления и швы — один шаг:
сервер должен смотреть в этот репозиторий, иначе наши правки исчезнут ночью.
2. **Переводы строк.** Релиз подписывается по контрольным суммам файлов в рабочей копии, а сервер
сверяет их с файлами из Gitea. При `core.autocrlf=true` суммы не сойдутся (CRLF против LF):
в этом клоне должно быть `git config core.autocrlf false`.
3. **Наш файл обязан быть в списке релиза** (`tools/release.sh`, `FILES=(…)`) и в списке загрузки
`fetch_release()` — иначе при обновлении `kit.sh` приедет новый, а `kit-local.sh` останется старым.
4. **Панель 3X-UI ставится с GitHub** по закреплённой версии и SHA256 — это шаг автора, форк его не
трогает. Для установки с нуля серверу нужен доступ к GitHub.
1. **Ночное автообновление** (`kit-update.timer`, 03:00) перезаписывает `/usr/local/bin/kit` тем, что
лежит в настроенном репозитории. Канал и наши правки — один шаг, а не два.
2. **Переводы строк.** Релиз подписывается по суммам рабочей копии, а сервер сверяет их с файлами из
Gitea: при `core.autocrlf=true` суммы не сойдутся (CRLF против LF). В клоне должно быть
`git config core.autocrlf false` (и `.gitattributes`), проверка есть в `tools/fork-sync.sh`.
3. **Наш файл обязан быть в двух списках** — `FILES=(…)` в `tools/release.sh` и список загрузки
`fetch_release()` в `scripts/kit.sh`, иначе после обновления `kit-local.sh` останется старым.
4. **Панель 3X-UI ставится с GitHub** по закреплённой версии и SHA256 — это шаг автора; для установки
с нуля серверу нужен доступ к GitHub.
5. **Формат контрольных сумм.** `kit` сверяет имя файла в `SHA256SUMS` строго (`$2 == "путь"`).
На Windows `sha256sum` пишет `hash *путь`, и такие релизы `kit update` отклоняет («в подписанном
списке нет такого файла»), хотя `sha256sum -c` их принимает. Поэтому `tools/release.sh` приводит
список к POSIX-виду **до** подписи, а релизы **v1.2.1–v1.2.4 ставить нельзя** — только v1.2.5+.
Проверять релиз надо логикой самого `kit`, а не одной `sha256sum -c`.
6. **Сборка релиза обращается к GitHub** (сверка закреплённых версий панели и ядра). Из домашней сети
TLS до GitHub иногда рвётся (`schannel: failed to receive handshake`) — просто повторить запуск.
## Что проверено на сегодня
- Релиз `v1.2.5`: подпись сходится с ключом из опубликованного `kit.sh`, строгая сверка сумм
`$2 == путь` для `kit.sh`, `kit-sub.py`, `kit-local.sh` — как это делает `kit` на сервере.
- Публичный однострочник в режиме `--verify-only` отвечает «подпись сошлась, SHA256 установщика
совпал» — проверено снаружи, из домашней сети.
- Установка «в бою» на живом сервере пока не прогонялась: сначала её стоит выполнить на новом VPS,
посмотрев `--verify-only` и `--dry-run`.