lightweight-server/ochenstarik-server-install.sh
2026-07-15 13:41:59 +07:00

162 lines
6.1 KiB
Bash
Raw 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
set -Eeuo pipefail
readonly REPO_RAW_BASE="https://raw.githubusercontent.com/ochenstarik-ui/lightweight-server/main"
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
declare -a STEP_FILES=(
"ochenstarik-server-1.sh"
"ochenstarik-server-2.sh"
"ochenstarik-server-user-3.sh"
"ochenstarik-server-tg-4.sh"
"ochenstarik-server-vpn-5.sh"
"ochenstarik-server-panel-warp-6.sh"
"ochenstarik-server-backup-7.sh"
)
declare -a STEP_TITLES=(
"Часовой пояс, язык терминала, набор программ и swap"
"Базовые пакеты, будущий SSH-порт, IPv4/IPv6 и UFW"
"Администратор, перенос SSH и fail2ban"
"Telegram-уведомления о входах по SSH"
"Системный VPN через Xray"
"Панель 3x-ui и Cloudflare WARP"
"Первичный снимок и расписания резервного копирования"
)
TEMP_FILE=""
log() { printf '[+] %s\n' "$*"; }
warn() { printf '[!] %s\n' "$*" >&2; }
die() { printf '[x] %s\n' "$*" >&2; exit 1; }
cleanup() {
if [[ -n "$TEMP_FILE" && "$TEMP_FILE" == "$SCRIPT_DIR"/.ochenstarik-server-* \
&& -f "$TEMP_FILE" && ! -L "$TEMP_FILE" ]]; then
rm -f -- "$TEMP_FILE"
fi
}
trap cleanup EXIT
ensure_step_script() {
local filename="$1" result_variable="$2" target
target="${SCRIPT_DIR}/${filename}"
if [[ -e "$target" ]]; then
[[ -f "$target" && ! -L "$target" ]] \
|| die "Отказ от запуска: $target должен быть обычным файлом"
else
command -v curl >/dev/null 2>&1 \
|| die "Не найден curl: установите его командой apt-get install -y curl ca-certificates"
[[ -d "$SCRIPT_DIR" && ! -L "$SCRIPT_DIR" && -w "$SCRIPT_DIR" ]] \
|| die "Каталог $SCRIPT_DIR недоступен для безопасной загрузки"
log "Файл ${filename} отсутствует; загружаю его из основного репозитория"
TEMP_FILE="$(mktemp "${SCRIPT_DIR}/.ochenstarik-server-download.XXXXXX")"
chmod 600 "$TEMP_FILE"
curl -fL --retry 5 --retry-delay 5 --connect-timeout 30 \
--proto '=https' --tlsv1.2 "${REPO_RAW_BASE}/${filename}" -o "$TEMP_FILE"
bash -n "$TEMP_FILE" || die "Загруженный файл ${filename} не прошёл проверку Bash"
chmod 700 "$TEMP_FILE"
mv -- "$TEMP_FILE" "$target"
TEMP_FILE=""
fi
chmod 700 "$target"
bash -n "$target" || die "Синтаксическая ошибка в $target"
printf -v "$result_variable" '%s' "$target"
}
choose_step_action() {
local step_number="$1" title="$2" result_variable="$3" answer
while :; do
printf '\n============================================================\n'
printf 'Этап %s из %s: %s\n' "$step_number" "${#STEP_FILES[@]}" "$title"
printf ' 1) Установить / запустить этот этап\n'
printf ' 2) Пропустить и перейти к следующему\n'
printf ' 3) Завершить мастер\n'
read -rp 'Выберите действие: ' answer || die "Ввод прерван"
case "$answer" in
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
*) warn "Введите 1, 2 или 3" ;;
esac
done
}
choose_after_failure() {
local result_variable="$1" answer
while :; do
printf '\nЭтап завершился с ошибкой.\n'
printf ' 1) Запустить этот этап повторно\n'
printf ' 2) Пропустить и перейти к следующему\n'
printf ' 3) Завершить мастер\n'
read -rp 'Выберите действие: ' answer || die "Ввод прерван"
case "$answer" in
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
*) warn "Введите 1, 2 или 3" ;;
esac
done
}
print_summary() {
local completed="$1" skipped="$2"
printf '\n============================================================\n'
printf 'Мастер установки завершён.\n'
printf 'Успешно выполнено этапов: %s\n' "$completed"
printf 'Пропущено этапов: %s\n' "$skipped"
printf '\nМастер можно запустить повторно: каждый этап поддерживает повторную настройку.\n'
printf 'Для полного сброса используйте ochenstarik-server-uninstall.sh.\n'
}
[[ "$EUID" -eq 0 ]] || die "Запустите мастер от имени root: sudo ./ochenstarik-server-install.sh"
((${#STEP_FILES[@]} == ${#STEP_TITLES[@]})) || die "Некорректное описание этапов"
cat <<'INTRO'
Единый мастер установки lightweight-server
Этапы будут показаны по порядку. Каждый из них можно выполнить, пропустить
или завершить весь мастер. Не закрывайте текущую SSH-сессию во время изменения
порта SSH и проверяйте новый вход во втором терминале.
INTRO
completed=0
skipped=0
for index in "${!STEP_FILES[@]}"; do
step_number="$((index + 1))"
action=""
choose_step_action "$step_number" "${STEP_TITLES[index]}" action
case "$action" in
2)
skipped="$((skipped + 1))"
continue
;;
3)
print_summary "$completed" "$skipped"
exit 0
;;
esac
script_path=""
ensure_step_script "${STEP_FILES[index]}" script_path
while :; do
log "Запуск этапа ${step_number}: ${STEP_TITLES[index]}"
if bash -- "$script_path"; then
completed="$((completed + 1))"
log "Этап ${step_number} успешно завершён"
break
fi
warn "Этап ${step_number} вернул ошибку"
failure_action=""
choose_after_failure failure_action
case "$failure_action" in
1) continue ;;
2) skipped="$((skipped + 1))"; break ;;
3) print_summary "$completed" "$skipped"; exit 1 ;;
esac
done
done
print_summary "$completed" "$skipped"