1.1: kit update и kit version для доставки исправлений на серверы 1.0
kit update скачивает kit и kit-sub из тега релиза, переводит kit-sub на работу без root, убирает cron меню x-ui и исправляет ссылку подписки в панели. При сбое новой kit-sub возвращает прежнюю. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7GrBSRPVXhrz3RAprWDnt
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fdae4588ea
commit
7167c8158d
+12
-4
@@ -31,13 +31,21 @@
|
||||
- `SECURITY.md`: как сообщить об уязвимости, не публикуя её на весь интернет.
|
||||
- Проверка кода на каждый коммит: ShellCheck, Python, тесты генераторов.
|
||||
|
||||
**Новая команда: `kit update`**
|
||||
|
||||
- Обновляет kit и подписку до новой версии, а пользователи, ссылки и подписки остаются прежними.
|
||||
Раньше, чтобы получить исправление, приходилось сносить всё и раздавать ссылки заново.
|
||||
«Мам, удали старый VPN, вот новый» больше не повторится.
|
||||
- Если новая подписка вдруг не запустится, `kit update` молча вернёт старую. Ну, не молча,
|
||||
предупредит.
|
||||
|
||||
**Как обновиться**
|
||||
|
||||
- Новые установки получают всё сразу.
|
||||
- Сервер 3X-UI KIT из версии 1.0 (там ещё нет `kit update`), один раз:
|
||||
`curl -fsSL https://raw.githubusercontent.com/itsnotkubrick/3X-UI_KIT/v1.1/scripts/kit.sh -o /usr/local/bin/kit && chmod 755 /usr/local/bin/kit && kit update`
|
||||
- Дальше хватит `kit update`, он сам подскажет, когда выйдет новая версия.
|
||||
- Hysteria2: `hy2 update`.
|
||||
- Серверу 3X-UI из версии 1.0 ничего не угрожает: критическая ошибка была только в установщике
|
||||
Hysteria2 и срабатывала при установке. Перевести подписку на работу без root поможет
|
||||
`kit update` в версии 1.2. Пока можно просто продолжать пользоваться.
|
||||
- Новые установки получают всё сразу.
|
||||
|
||||
## v1.0
|
||||
|
||||
|
||||
@@ -106,6 +106,26 @@ kit user add sasha --gb 50 --days 30
|
||||
|
||||
Трафик и лимиты общие на все протоколы: 50 ГБ — это 50 ГБ суммарно, через что бы пользователь ни подключался.
|
||||
|
||||
## Обновление
|
||||
|
||||
```bash
|
||||
kit update
|
||||
```
|
||||
|
||||
Обновляет команду `kit` и подписку `kit-sub` до новой версии 3X-UI KIT. Пользователи, ссылки
|
||||
и подписки не меняются, раздавать ничего заново не нужно. Файлы берутся из тега релиза
|
||||
на GitHub, а если новая подписка не запустится, `kit update` вернёт прежнюю.
|
||||
`kit version` покажет версию kit, панели и ядра Xray.
|
||||
|
||||
Сервер ставили версией 1.0? В ней команды `kit update` ещё нет, поэтому один раз:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/itsnotkubrick/3X-UI_KIT/v1.1/scripts/kit.sh -o /usr/local/bin/kit && chmod 755 /usr/local/bin/kit && kit update
|
||||
```
|
||||
|
||||
Панель 3X-UI обновляется отдельно, через `x-ui`. Ядро Xray в панели не обновляйте до последней
|
||||
версии: с Xray 26.7 и новее Hiddify, FlClash и Clash Verge не подключаются к REALITY.
|
||||
|
||||
## Параметры
|
||||
|
||||
| Параметр | Что делает |
|
||||
|
||||
+163
-6
@@ -1,15 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# kit — пользователи 3X-UI KIT: один пользователь сразу на всех протоколах.
|
||||
# kit — управление сервером 3X-UI KIT: пользователи и обновление.
|
||||
# https://github.com/itsnotkubrick/3X-UI_KIT
|
||||
#
|
||||
# kit user add имя [--gb 50] [--days 30] [--devices 3]
|
||||
# kit user list | link имя | limit имя [--gb N] [--days N] | off имя | on имя | del имя
|
||||
# kit update | kit version
|
||||
|
||||
set -Eeuo pipefail
|
||||
export LC_ALL=C.UTF-8 # ширина колонок по символам, а не байтам
|
||||
|
||||
KIT_VERSION="1.1"
|
||||
KIT_RAW="https://raw.githubusercontent.com/itsnotkubrick/3X-UI_KIT/main"
|
||||
# Файлы новой версии берём из её тега (v1.2 и т.д.), а не из меняющейся ветки main.
|
||||
kit_ref_raw() { echo "https://raw.githubusercontent.com/itsnotkubrick/3X-UI_KIT/v$1"; }
|
||||
|
||||
XUI_ENV=/etc/x-ui/install-result.env
|
||||
KIT_ENV=/etc/kit/kit.env
|
||||
KIT_LATEST=/etc/kit/latest-version
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
G=$'\e[32m'; Y=$'\e[33m'; R=$'\e[31m'; B=$'\e[1m'; D=$'\e[2m'; N=$'\e[0m'
|
||||
@@ -17,6 +24,7 @@ else
|
||||
G=; Y=; R=; B=; D=; N=
|
||||
fi
|
||||
say() { printf '%s\n' "${G}==>${N} $*"; }
|
||||
warn() { printf '%s\n' "${Y}!${N} $*" >&2; }
|
||||
die() { printf '%s\n' "${R}✗${N} $*" >&2; exit 1; }
|
||||
|
||||
[[ $EUID -eq 0 ]] || die "Запустите от root: sudo -i, затем команду ещё раз."
|
||||
@@ -212,27 +220,176 @@ cmd_del() {
|
||||
say "Пользователь $name удалён, его подписка больше не работает."
|
||||
}
|
||||
|
||||
# ---------- версия и обновление ----------
|
||||
|
||||
xray_version() {
|
||||
local b
|
||||
for b in /usr/local/x-ui/bin/xray-linux-*; do [[ -x $b ]] && "$b" version 2>/dev/null | awk 'NR==1 {print "v" $2}'; return; done
|
||||
}
|
||||
remote_version() { curl -fsS -m "${1:-5}" "$KIT_RAW/VERSION" 2>/dev/null | tr -d '[:space:]'; }
|
||||
newer() { [[ $1 != "$2" && $(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -1) == "$1" ]]; } # $1 новее $2?
|
||||
|
||||
# Раз в сутки узнаём последнюю версию (не дольше 3 секунд) и подсказываем обновиться.
|
||||
update_hint() {
|
||||
local latest=""
|
||||
if [[ ! -f $KIT_LATEST ]] || (($(date +%s) - $(stat -c %Y "$KIT_LATEST") > 86400)); then
|
||||
latest=$(remote_version 3) || true
|
||||
[[ $latest =~ ^[0-9]+(\.[0-9]+)+$ ]] && echo "$latest" >"$KIT_LATEST" || touch "$KIT_LATEST"
|
||||
fi
|
||||
latest=$(cat "$KIT_LATEST" 2>/dev/null || true)
|
||||
if [[ -n $latest ]] && newer "$latest" "$KIT_VERSION"; then
|
||||
echo
|
||||
echo "${Y}↑ Доступна версия $latest${N} (у вас $KIT_VERSION). Обновить: ${B}kit update${N}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_version() {
|
||||
echo "3X-UI KIT $KIT_VERSION"
|
||||
echo "${D}панель 3X-UI $(/usr/local/x-ui/x-ui -v 2>/dev/null | head -1 || echo '?'), ядро Xray $(xray_version)${N}"
|
||||
update_hint
|
||||
}
|
||||
|
||||
# Что нового в версии $1 – из CHANGELOG.md, без разметки.
|
||||
changelog_of() {
|
||||
curl -fsS -m 5 "$KIT_RAW/CHANGELOG.md" 2>/dev/null | awk -v v="## v$1" '
|
||||
index($0, v) == 1 { on = 1; t = substr($0, length(v) + 1); sub(/^[: ]+/, "", t); if (t != "") print t; next } on && /^## / { exit } on' | sed 's/\*\*//g; s/`//g' | grep -v '^[[:space:]]*$' | head -40 || true
|
||||
}
|
||||
|
||||
# Юнит kit-sub: без root (DynamicUser), конфиг и сертификат – через LoadCredential.
|
||||
# Сертификат Let's Encrypt на IP продлевается раз в несколько дней, поэтому при отдельном
|
||||
# порте kit-sub перезапускается раз в сутки и берёт свежий.
|
||||
kit_sub_unit() { # путь-к-сертификату путь-к-ключу (пусто – за nginx)
|
||||
cat <<UNIT
|
||||
[Unit]
|
||||
Description=kit-sub: подписка с учётом приложения (3X-UI KIT)
|
||||
After=network-online.target x-ui.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python3 /usr/local/lib/kit-sub/kit_sub.py
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
DynamicUser=yes
|
||||
LoadCredential=config.json:/etc/kit-sub/config.json
|
||||
${1:+LoadCredential=cert.pem:$1}
|
||||
${2:+LoadCredential=key.pem:$2}
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectProc=invisible
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
MemoryMax=64M
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
UNIT
|
||||
}
|
||||
|
||||
# Сервер ещё не получил исправления 1.1 (например, kit обновили вручную из 1.0)?
|
||||
needs_migration() {
|
||||
[[ -f /etc/cron.d/kit-xui-menu ]] && return 0
|
||||
[[ -f /etc/systemd/system/kit-sub.service ]] && ! grep -q '^DynamicUser=yes' /etc/systemd/system/kit-sub.service && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
cmd_update() {
|
||||
local force=${1:-} latest tmp
|
||||
latest=$(remote_version) || true
|
||||
[[ $latest =~ ^[0-9]+(\.[0-9]+)+$ ]] || die "Не удалось узнать последнюю версию: GitHub недоступен с сервера. Попробуйте позже."
|
||||
echo "$latest" >"$KIT_LATEST"
|
||||
if ! newer "$latest" "$KIT_VERSION" && [[ $force != --force ]] && ! needs_migration; then
|
||||
say "У вас последняя версия: $KIT_VERSION."
|
||||
echo "${D}Переустановить файлы kit той же версии: kit update --force${N}"
|
||||
return
|
||||
fi
|
||||
if [[ $latest == "$KIT_VERSION" ]]; then say "Применяю исправления версии $latest"; else say "3X-UI KIT $KIT_VERSION → $latest"; fi
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' RETURN
|
||||
curl -fsSL --retry 3 -o "$tmp/kit.sh" "$(kit_ref_raw "$latest")/scripts/kit.sh" && bash -n "$tmp/kit.sh" \
|
||||
|| die "Не удалось скачать новую версию kit – сервер не тронут."
|
||||
|
||||
# Подписка kit-sub: ставим новую, при сбое возвращаем старую.
|
||||
if [[ -f /usr/local/lib/kit-sub/kit_sub.py ]]; then
|
||||
curl -fsSL --retry 3 -o "$tmp/kit_sub.py" "$(kit_ref_raw "$latest")/scripts/kit-sub.py" \
|
||||
&& python3 -c "import ast,sys; ast.parse(open(sys.argv[1]).read())" "$tmp/kit_sub.py" \
|
||||
|| die "Не удалось скачать kit-sub – сервер не тронут."
|
||||
cp /usr/local/lib/kit-sub/kit_sub.py "$tmp/kit_sub.old"
|
||||
cp /etc/systemd/system/kit-sub.service "$tmp/kit-sub.service.old"
|
||||
install -m 644 "$tmp/kit_sub.py" /usr/local/lib/kit-sub/kit_sub.py
|
||||
# С 1.1 kit-sub работает без root: переписываем юнит под DynamicUser и LoadCredential.
|
||||
local c k
|
||||
c=$(jq -r '.cert // empty' /etc/kit-sub/config.json); k=$(jq -r '.key // empty' /etc/kit-sub/config.json)
|
||||
kit_sub_unit "$c" "$k" >/etc/systemd/system/kit-sub.service
|
||||
[[ -n $c ]] && echo '19 4 * * * root systemctl restart kit-sub >/dev/null 2>&1' >/etc/cron.d/kit-sub-cert
|
||||
systemctl daemon-reload
|
||||
systemctl restart kit-sub
|
||||
sleep 3
|
||||
if systemctl is-active -q kit-sub; then
|
||||
say "Подписка kit-sub обновлена"
|
||||
else
|
||||
install -m 644 "$tmp/kit_sub.old" /usr/local/lib/kit-sub/kit_sub.py
|
||||
install -m 644 "$tmp/kit-sub.service.old" /etc/systemd/system/kit-sub.service
|
||||
rm -f /etc/cron.d/kit-sub-cert
|
||||
systemctl daemon-reload
|
||||
systemctl restart kit-sub
|
||||
warn "Новая kit-sub не запустилась – вернул прежнюю. Лог: journalctl -u kit-sub -n 30"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Исправления для установок 1.0.
|
||||
local all uri
|
||||
all=$(api POST setting/all)
|
||||
uri=${SUB_BASE:-}
|
||||
if [[ $uri == https://* && $(jq -r '.subURI // ""' <<<"$all") != "$uri" ]]; then
|
||||
api POST setting/update "$(jq -c --arg u "$uri" '.subURI = $u' <<<"$all")" >/dev/null
|
||||
say "Ссылка подписки в панели: $uri…"
|
||||
fi
|
||||
# 1.0 ставил cron, который каждый день правил файлы x-ui, – убираем.
|
||||
rm -f /etc/cron.d/kit-xui-menu
|
||||
|
||||
# Через rename: bash дочитывает текущий kit по ходу работы, его файл трогать нельзя.
|
||||
install -m 755 "$tmp/kit.sh" /usr/local/bin/kit.new && mv -f /usr/local/bin/kit.new /usr/local/bin/kit
|
||||
echo
|
||||
echo "${G}✓ Готово: 3X-UI KIT $latest.${N} Пользователи, ссылки и подписки не менялись."
|
||||
local news
|
||||
news=$(changelog_of "$latest")
|
||||
if [[ -n $news ]]; then echo; echo "${B}Что нового в $latest${N}"; echo "$news"; fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
${B}kit${N} — пользователи: один пользователь сразу на всех протоколах
|
||||
${B}kit${N} $KIT_VERSION – управление сервером 3X-UI KIT
|
||||
|
||||
Пользователи (один пользователь сразу на всех протоколах):
|
||||
kit user add имя [--gb 50] [--days 30] [--devices 3] добавить и показать подписку
|
||||
kit user list трафик, срок, статус
|
||||
kit user link имя [--all] подписка и QR; --all — ещё vpn:// и tg://
|
||||
kit user limit имя [--gb N] [--days N] [--devices N] изменить лимиты (0 — без ограничений)
|
||||
kit user link имя [--all] подписка и QR; --all – ещё vpn:// и tg://
|
||||
kit user limit имя [--gb N] [--days N] [--devices N] изменить лимиты (0 – без ограничений)
|
||||
kit user off имя / kit user on имя выключить и включить
|
||||
kit user del имя удалить
|
||||
|
||||
Сервер:
|
||||
kit update обновить kit и подписку kit-sub (пользователи и ссылки не меняются)
|
||||
kit version версия kit, панели и ядра
|
||||
EOF
|
||||
}
|
||||
|
||||
case "${1:-} ${2:-}" in
|
||||
"user add") shift 2; cmd_add "$@" ;;
|
||||
"user list") cmd_list ;;
|
||||
"user list") cmd_list; update_hint ;;
|
||||
"user link") shift 2; cmd_link "$@" ;;
|
||||
"user limit") shift 2; cmd_limit "$@" ;;
|
||||
"user off") cmd_toggle "${3:-}" false ;;
|
||||
"user on") cmd_toggle "${3:-}" true ;;
|
||||
"user del") shift 2; cmd_del "$@" ;;
|
||||
*) usage ;;
|
||||
"update "*) cmd_update "${2:-}" ;;
|
||||
"version "*|"--version "*|"-v "*) cmd_version ;;
|
||||
*) usage; update_hint ;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user