zarya/cmd/init/vps.sh

143 lines
4.9 KiB
Bash
Executable file

#!/bin/bash
set -euo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "${ZARYA_DIR}/lib/common.sh"
TARGET_IP=""
ALIAS=""
PORT="${SRV_DEFAULT_PORT:-1488}"
USER_NAME="${SRV_DEFAULT_USER:-atlas}"
TCP_PORTS="${SRV_DEFAULT_TCP_PORTS:-1488 80 443}"
UDP_PORTS="${SRV_DEFAULT_UDP_PORTS:-51820}"
UFW_IN="${SRV_UFW_INCOMING:-deny}"
UFW_OUT="${SRV_UFW_OUTGOING:-allow}"
UFW_FWD="${SRV_UFW_FORWARD:-deny}"
UFW_APP="${SRV_UFW_APPLICATION:-skip}"
ENABLE_BBR="${SRV_ENABLE_BBR:-true}"
DISABLE_IPV6="${SRV_DISABLE_IPV6:-true}"
DISABLE_ICMP="${SRV_DISABLE_ICMP:-false}"
VERIFY_GATE="false"
while [[ $# -gt 0 ]]; do
case "$1" in
--verify|--test|-v)
VERIFY_GATE="true"
shift
;;
--port)
PORT="$2"
shift 2
;;
--user)
USER_NAME="$2"
shift 2
;;
--tcp)
TCP_PORTS="$2"
shift 2
;;
--udp)
UDP_PORTS="$2"
shift 2
;;
--disable-icmp)
DISABLE_ICMP="true"
shift
;;
--enable-icmp)
DISABLE_ICMP="false"
shift
;;
--disable-ipv6)
DISABLE_IPV6="true"
shift
;;
--enable-ipv6)
DISABLE_IPV6="false"
shift
;;
--no-bbr)
ENABLE_BBR="false"
shift
;;
--help|-h)
echo "Использование: z init vps <IP> [ALIAS] [--verify] [--port N] [--user NAME] [--tcp 'PORTS'] [--udp 'PORTS'] [--disable-icmp] [--disable-ipv6] [--no-bbr]"
exit 0
;;
*)
if [[ -z "${TARGET_IP}" ]]; then
TARGET_IP="$1"
elif [[ -z "${ALIAS}" ]]; then
ALIAS="$1"
fi
shift
;;
esac
done
if [[ -z "${TARGET_IP}" ]]; then
log_err "IP-адрес целевого сервера обязателен. Введите 'z init vps --help'."
exit 1
fi
SSH_CONFIG="${HOME}/.ssh/config"
if [[ -z "${ALIAS}" ]]; then
CURRENT_MAX=$(grep -oP 'Host\s+n\K[0-9]+(?=\.srv)' "${SSH_CONFIG}" 2>/dev/null | sort -n | tail -n1 || true)
CURRENT_MAX="${CURRENT_MAX:-0}"
NEXT_NUM=$(( CURRENT_MAX + 1 ))
ALIAS="n${NEXT_NUM}.srv"
fi
if [[ ! -f "${RAM_KEY}" ]] || [[ ! -s "${RAM_KEY}" ]]; then
log_err "Аппаратный ключ в RAM отсутствует (${RAM_KEY}). Выполните 'z login'."
exit 1
fi
PUBKEY_B64=$(ssh-keygen -y -f "${RAM_KEY}" | base64 -w0)
ssh-keygen -R "${TARGET_IP}" >/dev/null 2>&1 || true
ssh-keygen -R "${ALIAS}" >/dev/null 2>&1 || true
ssh-keygen -R "[${TARGET_IP}]:${PORT}" >/dev/null 2>&1 || true
ssh-keygen -R "[${TARGET_IP}]:22" >/dev/null 2>&1 || true
log_info "Инициализация ноды ${ALIAS} (${TARGET_IP}:${PORT})..."
ssh -o StrictHostKeyChecking=accept-new -p 22 "root@${TARGET_IP}" \
"env BOOTSTRAP_USER='${USER_NAME}' \
BOOTSTRAP_PORT='${PORT}' \
BOOTSTRAP_PUBKEY_B64='${PUBKEY_B64}' \
BOOTSTRAP_TCP_PORTS='${TCP_PORTS}' \
BOOTSTRAP_UDP_PORTS='${UDP_PORTS}' \
BOOTSTRAP_UFW_IN='${UFW_IN}' \
BOOTSTRAP_UFW_OUT='${UFW_OUT}' \
BOOTSTRAP_UFW_FWD='${UFW_FWD}' \
BOOTSTRAP_UFW_APP='${UFW_APP}' \
BOOTSTRAP_ENABLE_BBR='${ENABLE_BBR}' \
BOOTSTRAP_DISABLE_IPV6='${DISABLE_IPV6}' \
BOOTSTRAP_DISABLE_ICMP='${DISABLE_ICMP}' \
bash -s" < "${ZARYA_DIR}/templates/vps-bootstrap.sh"
ssh_register_node "${ALIAS}" "${TARGET_IP}"
if [[ "${VERIFY_GATE}" == "true" ]]; then
log_warn "Включен режим ручного подтверждения."
echo "Откройте соседний терминал и выполните: ssh ${ALIAS}"
read -r -p "Подключение успешно? [y/N]: " CONFIRM
if [[ "${CONFIRM}" != "y" && "${CONFIRM}" != "Y" ]]; then
log_err "Подтверждение отклонено оператором. Откат конфигурации..."
ssh -o ConnectTimeout=10 -p "${PORT}" -i "${RAM_KEY}" "${USER_NAME}@${TARGET_IP}" "sudo ufw disable && sudo sed -i -E 's/^Port .*/Port 22/' /etc/ssh/sshd_config && sudo systemctl restart ssh.service" || true
log_warn "Откат завершен: порт 22 возвращен, UFW выключен."
exit 1
fi
fi
log_info "Автоматическая валидация ноды ${ALIAS}..."
if ! ssh -o ConnectTimeout=5 -o BatchMode=yes "${ALIAS}" "hostname" >/dev/null 2>&1; then
log_err "Валидация FIDO2-ключа для ${ALIAS} провалена."
echo "Диагностика SSH-соединения:"
ssh -v -o ConnectTimeout=5 -o BatchMode=yes "${ALIAS}" 2>&1 | grep -E 'Offering|Authenticat|Denied|Connection' || true
exit 1
fi
log_ok "Сервер ${ALIAS} (${TARGET_IP}:${PORT}) успешно инициализирован и подтвержден."