#!/bin/bash # deploy-vpn-route-check.sh — идемпотентный деплой vpn-route-check на CT 100 # Секреты берутся из Vaultwarden (объект localhost), .env генерируется на Proxmox и пушится в CT. # # Использование: # /root/scripts/deploy-vpn-route-check.sh # деплой # /root/scripts/deploy-vpn-route-check.sh --dry-run # только проверка, без записи и compose # # Требования: bw, jq, /root/.bw-master (chmod 600) set -e CT_ID=100 CT_PATH="/opt/docker/vpn-route-check" BW_MASTER_FILE="${BW_MASTER_PASSWORD_FILE:-/root/.bw-master}" DRY_RUN=false for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; esac done export PATH="/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH}" log() { echo "[$(date -Iseconds)] $*"; } err() { echo "[$(date -Iseconds)] ERROR: $*" >&2; } # --- 1. Разблокировка bw (reuse session если возможно) ensure_bw_unlocked() { local status status=$(bw status 2>/dev/null | jq -r '.status' 2>/dev/null || echo "unknown") if [ "$status" = "unlocked" ]; then log "bw already unlocked, reusing session" return 0 fi if [ ! -f "$BW_MASTER_FILE" ]; then err "Missing $BW_MASTER_FILE" exit 1 fi export BW_SESSION=$(bw unlock --passwordfile "$BW_MASTER_FILE" --raw 2>/dev/null) || { err "bw unlock failed" exit 1 } log "bw unlocked" } # --- 2. Получить секреты из Vaultwarden (localhost) get_secrets() { local host user pass host=$(bw get item "localhost" 2>/dev/null | jq -r '.fields[] | select(.name=="ROUTER_TELNET_HOST") | .value // empty') user=$(bw get username "localhost" 2>/dev/null) pass=$(bw get password "localhost" 2>/dev/null) if [ -z "$user" ] || [ -z "$pass" ]; then err "localhost: missing username or password in Vaultwarden" exit 1 fi host="${host:-192.168.1.1}" ROUTER_TELNET_HOST="$host" ROUTER_TELNET_USER="$user" ROUTER_TELNET_PASSWORD="$pass" } # --- 3. Сгенерировать .env во временный файл gen_env() { local tmp tmp=$(mktemp) cat > "$tmp" << EOF ROUTER_TELNET_HOST=${ROUTER_TELNET_HOST} ROUTER_TELNET_USER=${ROUTER_TELNET_USER} ROUTER_TELNET_PASSWORD=${ROUTER_TELNET_PASSWORD} EOF echo "$tmp" } # --- 4. Атомарно записать .env в CT 100 push_env_to_ct() { local tmp="$1" < "$tmp" pct exec "$CT_ID" -- bash -c "cat > ${CT_PATH}/.env.tmp && chmod 600 ${CT_PATH}/.env.tmp && mv ${CT_PATH}/.env.tmp ${CT_PATH}/.env" log ".env written to CT $CT_ID (atomic)" } # --- 5. docker compose up -d run_compose() { pct exec "$CT_ID" -- bash -c "cd ${CT_PATH} && docker compose up -d --force-recreate" log "vpn-route-check started" } # --- main main() { log "deploy-vpn-route-check start (dry_run=$DRY_RUN)" ensure_bw_unlocked get_secrets if [ "$DRY_RUN" = true ]; then log "DRY-RUN: would push .env and run compose" log " ROUTER_TELNET_HOST=$ROUTER_TELNET_HOST" log " ROUTER_TELNET_USER=$ROUTER_TELNET_USER" log " ROUTER_TELNET_PASSWORD=***" exit 0 fi tmp=$(gen_env) trap "rm -f $tmp" EXIT push_env_to_ct "$tmp" run_compose log "done" } main