diff --git a/migration.sh b/migration.sh index 28d68e3..34bcdf4 100755 --- a/migration.sh +++ b/migration.sh @@ -21,22 +21,22 @@ if [ -f "$OPERATOR_DIR/lib/ui.sh" ]; then source "$OPERATOR_DIR/lib/ui.sh" source "$OPERATOR_DIR/lib/log.sh" source "$OPERATOR_DIR/lib/steps.sh" - -fail() { log_error "$1"; exit 1; } else RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; RESET='\033[0m' ok() { echo -e "${GREEN}[OK]${RESET} $1"; [ -f "$LOG" ] && echo "[OK] $1" >> "$LOG"; } info() { echo -e "${CYAN}[i]${RESET} $1"; [ -f "$LOG" ] && echo "[i] $1" >> "$LOG"; } warn() { echo -e "${YELLOW}[!]${RESET} $1"; [ -f "$LOG" ] && echo "[!] $1" >> "$LOG"; } - fail() { echo -e "${RED}[X]${RESET} $1"; [ -f "$LOG" ] && echo "[X] $1" >> "$LOG"; exit 1; } - print_header() { echo ""; echo " $1 $2"; echo ""; } + print_header() { echo ""; echo " $1 $2"; echo ""; } print_section() { echo -e "\n${CYAN}─── $1 ───${RESET}"; } log_ok() { ok "$1"; } log_info() { info "$1"; } log_warn() { warn "$1"; } - log_error() { fail "$1"; } + log_error() { echo -e "${RED}[X]${RESET} $1"; [ -f "$LOG" ] && echo "[X] $1" >> "$LOG"; } fi +# fail() always defined after if/else/fi — never inside a block +fail() { log_error "$1"; exit 1; } + mkdir -p "$BACKUP_DIR" : > "$LOG" 2>/dev/null || true @@ -47,10 +47,18 @@ info "Requesting sudo credentials (used throughout migration)..." sudo -v || fail "sudo required. Check your permissions." ok "Sudo credentials cached." -# ─── STEP 1: SSH + Clone ────────────────────────────────────────────────────── -print_section "Step 1/$TOTAL_STEPS — Verify SSH & Clone operator-docker" +# ─── STEP 1: Backup (go-legacy stays running) ──────────────────────────────── +print_section "Step 1/$TOTAL_STEPS — Backup WireGuard identity & peers" -[ -f "$HOME/.ssh/id_ed25519" ] || fail "SSH key not found. Generate one or run 00-backup.sh first." +[ -f "$BACKUP_DIR/private_key" ] && ok "Backup already exists — skipping step 1." || { + info "Running backup (sudo required)..." + sudo bash "$SCRIPT_DIR/steps/00-backup.sh" || fail "Backup failed." +} + +# ─── STEP 2: SSH + Clone operator-docker ───────────────────────────────────── +print_section "Step 2/$TOTAL_STEPS — Verify SSH & Clone operator-docker" + +[ -f "$HOME/.ssh/id_ed25519" ] || fail "SSH key not found. Run step 1 first (00-backup.sh generates it)." SSH_TEST=$(GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10' \ ssh -T git@git.simplifiedprivacy.com 2>&1 || true) @@ -74,24 +82,16 @@ else ok "Cloned to $OPERATOR_DIR" fi -# Borrow UI from freshly cloned repo +# Re-source UI from freshly cloned repo (better version) if [ -f "$OPERATOR_DIR/lib/ui.sh" ]; then source "$OPERATOR_DIR/lib/ui.sh" source "$OPERATOR_DIR/lib/log.sh" source "$OPERATOR_DIR/lib/steps.sh" - fi +# Re-define fail() after re-source so it always exists fail() { log_error "$1"; exit 1; } -# ─── STEP 2: Backup & cleanup (needs root) ──────────────────────────────────── -print_section "Step 2/$TOTAL_STEPS — Backup & cleanup" - -[ -f "$BACKUP_DIR/private_key" ] && ok "Backup already exists — skipping step 2." || { - info "Running backup (sudo required)..." - sudo OPERATOR_DIR="$OPERATOR_DIR" bash "$SCRIPT_DIR/steps/00-backup.sh" || fail "Backup failed." -} - -# ─── STEP 3: Install operator-docker ───────────────────────────────────────── +# ─── STEP 3: Install operator-docker (preflight runs inside as step 3) ─────── print_section "Step 3/$TOTAL_STEPS — Install operator-docker" [ -f "$OPERATOR_DIR/.env" ] && ok ".env exists — skipping install." || { @@ -104,7 +104,7 @@ print_section "Step 3/$TOTAL_STEPS — Install operator-docker" ok "operator-docker installed." } -# ─── STEP 4: Migrate peers & identity ──────────────────────────────────────── +# ─── STEP 4: Migrate peers & identity (shuts down go-legacy here) ──────────── print_section "Step 4/$TOTAL_STEPS — Migrate WireGuard identity & peers" bash "$SCRIPT_DIR/steps/02-peers.sh" || fail "Peer migration failed." diff --git a/steps/00-backup.sh b/steps/00-backup.sh index 253bd90..58644a7 100644 --- a/steps/00-backup.sh +++ b/steps/00-backup.sh @@ -1,12 +1,12 @@ #!/bin/bash -eu # ============================================================================= -# 00-migrate-root.sh — Run as ROOT +# 00-backup.sh — Run as ROOT via: sudo bash steps/00-backup.sh # 1. Full backup (keys, peers, nginx, certs, ufw, env) -# 2. Shuts down legacy stack -# 3. Cleans system for fresh install +# NOTE: does NOT shut down legacy stack — that happens in 02-peers.sh +# only after the new WireGuard is verified and running. # ============================================================================= if [ "$EUID" -ne 0 ]; then - echo "[X] Run as root: sudo bash 00-migrate-root.sh" + echo "[X] Run as root: sudo bash steps/00-backup.sh" exit 1 fi @@ -46,7 +46,7 @@ _save() { echo "" echo "=========================================" -echo " 00 - Backup, cleanup and preparation" +echo " 00 - Backup and preparation" echo " $(date '+%Y-%m-%d %H:%M:%S')" echo " User : $LINUX_USER" echo " Backup : $BACKUP_DIR" @@ -77,7 +77,6 @@ sep info "Detecting legacy stack location..." LEGACY_COMPOSE_DIR="" -# Search in known paths first for DIR in "$LINUX_HOME/sp-env-wireguard" \ "$LINUX_HOME/sp-env-wireguard-ipv6" \ "$LINUX_HOME/wireguard" \ @@ -91,9 +90,8 @@ for DIR in "$LINUX_HOME/sp-env-wireguard" \ fi done -# Fallback: search entire home directory if [ -z "$LEGACY_COMPOSE_DIR" ]; then - LEGACY_COMPOSE_DIR=$(find "$LINUX_HOME" -maxdepth 6 -name "docker-compose.yml" 2>/dev/null | \ + LEGACY_COMPOSE_DIR=$(find "$LINUX_HOME" /root -maxdepth 6 -name "docker-compose.yml" 2>/dev/null | \ while read -r f; do grep -q "wireguard" "$f" 2>/dev/null && dirname "$f" && break done | head -1) @@ -140,7 +138,6 @@ ok "$PEER_COUNT peers saved." # ─── BACKUP NGINX ───────────────────────────────────────────────────────────── sep info "Backing up Nginx..." -mkdir -p "$BACKUP_DIR/nginx" mkdir -p "$BACKUP_DIR/nginx/sites-available" "$BACKUP_DIR/nginx/sites-enabled" cp -r /etc/nginx/sites-available/. "$BACKUP_DIR/nginx/sites-available/" 2>/dev/null || true cp -r /etc/nginx/sites-enabled/. "$BACKUP_DIR/nginx/sites-enabled/" 2>/dev/null || true @@ -173,6 +170,7 @@ info "Backing up legacy .env..." _save "$LEGACY_COMPOSE_DIR/.env" legacy.env # ─── DETECT NETWORK ─────────────────────────────────────────────────────────── +sep IPV6_ADDRS=$(ip -6 addr show | grep -oP 'inet6 \K[0-9a-fA-F:]+' | grep -v '^::1$' || true) if [ -n "$IPV6_ADDRS" ]; then echo "ipv6=true" > "$BACKUP_DIR/network_info" @@ -203,47 +201,16 @@ SSH_PUBKEY=$(cat "$LINUX_HOME/.ssh/id_ed25519.pub") echo "$SSH_PUBKEY" > "$BACKUP_DIR/ssh_pubkey" chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/ssh_pubkey" -# ─── SHUT DOWN LEGACY STACK ─────────────────────────────────────────────────── -sep -warn "Shutting down legacy stack..." -cd "$LEGACY_COMPOSE_DIR" -docker compose down --remove-orphans 2>/dev/null || true - -for CNAME in $(docker ps -a --format '{{.Names}} {{.Image}}' | \ - grep -iE "linuxserver/wireguard|lscr.io/linuxserver/wireguard|wireguard-api|sp-wireguard-api" | \ - awk '{print $1}' || true); do - docker stop "$CNAME" 2>/dev/null || true - docker rm "$CNAME" 2>/dev/null || true - warn "Removed: $CNAME" -done -ok "Legacy stack stopped." - -# ─── CLEAN NGINX ────────────────────────────────────────────────────────────── -sep -info "Cleaning Nginx for fresh install..." -for SITE in /etc/nginx/sites-enabled/*; do - rm -f "$SITE" && warn "Removed from sites-enabled: $(basename $SITE)" -done -for SITE in /etc/nginx/sites-available/*; do - NAME=$(basename "$SITE") - [ "$NAME" = "default" ] && continue - rm -f "$SITE" && warn "Removed from sites-available: $NAME" -done -rm -f /etc/nginx/sites-enabled/certbot-temp /etc/nginx/sites-available/certbot-temp 2>/dev/null || true -systemctl stop nginx 2>/dev/null || true -ok "Nginx cleaned." - -# ─── VERIFY PORT 51820 FREE ─────────────────────────────────────────────────── -sep -info "Checking port 51820/UDP..." -sleep 3 -ss -ulnp 2>/dev/null | grep -q ":51820" && fail "Port 51820 still in use." || ok "Port 51820/UDP free." +# ─── NOTE: legacy stack NOT shut down here ──────────────────────────────────── +# go-legacy continues running until 02-peers.sh confirms the new +# WireGuard is up and identity is preserved. This avoids any VPN downtime +# during the install phase. echo "[END-00] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG" echo "" echo "=========================================" -echo " Backup complete — System ready" +echo " Backup complete — legacy still running" echo "=========================================" echo "" echo " Backup dir : $BACKUP_DIR" @@ -254,8 +221,9 @@ echo "" echo " SSH key for Simplified Privacy:" echo " $SSH_PUBKEY" echo "" -echo " Once SP authorizes access, run:" -echo " bash 01-migrate-user.sh" +echo " go-legacy is still running." +echo " It will be stopped by 02-peers.sh" +echo " only after the new WireGuard is verified." echo "" echo " Log: cat $LOG" echo "========================================="