server-monitor-manager/agents/_salvage-2026-08-18/smm-deliverables/Старые задачи/smm-setup.sh
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

235 lines
9.6 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Установщик Server Monitor Manager для одного сервера.
#
# sudo ./smm-setup.sh hub <публичный-хост> [https-порт] [wg-порт]
# sudo ./smm-setup.sh node
# sudo ./smm-setup.sh check
#
# Скачивает bootstrap и release-архив из GitHub Release, проверяет контрольные
# суммы и выполняет установку выбранной роли. Ничего не удаляет.
set -Eeuo pipefail
IFS=$'\n\t'
REPO="${SMM_REPO:-ochenstarik-ui/server-monitor-manager}"
TAG="${SMM_TAG:-v0.1.0-alpha.8}"
WORK_DIR="${SMM_WORK_DIR:-/opt/smm}"
HTTPS_PORT_DEFAULT=7443
WG_PORT_DEFAULT=51820
say() { printf '\n[smm-setup] %s\n' "$*"; }
ok() { printf '[smm-setup] ok: %s\n' "$*"; }
fail() { printf '\n[smm-setup] ОШИБКА: %s\n' "$*" >&2; exit 1; }
require_root() {
[[ ${EUID:-$(id -u)} -eq 0 ]] || fail "запускать через sudo"
}
check_platform() {
say "Проверка платформы"
[[ -r /etc/os-release ]] || fail "/etc/os-release отсутствует"
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-}" in
ubuntu) case "${VERSION_ID:-}" in 22.04|24.04) ;; *) fail "Ubuntu ${VERSION_ID:-?} не поддерживается, нужна 22.04 или 24.04" ;; esac ;;
debian) case "${VERSION_ID:-}" in 12|13) ;; *) fail "Debian ${VERSION_ID:-?} не поддерживается, нужна 12 или 13" ;; esac ;;
*) fail "дистрибутив ${ID:-?} не поддерживается: нужны Ubuntu или Debian" ;;
esac
[[ "$(ps -p 1 -o comm=)" == "systemd" ]] || fail "PID 1 не systemd"
case "$(uname -m)" in
x86_64) RUNTIME="linux-x64" ;;
aarch64|arm64) RUNTIME="linux-arm64" ;;
*) fail "архитектура $(uname -m) не поддерживается" ;;
esac
ok "${ID} ${VERSION_ID}, $(uname -m) -> ${RUNTIME}"
}
# Возвращает 1, если что-то занято. Решение принимает вызывающий.
check_ports() {
local role="$1" busy=0
say "Проверка портов"
if [[ "$role" == "hub" ]]; then
if ss -lntu 2>/dev/null | grep -qE ":${HTTPS_PORT}\b"; then
printf '[smm-setup] ЗАНЯТ tcp/%s:\n' "$HTTPS_PORT"
ss -lntup 2>/dev/null | grep -E ":${HTTPS_PORT}\b" || true
busy=1
else ok "tcp/${HTTPS_PORT} свободен"; fi
if ss -lnu 2>/dev/null | grep -qE ":${WG_PORT}\b"; then
printf '[smm-setup] ЗАНЯТ udp/%s:\n' "$WG_PORT"
ss -lnup 2>/dev/null | grep -E ":${WG_PORT}\b" || true
busy=1
else ok "udp/${WG_PORT} свободен"; fi
fi
if ip -4 route 2>/dev/null | grep -q '10\.77\.0\.'; then
printf '[smm-setup] ЗАНЯТА подсеть 10.77.0.0/24:\n'
ip -4 route 2>/dev/null | grep '10\.77\.0\.' || true
busy=1
else ok "подсеть 10.77.0.0/24 свободна"; fi
return "$busy"
}
show_state() {
# Все проверки здесь диагностические: ненулевой код — это нормальный ответ,
# а не отказ. Поэтому каждая обёрнута так, чтобы не уронить set -e.
say "Текущее состояние"
local units xui
units="$(systemctl is-active \
ochenstarik-smm-control.service \
ochenstarik-smm-agent.service \
ochenstarik-smm-provisioning-helper.service \
wg-quick@smm0.service 2>&1 | paste -sd' ' || true)"
printf '[smm-setup] юниты: %s\n' "${units:-неизвестно}"
if [[ -e /etc/wireguard/smm0.conf ]]; then ok "smm0 настроен"; else ok "smm0 не настроен"; fi
if nft list table inet ochenstarik_smm >/dev/null 2>&1; then ok "таблица nftables есть"; else ok "таблицы nftables нет"; fi
xui="$(systemctl is-active x-ui 2>/dev/null || true)"
printf '[smm-setup] x-ui: %s\n' "${xui:-не установлен}"
}
install_dependencies() {
say "Установка зависимостей"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq --no-install-recommends \
curl ca-certificates openssl coreutils tar sudo util-linux netcat-openbsd
ok "зависимости установлены"
}
download_and_verify() {
local base="https://github.com/${REPO}/releases/download/${TAG}"
local archive="server-monitor-manager-${RUNTIME}.tar.gz"
say "Загрузка релиза ${TAG}"
install -d -m 0755 "$WORK_DIR"
cd "$WORK_DIR"
printf '[smm-setup] архив ~24 МБ, это может занять минуту\n'
local file
for file in \
"ochenstarik-server-monitor-manager.sh" \
"ochenstarik-server-monitor-manager.sh.sha256" \
"$archive" \
"${archive}.sha256"
do
printf '[smm-setup] качаю %s\n' "$file"
curl -fL --retry 3 --connect-timeout 20 --progress-bar -o "$file" "${base}/${file}" \
|| fail "не удалось скачать ${file} из релиза ${TAG}. Тег опубликован? Артефакты собраны?"
ok "получен $file ($(du -h "$file" | cut -f1))"
done
say "Проверка контрольных сумм"
sha256sum -c ochenstarik-server-monitor-manager.sh.sha256 || fail "контрольная сумма bootstrap не совпала"
sha256sum -c "${archive}.sha256" || fail "контрольная сумма архива не совпала"
ok "суммы совпали"
chmod 700 ochenstarik-server-monitor-manager.sh
ARCHIVE_PATH="${WORK_DIR}/${archive}"
BOOTSTRAP="${WORK_DIR}/ochenstarik-server-monitor-manager.sh"
}
run_preflight() {
say "Preflight"
"$BOOTSTRAP" preflight
"$BOOTSTRAP" verify-release "$ARCHIVE_PATH"
ok "релиз пригоден"
}
install_hub() {
say "Установка Control Hub"
"$BOOTSTRAP" install-control "$ARCHIVE_PATH" "$PUBLIC_HOST" "$HTTPS_PORT"
say "Инициализация mesh"
"$BOOTSTRAP" mesh-init "$PUBLIC_HOST" "$WG_PORT"
say "Состояние"
"$BOOTSTRAP" status
"$BOOTSTRAP" control-ca-fingerprint
cat <<EOF
[smm-setup] ГОТОВО. Hub установлен.
Откройте во внешнем firewall хостера:
TCP ${HTTPS_PORT}
UDP ${WG_PORT}
Дальше для каждого Node на этом Hub выпустите код:
sudo ${BOOTSTRAP} node-code <имя-node>
Имена для приёмки: ai-agent, home, second.
Полученный SMMNODE2-код введите на Node командой:
sudo ./smm-setup.sh node
Возвращённый Node код SMMPEER1 активируйте здесь:
sudo ${BOOTSTRAP} peer-add 'SMMPEER1....'
sudo ${BOOTSTRAP} mesh-status
EOF
}
install_node() {
say "Установка Node"
cat <<'EOF'
[smm-setup] Сейчас будет запрошен одноразовый код SMMNODE2, выданный на Hub
[smm-setup] командой node-code. После него сверьте отпечаток Control CA
[smm-setup] с тем, что показал Hub, и введите yes.
EOF
"$BOOTSTRAP" install-node "$ARCHIVE_PATH"
cat <<EOF
[smm-setup] ГОТОВО. Node установлен.
Скопируйте выведенный выше код SMMPEER1 и активируйте его на Hub:
sudo /opt/smm/ochenstarik-server-monitor-manager.sh peer-add 'SMMPEER1....'
Проверка на этом сервере:
sudo systemctl is-active ochenstarik-smm-agent.service
sudo wg show smm0
EOF
}
usage() {
cat <<EOF
Установщик Server Monitor Manager
sudo ./smm-setup.sh hub <публичный-хост> [https-порт] [wg-порт]
sudo ./smm-setup.sh node
sudo ./smm-setup.sh check
Переменные окружения:
SMM_TAG тег релиза (сейчас ${TAG})
SMM_REPO репозиторий (сейчас ${REPO})
SMM_WORK_DIR рабочий каталог (сейчас ${WORK_DIR})
EOF
}
main() {
local role="${1:-help}"
case "$role" in
hub)
[[ $# -ge 2 ]] || fail "укажите публичный хост: sudo ./smm-setup.sh hub <хост> [порт] [wg-порт]"
PUBLIC_HOST="$2"
HTTPS_PORT="${3:-$HTTPS_PORT_DEFAULT}"
WG_PORT="${4:-$WG_PORT_DEFAULT}"
[[ "$PUBLIC_HOST" =~ ^[A-Za-z0-9]([A-Za-z0-9.-]{0,251}[A-Za-z0-9])?$ ]] \
|| fail "некорректный публичный хост: $PUBLIC_HOST"
require_root; check_platform; show_state
check_ports hub || fail "освободите занятое либо задайте другие порты аргументами"
install_dependencies; download_and_verify; run_preflight; install_hub
;;
node)
HTTPS_PORT="$HTTPS_PORT_DEFAULT"; WG_PORT="$WG_PORT_DEFAULT"
require_root; check_platform; show_state
check_ports node || fail "освободите подсеть 10.77.0.0/24"
install_dependencies; download_and_verify; run_preflight; install_node
;;
check)
HTTPS_PORT="${2:-$HTTPS_PORT_DEFAULT}"; WG_PORT="${3:-$WG_PORT_DEFAULT}"
require_root; check_platform; show_state
check_ports hub || true
say "Диагностика завершена, изменений не вносилось"
;;
help|-h|--help) usage ;;
*) usage; fail "неизвестная роль: $role" ;;
esac
}
main "$@"