#!/usr/bin/env bash # ПРОВЕРИТЬ ЧТО ЗАПУСТИТСЯ НЕ ОТ ROOT # ТАК КАК ИНИТ ВЫЗЫВАЕТСЯ КОМАНДОЙ sudo -u "$USERNAME" -H bash "$init_script" # Скрипт инициализации ноды. # 1. Скачивает случайный шаблон сайта и разворачивает его в /var/www/html. # ПРОПУСТИТЬ 2. Создаёт докер-сеть, указанную в docker-compose.yml. # 3. Запрашивает необходимые параметры у пользователя и записывает их в .env. # 4. Открывает порт панели только для центрального сервера. # 5. Запускает docker compose. set -euo pipefail SELF_PATH="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || printf '%s\n' "$0")" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" SITE_DIR="$SCRIPT_DIR/site" SITE_BAC_DIR="$SCRIPT_DIR/site_bac" CERT_DIR="$SITE_DIR/certs" CERT_FILE="$CERT_DIR/certchain.pem" KEY_FILE="$CERT_DIR/key.pem" ENV_FILE="$SCRIPT_DIR/.env-node" NGINX_TEMPLATE="$SCRIPT_DIR/nginx.conf.template" NGINX_CONF="$SCRIPT_DIR/nginx.conf" LOG_DIR="$SCRIPT_DIR/logs" LOGROTATE_DIR="/etc/logrotate.d" LOGROTATE_CONF="$LOGROTATE_DIR/remnanode" # --- Шаг 1: загрузка случайного шаблона сайта --- TMP_DIR=$(mktemp -d) trap 'rm -rf "$TMP_DIR"' EXIT git clone --depth 1 https://github.com/distillium/sni-templates "$TMP_DIR" >/dev/null 2>&1 TEMPLATE_DIR=$(find "$TMP_DIR" -mindepth 1 -maxdepth 1 -type d ! -name '.git' | shuf -n 1) if [ -d $SITE_DIR ] && [ "$(ls -A $SITE_DIR 2>/dev/null)" ]; then rm -rf $SITE_BAC_DIR mv $SITE_DIR $SITE_BAC_DIR else rm -rf $SITE_DIR fi mkdir -p $SITE_DIR cp -R "$TEMPLATE_DIR"/. $SITE_DIR rm -rf $SITE_DIR/.git # --- Шаг 2: создание докер-сети --- # N=$(awk '/^networks:/,/^[^[:space:]]/{if($1=="name:"){print $2; exit}}' "$COMPOSE_FILE"); N=${N:-proxy} # docker network inspect "$N" >/dev/null 2>&1 || docker network create --driver bridge --attachable "$N" # --- Шаг 3: запрос параметров --- read -rp "NODE_PORT: " NODE_PORT read -rp "SECRET_KEY: " SECRET_KEY read -rp "NODE_DOMAIN: " NODE_DOMAIN read -rp "CW_CLIENT_AES_KEY_BASE64: " CW_CLIENT_AES_KEY_BASE64 read -rp "CW_CLIENT_KEY_APIKEY: " CW_CLIENT_KEY_APIKEY read -rp "CW_CLIENT_CERT_APIKEY: " CW_CLIENT_CERT_APIKEY touch "$ENV_FILE" update_env_var() { local key="$1" local value="$2" sed -i "/^${key}=.*/d" "$ENV_FILE" printf '%s="%s"\n' "$key" "$value" >> "$ENV_FILE" } update_env_var NODE_PORT "$NODE_PORT" update_env_var SECRET_KEY "$SECRET_KEY" update_env_var CW_CLIENT_KEY_NAME "$NODE_DOMAIN" update_env_var CW_CLIENT_CERT_NAME "$NODE_DOMAIN" update_env_var CW_CLIENT_AES_KEY_BASE64 "$CW_CLIENT_AES_KEY_BASE64" update_env_var CW_CLIENT_KEY_APIKEY "$CW_CLIENT_KEY_APIKEY" update_env_var CW_CLIENT_CERT_APIKEY "$CW_CLIENT_CERT_APIKEY" sed \ -e "s|__NODE_DOMAIN__|$NODE_DOMAIN|g" \ "$NGINX_TEMPLATE" > "$NGINX_CONF" # --- Шаг 4: открытие порта только для центрального сервера --- read -rp "IP или домен центрального сервера: " CENTRAL_HOST CENTRAL_IP=$(getent ahosts "$CENTRAL_HOST" | awk '{print $1; exit}') if [ -n "$CENTRAL_IP" ]; then sudo ufw allow from "$CENTRAL_IP" to any port "$NODE_PORT" proto tcp comment "PANEL" && ufw reload fi # --- Шаг 5: запуск docker compose --- docker compose -f "$COMPOSE_FILE" up -d certwardenclient echo "Ждём появления сертификатов..." for i in {1..120}; do if [ -s "$CERT_FILE" ] && [ -s "$KEY_FILE" ]; then if openssl x509 -in "$CERT_FILE" -checkend 60 -noout >/dev/null 2>&1; then if openssl pkey -in "$KEY_FILE" -noout >/dev/null 2>&1; then echo "Сертификаты готовы!" break fi fi fi sleep 2 done if ! openssl x509 -in "$CERT_FILE" -checkend 60 -noout >/dev/null 2>&1; then echo "ОШИБКА: Сертификаты не получены" exit 1 fi docker compose -f "$COMPOSE_FILE" up -d # логи mkdir -p "$LOG_DIR" sudo mkdir -p $LOGROTATE_DIR TMP_LOGROTATE_CONF="$(mktemp)" cat > "$TMP_LOGROTATE_CONF" </dev/null < "$TMP_LOGROTATE_CONF" fi else echo "creating logrotate config: $LOGROTATE_CONF" sudo tee "$LOGROTATE_CONF" >/dev/null < "$TMP_LOGROTATE_CONF" fi trap 'rm -rf "$TMP_LOGROTATE_CONF"' EXIT sudo logrotate -vf /etc/logrotate.d/remnanode echo "Инициализация завершена успешно" rm -f -- "$SELF_PATH"