feat(zarya): modular z init architecture with isolated vps payload template
This commit is contained in:
parent
8259b80620
commit
d3cdb3aea3
|
|
@ -26,7 +26,7 @@ case "${SUBCMD}" in
|
||||||
pack) exec "${ZARYA_DIR}/cmd/pack.sh" "$@" ;;
|
pack) exec "${ZARYA_DIR}/cmd/pack.sh" "$@" ;;
|
||||||
reset|nuke) exec "${ZARYA_DIR}/layers/reset.sh" "$@" ;;
|
reset|nuke) exec "${ZARYA_DIR}/layers/reset.sh" "$@" ;;
|
||||||
gc) exec "${ZARYA_DIR}/layers/gc.sh" "$@" ;;
|
gc) exec "${ZARYA_DIR}/layers/gc.sh" "$@" ;;
|
||||||
srv-init|vps-init) exec "${ZARYA_DIR}/cmd/vps-init.sh" "$@" ;;
|
init) exec "${ZARYA_DIR}/cmd/init.sh" "$@" ;;
|
||||||
help|--help|-h)
|
help|--help|-h)
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
ZARYA Operator Interface (z)
|
ZARYA Operator Interface (z)
|
||||||
|
|
@ -48,7 +48,7 @@ GitOps и оркестрация:
|
||||||
z up [layer] Макро-слои (host, net, tier0, talos, apps, all)
|
z up [layer] Макро-слои (host, net, tier0, talos, apps, all)
|
||||||
z run <selector> Плейбуки Ansible (01, 02)
|
z run <selector> Плейбуки Ansible (01, 02)
|
||||||
z a [-auto-approve] OpenTofu apply в RAM-изоляции
|
z a [-auto-approve] OpenTofu apply в RAM-изоляции
|
||||||
z srv-init <IP> [ALIAS] [FLAGS] Day-0 удаленный бутстрап ноды .srv в 1 клик
|
z init <target> [аргументы...] Модульный Day-0 бутстрап (vps)
|
||||||
Телеметрия и LLM:
|
Телеметрия и LLM:
|
||||||
z snap Снятие аудита в state/snapshots/
|
z snap Снятие аудита в state/snapshots/
|
||||||
z pack [all|atlas|code|state] Сборка контекстов Repomix для LLM
|
z pack [all|atlas|code|state] Сборка контекстов Repomix для LLM
|
||||||
|
|
|
||||||
23
cmd/init.sh
Executable file
23
cmd/init.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
source "${ZARYA_DIR}/lib/common.sh"
|
||||||
|
|
||||||
|
TARGET="${1:-}"
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
case "${TARGET}" in
|
||||||
|
vps|srv)
|
||||||
|
exec "${ZARYA_DIR}/cmd/init/vps.sh" "$@"
|
||||||
|
;;
|
||||||
|
help|--help|-h|"")
|
||||||
|
echo "Использование: z init <target> [аргументы...]"
|
||||||
|
echo "Доступные цели инициализации:"
|
||||||
|
echo " vps Day-0 удаленный бутстрап ноды .srv"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_err "Неизвестная цель инициализации: ${TARGET}. Доступно: vps"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
123
cmd/init/vps.sh
Executable file
123
cmd/init/vps.sh
Executable file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#!/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"
|
||||||
|
|
||||||
|
PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGY8TEByHoDFNsy18VG6BJALc8HUYeoKZz2PeKMyKMND atlas@core"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if [[ -z "${ALIAS}" ]]; then
|
||||||
|
LAST_OCTET="${TARGET_IP##*.}"
|
||||||
|
ALIAS="n${LAST_OCTET}.srv"
|
||||||
|
fi
|
||||||
|
|
||||||
|
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='${PUBKEY}' \
|
||||||
|
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}..."
|
||||||
|
ssh -o ConnectTimeout=5 "${ALIAS}" "hostname"
|
||||||
|
log_ok "Сервер ${ALIAS} успешно инициализирован и верифицирован."
|
||||||
|
|
@ -3,9 +3,9 @@ set -euo pipefail
|
||||||
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
export ATLAS_DIR="${ATLAS_DIR:-$HOME/Projects/atlas}"
|
export ATLAS_DIR="${ATLAS_DIR:-$HOME/Projects/atlas}"
|
||||||
export REPO_ROOT="${ATLAS_DIR}"
|
export REPO_ROOT="${ATLAS_DIR}"
|
||||||
|
|
||||||
source "${ZARYA_DIR}/config.env" 2>/dev/null || true
|
source "${ZARYA_DIR}/config.env" 2>/dev/null || true
|
||||||
source "${ZARYA_DIR}/lib/log.sh"
|
source "${ZARYA_DIR}/lib/log.sh"
|
||||||
source "${ZARYA_DIR}/lib/net.sh"
|
source "${ZARYA_DIR}/lib/net.sh"
|
||||||
source "${ZARYA_DIR}/lib/vault.sh"
|
source "${ZARYA_DIR}/lib/vault.sh"
|
||||||
source "${ZARYA_DIR}/lib/session.sh"
|
source "${ZARYA_DIR}/lib/session.sh"
|
||||||
|
source "${ZARYA_DIR}/lib/ssh.sh"
|
||||||
17
lib/ssh.sh
Normal file
17
lib/ssh.sh
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ssh_register_node() {
|
||||||
|
local alias="$1"
|
||||||
|
local ip="$2"
|
||||||
|
local config_file="${HOME}/.ssh/config"
|
||||||
|
|
||||||
|
if [[ ! -f "${config_file}" ]]; then
|
||||||
|
touch "${config_file}"
|
||||||
|
chmod 600 "${config_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "Host.*[[:space:]]${alias}\([[:space:]]\|$\)" "${config_file}" 2>/dev/null; then
|
||||||
|
printf "\nHost %s\n Hostname %s\n" "${alias}" "${ip}" >> "${config_file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
82
templates/vps-bootstrap.sh
Executable file
82
templates/vps-bootstrap.sh
Executable file
|
|
@ -0,0 +1,82 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
USER_NAME="${BOOTSTRAP_USER:-atlas}"
|
||||||
|
PORT="${BOOTSTRAP_PORT:-1488}"
|
||||||
|
PUBKEY="${BOOTSTRAP_PUBKEY}"
|
||||||
|
TCP_PORTS="${BOOTSTRAP_TCP_PORTS:-1488 80 443}"
|
||||||
|
UDP_PORTS="${BOOTSTRAP_UDP_PORTS:-51820}"
|
||||||
|
UFW_IN="${BOOTSTRAP_UFW_IN:-deny}"
|
||||||
|
UFW_OUT="${BOOTSTRAP_UFW_OUT:-allow}"
|
||||||
|
UFW_FWD="${BOOTSTRAP_UFW_FWD:-deny}"
|
||||||
|
UFW_APP="${BOOTSTRAP_UFW_APP:-skip}"
|
||||||
|
ENABLE_BBR="${BOOTSTRAP_ENABLE_BBR:-true}"
|
||||||
|
DISABLE_IPV6="${BOOTSTRAP_DISABLE_IPV6:-true}"
|
||||||
|
DISABLE_ICMP="${BOOTSTRAP_DISABLE_ICMP:-false}"
|
||||||
|
|
||||||
|
id -u "${USER_NAME}" &>/dev/null || useradd -m -s /bin/bash -G sudo "${USER_NAME}"
|
||||||
|
mkdir -p "/home/${USER_NAME}/.ssh"
|
||||||
|
echo "${PUBKEY}" > "/home/${USER_NAME}/.ssh/authorized_keys"
|
||||||
|
chmod 700 "/home/${USER_NAME}/.ssh"
|
||||||
|
chmod 600 "/home/${USER_NAME}/.ssh/authorized_keys"
|
||||||
|
chown -R "${USER_NAME}:${USER_NAME}" "/home/${USER_NAME}/.ssh"
|
||||||
|
|
||||||
|
echo "${USER_NAME} ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/${USER_NAME}"
|
||||||
|
chmod 440 "/etc/sudoers.d/${USER_NAME}"
|
||||||
|
|
||||||
|
if systemctl is-active --quiet ssh.socket 2>/dev/null; then
|
||||||
|
systemctl disable --now ssh.socket
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf /etc/ssh/sshd_config.d/*.conf
|
||||||
|
cat << SSHEOF > /etc/ssh/sshd_config
|
||||||
|
Port ${PORT}
|
||||||
|
PasswordAuthentication no
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
PermitRootLogin prohibit-password
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
X11Forwarding no
|
||||||
|
AcceptEnv LANG LC_*
|
||||||
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||||
|
SSHEOF
|
||||||
|
|
||||||
|
systemctl enable --now ssh.service
|
||||||
|
systemctl restart ssh.service
|
||||||
|
|
||||||
|
which ufw >/dev/null 2>&1 || (DEBIAN_FRONTEND=noninteractive apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y ufw)
|
||||||
|
ufw --force reset
|
||||||
|
ufw default ${UFW_IN} incoming
|
||||||
|
ufw default ${UFW_OUT} outgoing
|
||||||
|
ufw default ${UFW_FWD} forward
|
||||||
|
sed -i -E 's/^DEFAULT_APPLICATION_POLICY=.*/DEFAULT_APPLICATION_POLICY="'${UFW_APP}'"/' /etc/default/ufw || true
|
||||||
|
|
||||||
|
if [[ "${DISABLE_IPV6}" == "true" ]]; then
|
||||||
|
sed -i -E 's/^IPV6=.*/IPV6=no/' /etc/default/ufw || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
for p in ${TCP_PORTS}; do
|
||||||
|
ufw allow "${p}/tcp"
|
||||||
|
done
|
||||||
|
|
||||||
|
for p in ${UDP_PORTS}; do
|
||||||
|
ufw allow "${p}/udp"
|
||||||
|
done
|
||||||
|
|
||||||
|
ufw --force enable
|
||||||
|
|
||||||
|
rm -f /etc/sysctl.d/99-atlas.conf
|
||||||
|
touch /etc/sysctl.d/99-atlas.conf
|
||||||
|
|
||||||
|
if [[ "${ENABLE_BBR}" == "true" ]]; then
|
||||||
|
printf "net.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\n" >> /etc/sysctl.d/99-atlas.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${DISABLE_IPV6}" == "true" ]]; then
|
||||||
|
printf "net.ipv6.conf.all.disable_ipv6 = 1\nnet.ipv6.conf.default.disable_ipv6 = 1\nnet.ipv6.conf.lo.disable_ipv6 = 1\n" >> /etc/sysctl.d/99-atlas.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${DISABLE_ICMP}" == "true" ]]; then
|
||||||
|
printf "net.ipv4.icmp_echo_ignore_all = 1\n" >> /etc/sysctl.d/99-atlas.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
sysctl --system >/dev/null 2>&1 || true
|
||||||
Loading…
Reference in a new issue