#!/usr/bin/env bash # ════════════════════════════════════════════════════════════════ # install-uploader.sh # Установка log-uploader'а на ОДНУ VPN-ноду. # # Использование: # Вариант 1 (с аргументами): # curl -fsSL https://logs.killu.net/install-uploader.sh | bash -s -- \ # --bucket=YOUR_BUCKET \ # --endpoint=https://s3.twcstorage.ru \ # --access=YOUR_KEY \ # --secret=YOUR_SECRET \ # --node-name=de-1 # # Вариант 2 (с config.env): # wget https://logs.killu.net/config.env.example -O config.env # nano config.env # curl -fsSL https://logs.killu.net/install-uploader.sh | bash -s -- --config=./config.env # # Требования: Debian/Ubuntu, root, доступ к интернету. # ════════════════════════════════════════════════════════════════ set -euo pipefail export DEBIAN_FRONTEND=noninteractive C_GR="\033[32m"; C_YE="\033[33m"; C_BL="\033[34m"; C_OF="\033[0m" say() { echo -e "${C_BL}▸${C_OF} $*"; } ok() { echo -e "${C_GR}✓${C_OF} $*"; } warn() { echo -e "${C_YE}⚠${C_OF} $*"; } [ "$(id -u)" -eq 0 ] || { echo "Запусти под root"; exit 1; } # ── парсинг аргументов ─────────────────────────────────────── CONFIG_FILE="" BUCKET=""; ENDPOINT=""; ACCESS=""; SECRET=""; NODE_NAME="" UPLOAD_TIME="${NODE_UPLOAD_TIME:-01:00}" for arg in "$@"; do case "$arg" in --config=*) CONFIG_FILE="${arg#*=}" ;; --bucket=*) BUCKET="${arg#*=}" ;; --endpoint=*) ENDPOINT="${arg#*=}" ;; --access=*) ACCESS="${arg#*=}" ;; --secret=*) SECRET="${arg#*=}" ;; --node-name=*) NODE_NAME="${arg#*=}" ;; --time=*) UPLOAD_TIME="${arg#*=}" ;; esac done # подгрузить config.env если указан if [ -n "$CONFIG_FILE" ] && [ -f "$CONFIG_FILE" ]; then say "Читаю $CONFIG_FILE" # shellcheck disable=SC1090 . "$CONFIG_FILE" BUCKET="${BUCKET:-$S3_BUCKET}" ENDPOINT="${ENDPOINT:-$S3_ENDPOINT}" ACCESS="${ACCESS:-$AWS_ACCESS_KEY_ID}" SECRET="${SECRET:-$AWS_SECRET_ACCESS_KEY}" NODE_NAME="${NODE_NAME:-$LOG_NODE_NAME}" UPLOAD_TIME="${UPLOAD_TIME:-${NODE_UPLOAD_TIME:-01:00}}" fi # проверка for var in BUCKET ENDPOINT ACCESS SECRET NODE_NAME; do if [ -z "${!var}" ]; then echo "ERROR: --${var,,} не задан. Использование:" echo " install-uploader.sh --bucket=X --endpoint=Y --access=K --secret=S --node-name=N" exit 1 fi done say "═══ установка log-uploader'а на $(hostname) ═══" echo " node-name: $NODE_NAME" echo " bucket: $BUCKET" echo " endpoint: $ENDPOINT" echo " schedule: ежедневно в $UPLOAD_TIME UTC" echo "" # ── 1. зависимости ─────────────────────────────────────────── say "1/4 · зависимости (zstd, gzip, curl, mc)" # wait apt-lock (unattended-upgrades на свежих VPS) n=0 while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do [ $n -eq 0 ] && warn "Жду apt-lock..." sleep 5; n=$((n+1)); [ $n -ge 60 ] && { echo "apt-lock держится >5 мин"; exit 1; } done apt-get update -qq apt-get -y -qq install zstd gzip curl ca-certificates jq logrotate psmisc if [ ! -x /usr/local/bin/mc ]; then curl -fLs https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc chmod +x /usr/local/bin/mc fi ok "пакеты + mc" # проверка connectivity до S3 /usr/local/bin/mc alias set _test "$ENDPOINT" "$ACCESS" "$SECRET" --api S3v4 >/dev/null 2>&1 if ! /usr/local/bin/mc ls "_test/$BUCKET/" >/dev/null 2>&1; then echo "ERROR: S3 не доступен с этой ноды. Проверь endpoint/bucket/keys." /usr/local/bin/mc alias rm _test >/dev/null 2>&1 exit 1 fi /usr/local/bin/mc alias rm _test >/dev/null 2>&1 ok "S3 доступен" # ── 2. секреты ────────────────────────────────────────────── say "2/4 · /etc/log-upload/secrets.env" mkdir -p /etc/log-upload cat >/etc/log-upload/secrets.env </etc/systemd/system/log-upload.service <<'EOF' [Unit] Description=Upload yesterday VPN logs to S3 After=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/usr/local/sbin/log-upload.sh StandardOutput=journal StandardError=journal Nice=10 IOSchedulingClass=idle EOF cat >/etc/systemd/system/log-upload.timer </dev/null | awk 'NR==2{print $1, $2, $3, $4}')"