feat: add migration CLI with backup, install and peer migration steps
This commit is contained in:
parent
cecd50d62b
commit
0a929223e6
4 changed files with 756 additions and 0 deletions
111
migration.sh
Executable file
111
migration.sh
Executable file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#!/bin/bash -eu
|
||||||
|
# =============================================================================
|
||||||
|
# migration.sh — WireGuard Go → FastAPI migration
|
||||||
|
# Run as Linux user (not root). Asks for sudo once.
|
||||||
|
# =============================================================================
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "[X] Run as your Linux user, not root: bash migration.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
OPERATOR_DIR="$HOME/operator-docker"
|
||||||
|
BACKUP_DIR="$HOME/.wg-migration"
|
||||||
|
LOG="$BACKUP_DIR/migration.log"
|
||||||
|
REPO_URL="git@git.simplifiedprivacy.com:zenaku/operator-docker.git"
|
||||||
|
TOTAL_STEPS=4
|
||||||
|
|
||||||
|
# ─── Borrow UI from operator-docker if available, else minimal fallback ───────
|
||||||
|
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"
|
||||||
|
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_section() { echo -e "\n${CYAN}─── $1 ───${RESET}"; }
|
||||||
|
log_ok() { ok "$1"; }
|
||||||
|
log_info() { info "$1"; }
|
||||||
|
log_warn() { warn "$1"; }
|
||||||
|
log_error() { fail "$1"; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
: > "$LOG" 2>/dev/null || true
|
||||||
|
|
||||||
|
print_header "WireGuard Migration" "v1.0"
|
||||||
|
|
||||||
|
# ─── SUDO once ────────────────────────────────────────────────────────────────
|
||||||
|
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"
|
||||||
|
|
||||||
|
[ -f "$HOME/.ssh/id_ed25519" ] || fail "SSH key not found. Generate one or run 00-backup.sh first."
|
||||||
|
|
||||||
|
SSH_TEST=$(GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10' \
|
||||||
|
ssh -T git@git.simplifiedprivacy.com 2>&1 || true)
|
||||||
|
|
||||||
|
if echo "$SSH_TEST" | grep -qiE "Welcome|successfully authenticated"; then
|
||||||
|
ok "SSH access authorized."
|
||||||
|
else
|
||||||
|
warn "SSH not authorized. Share this key with Simplified Privacy:"
|
||||||
|
echo ""
|
||||||
|
cat "$HOME/.ssh/id_ed25519.pub"
|
||||||
|
echo ""
|
||||||
|
fail "Once authorized, run again: bash migration.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$OPERATOR_DIR" ]; then
|
||||||
|
warn "operator-docker already exists — skipping clone."
|
||||||
|
else
|
||||||
|
info "Cloning operator-docker..."
|
||||||
|
GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no' \
|
||||||
|
git clone "$REPO_URL" "$OPERATOR_DIR" || fail "Could not clone repository."
|
||||||
|
ok "Cloned to $OPERATOR_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Borrow UI from freshly cloned repo
|
||||||
|
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
|
||||||
|
|
||||||
|
# ─── 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 ─────────────────────────────────────────
|
||||||
|
print_section "Step 3/$TOTAL_STEPS — Install operator-docker"
|
||||||
|
|
||||||
|
[ -f "$OPERATOR_DIR/.env" ] && ok ".env exists — skipping install." || {
|
||||||
|
info "Running installer..."
|
||||||
|
cd "$OPERATOR_DIR"
|
||||||
|
sudo systemctl start nginx 2>/dev/null || true
|
||||||
|
echo "$HOME" > /tmp/.migration_home
|
||||||
|
sudo MIGRATION_MODE=1 bash install.sh || { rm -f /tmp/.migration_home; fail "Installer failed."; }
|
||||||
|
rm -f /tmp/.migration_home
|
||||||
|
ok "operator-docker installed."
|
||||||
|
}
|
||||||
|
|
||||||
|
# ─── STEP 4: Migrate peers & identity ────────────────────────────────────────
|
||||||
|
print_section "Step 4/$TOTAL_STEPS — Migrate WireGuard identity & peers"
|
||||||
|
|
||||||
|
bash "$SCRIPT_DIR/steps/02-peers.sh" || fail "Peer migration failed."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " Migration complete"
|
||||||
|
echo " Log: cat $LOG"
|
||||||
|
echo "========================================="
|
||||||
107
rollback.sh
Executable file
107
rollback.sh
Executable file
|
|
@ -0,0 +1,107 @@
|
||||||
|
#!/bin/bash -eu
|
||||||
|
# =============================================================================
|
||||||
|
# rollback.sh — Revert to Go legacy WireGuard
|
||||||
|
# Run as Linux user (not root).
|
||||||
|
# =============================================================================
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "[X] Run as your Linux user, not root: bash rollback.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BACKUP_DIR="$HOME/.wg-migration"
|
||||||
|
OPERATOR_DIR="$HOME/operator-docker"
|
||||||
|
LOG="$BACKUP_DIR/migration.log"
|
||||||
|
|
||||||
|
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"; echo "[OK-ROLLBACK] $1" >> "$LOG" 2>/dev/null || true; }
|
||||||
|
warn() { echo -e "${YELLOW}[!]${RESET} $1"; echo "[!-ROLLBACK] $1" >> "$LOG" 2>/dev/null || true; }
|
||||||
|
fail() { echo -e "${RED}[X]${RESET} $1"; echo "[X-ROLLBACK] $1" >> "$LOG" 2>/dev/null || true; exit 1; }
|
||||||
|
sep() { echo -e "\n${CYAN}────────────────────────────────────${RESET}"; }
|
||||||
|
|
||||||
|
[ -f "$BACKUP_DIR/legacy_compose_dir" ] || fail "No backup found at $BACKUP_DIR. Cannot rollback."
|
||||||
|
|
||||||
|
LEGACY_COMPOSE_DIR=$(cat "$BACKUP_DIR/legacy_compose_dir")
|
||||||
|
[ -d "$LEGACY_COMPOSE_DIR" ] || fail "Legacy directory not found: $LEGACY_COMPOSE_DIR"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " Rollback — Restoring Go legacy"
|
||||||
|
echo " $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
echo "========================================="
|
||||||
|
|
||||||
|
sudo -v || fail "sudo required."
|
||||||
|
|
||||||
|
# ─── Stop FastAPI stack ───────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
warn "Stopping operator-docker..."
|
||||||
|
if [ -f "$OPERATOR_DIR/docker-compose.yml" ]; then
|
||||||
|
cd "$OPERATOR_DIR"
|
||||||
|
docker compose down -v --rmi all --remove-orphans &>/dev/null || true
|
||||||
|
ok "operator-docker stopped."
|
||||||
|
else
|
||||||
|
warn "operator-docker not found — skipping."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Remove certbot certs for FastAPI subdomains ──────────────────────────────
|
||||||
|
sep
|
||||||
|
warn "Removing FastAPI SSL certificates..."
|
||||||
|
if [ -f "$OPERATOR_DIR/.env" ]; then
|
||||||
|
set -a; source "$OPERATOR_DIR/.env"; set +a
|
||||||
|
for subdomain in "${API_SUBDOMAIN:-}" "${MARZBAN_SUBDOMAIN:-}" "${VPN_SUBDOMAIN:-}" "${HYSTERIA_SUBDOMAIN:-}"; do
|
||||||
|
[ -z "$subdomain" ] && continue
|
||||||
|
CERT="${subdomain}.${BASE_DOMAIN}"
|
||||||
|
sudo certbot delete --cert-name "$CERT" --non-interactive &>/dev/null && ok "Deleted: $CERT" || warn "Not found: $CERT"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
warn ".env not found — skipping cert deletion"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Clean nginx ──────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
warn "Cleaning nginx..."
|
||||||
|
sudo rm -f /etc/nginx/sites-enabled/operator /etc/nginx/sites-available/operator /etc/nginx/mtls-ca.cert.pem
|
||||||
|
|
||||||
|
# Restore backed-up nginx configs
|
||||||
|
if [ -d "$BACKUP_DIR/nginx/sites-available" ]; then
|
||||||
|
sudo cp -r "$BACKUP_DIR/nginx/sites-available/." /etc/nginx/sites-available/ 2>/dev/null || true
|
||||||
|
sudo cp -r "$BACKUP_DIR/nginx/sites-enabled/." /etc/nginx/sites-enabled/ 2>/dev/null || true
|
||||||
|
ok "Nginx configs restored from backup."
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo nginx -t && sudo systemctl reload nginx 2>/dev/null && ok "Nginx reloaded." || warn "Nginx reload failed."
|
||||||
|
|
||||||
|
# ─── Restore SSL certs ────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
warn "Restoring legacy SSL certificates..."
|
||||||
|
if [ -d "$BACKUP_DIR/letsencrypt" ]; then
|
||||||
|
sudo cp -r "$BACKUP_DIR/letsencrypt/." /etc/letsencrypt/ 2>/dev/null || true
|
||||||
|
ok "Certificates restored."
|
||||||
|
else
|
||||||
|
warn "No certificate backup found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── Remove operator-docker directory ─────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
warn "Removing operator-docker directory..."
|
||||||
|
sudo rm -rf "$OPERATOR_DIR"
|
||||||
|
ok "operator-docker removed."
|
||||||
|
|
||||||
|
# ─── Start Go legacy ──────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info() { echo -e "${CYAN}[i]${RESET} $1"; }
|
||||||
|
info "Starting Go legacy stack..."
|
||||||
|
sudo modprobe ip6table_filter 2>/dev/null || true
|
||||||
|
cd "$LEGACY_COMPOSE_DIR"
|
||||||
|
docker compose up -d 2>/dev/null || true
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
LEGACY_UP=$(docker ps --format '{{.Names}}' | grep -i wireguard | head -1 || true)
|
||||||
|
[ -n "$LEGACY_UP" ] && ok "Legacy WireGuard running: $LEGACY_UP" || \
|
||||||
|
warn "Legacy may not have started. Check: docker ps"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " Rollback complete"
|
||||||
|
echo " Legacy stack: $LEGACY_COMPOSE_DIR"
|
||||||
|
echo " Log: cat $LOG"
|
||||||
|
echo "========================================="
|
||||||
261
steps/00-backup.sh
Normal file
261
steps/00-backup.sh
Normal file
|
|
@ -0,0 +1,261 @@
|
||||||
|
#!/bin/bash -eu
|
||||||
|
# =============================================================================
|
||||||
|
# 00-migrate-root.sh — Run as ROOT
|
||||||
|
# 1. Full backup (keys, peers, nginx, certs, ufw, env)
|
||||||
|
# 2. Shuts down legacy stack
|
||||||
|
# 3. Cleans system for fresh install
|
||||||
|
# =============================================================================
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "[X] Run as root: sudo bash 00-migrate-root.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; RESET='\033[0m'
|
||||||
|
|
||||||
|
LINUX_USER="${SUDO_USER:-}"
|
||||||
|
if [ -z "$LINUX_USER" ] || [ "$LINUX_USER" = "root" ]; then
|
||||||
|
LINUX_USER=$(getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' | head -1 || true)
|
||||||
|
fi
|
||||||
|
[ -z "$LINUX_USER" ] && { echo -e "${RED}[X]${RESET} Could not detect Linux user."; exit 1; }
|
||||||
|
LINUX_HOME=$(getent passwd "$LINUX_USER" | cut -d: -f6)
|
||||||
|
|
||||||
|
BACKUP_DIR="$LINUX_HOME/.wg-migration"
|
||||||
|
LOG="$BACKUP_DIR/migration.log"
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
chmod 700 "$BACKUP_DIR"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR"
|
||||||
|
: > "$LOG"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$LOG"
|
||||||
|
|
||||||
|
ok() { echo -e "${GREEN}[OK]${RESET} $1"; echo "[OK] $1" >> "$LOG"; }
|
||||||
|
info() { echo -e "${CYAN}[i]${RESET} $1"; echo "[i] $1" >> "$LOG"; }
|
||||||
|
warn() { echo -e "${YELLOW}[!]${RESET} $1"; echo "[!] $1" >> "$LOG"; }
|
||||||
|
fail() { echo -e "${RED}[X]${RESET} $1"; echo "[X] $1" >> "$LOG"; exit 1; }
|
||||||
|
sep() { echo -e "\n${CYAN}------------------------------------${RESET}"; }
|
||||||
|
|
||||||
|
_save() {
|
||||||
|
if [ -e "$1" ]; then
|
||||||
|
cp -r "$1" "$BACKUP_DIR/$2" 2>/dev/null || true
|
||||||
|
chown -R "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/$2" 2>/dev/null || true
|
||||||
|
ok "Saved: $1 → $2"
|
||||||
|
else
|
||||||
|
warn "Not found (skipped): $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " 00 - Backup, cleanup and preparation"
|
||||||
|
echo " $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
echo " User : $LINUX_USER"
|
||||||
|
echo " Backup : $BACKUP_DIR"
|
||||||
|
echo "========================================="
|
||||||
|
echo "[START-00] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
# ─── DOCKER ───────────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Checking Docker..."
|
||||||
|
command -v docker &>/dev/null || fail "Docker not installed."
|
||||||
|
ok "Docker: $(docker --version)"
|
||||||
|
|
||||||
|
# ─── DETECT LEGACY WIREGUARD ──────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Detecting legacy WireGuard container..."
|
||||||
|
LEGACY_WG=$(docker ps --format '{{.Names}} {{.Image}}' | \
|
||||||
|
grep -i "linuxserver/wireguard\|lscr.io/linuxserver/wireguard" | \
|
||||||
|
awk '{print $1}' | head -1 || true)
|
||||||
|
if [ -z "$LEGACY_WG" ]; then
|
||||||
|
LEGACY_WG=$(docker ps --format '{{.Names}}' | \
|
||||||
|
grep -iE "^wireguard$|^wg$|^sp-wireguard$" | head -1 || true)
|
||||||
|
fi
|
||||||
|
[ -z "$LEGACY_WG" ] && fail "No legacy WireGuard container found. Check: docker ps"
|
||||||
|
ok "Legacy WireGuard: $LEGACY_WG"
|
||||||
|
|
||||||
|
# ─── DETECT LEGACY STACK ──────────────────────────────────────────────────────
|
||||||
|
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" \
|
||||||
|
/root/sp-env-wireguard \
|
||||||
|
/root/sp-env-wireguard-ipv6 \
|
||||||
|
/opt/sp-env-wireguard \
|
||||||
|
/srv/wireguard; do
|
||||||
|
if [ -f "$DIR/docker-compose.yml" ] && grep -q "wireguard" "$DIR/docker-compose.yml" 2>/dev/null; then
|
||||||
|
LEGACY_COMPOSE_DIR="$DIR"
|
||||||
|
break
|
||||||
|
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 | \
|
||||||
|
while read -r f; do
|
||||||
|
grep -q "wireguard" "$f" 2>/dev/null && dirname "$f" && break
|
||||||
|
done | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$LEGACY_COMPOSE_DIR" ] && fail "Legacy docker-compose.yml not found."
|
||||||
|
ok "Legacy stack: $LEGACY_COMPOSE_DIR"
|
||||||
|
echo "$LEGACY_COMPOSE_DIR" > "$BACKUP_DIR/legacy_compose_dir"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/legacy_compose_dir"
|
||||||
|
|
||||||
|
# ─── BACKUP WIREGUARD KEYS AND PEERS ──────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Backing up WireGuard keys and peers..."
|
||||||
|
|
||||||
|
WG_CONF_CONTENT=$(docker exec "$LEGACY_WG" cat /config/wg_confs/wg0.conf 2>/dev/null || true)
|
||||||
|
[ -z "$WG_CONF_CONTENT" ] && fail "Could not read wg0.conf from container $LEGACY_WG"
|
||||||
|
|
||||||
|
LEGACY_PRIVATE_KEY=$(echo "$WG_CONF_CONTENT" | grep "^PrivateKey" | awk '{print $3}' | tr -d '[:space:]')
|
||||||
|
[ -z "$LEGACY_PRIVATE_KEY" ] && fail "PrivateKey not found in wg0.conf"
|
||||||
|
echo "$LEGACY_PRIVATE_KEY" > "$BACKUP_DIR/private_key"
|
||||||
|
chmod 600 "$BACKUP_DIR/private_key"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/private_key"
|
||||||
|
ok "Private key saved."
|
||||||
|
|
||||||
|
LEGACY_PUBLIC_KEY=$(docker exec "$LEGACY_WG" cat /config/server/publickey-server 2>/dev/null | tr -d '[:space:]' || true)
|
||||||
|
if [ -z "$LEGACY_PUBLIC_KEY" ]; then
|
||||||
|
warn "publickey-server not found — deriving from private key..."
|
||||||
|
LEGACY_PUBLIC_KEY=$(echo "$LEGACY_PRIVATE_KEY" | wg pubkey 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
[ -z "$LEGACY_PUBLIC_KEY" ] && fail "Could not obtain public key."
|
||||||
|
echo "$LEGACY_PUBLIC_KEY" > "$BACKUP_DIR/public_key"
|
||||||
|
chmod 600 "$BACKUP_DIR/public_key"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/public_key"
|
||||||
|
ok "Public key: $LEGACY_PUBLIC_KEY"
|
||||||
|
|
||||||
|
PEER_CONF=$(docker exec "$LEGACY_WG" wg showconf wg0 2>/dev/null || echo "$WG_CONF_CONTENT")
|
||||||
|
echo "$PEER_CONF" > "$BACKUP_DIR/wg0-legacy.conf"
|
||||||
|
cp "$BACKUP_DIR/wg0-legacy.conf" "$BACKUP_DIR/wg0-legacy.conf.original"
|
||||||
|
chmod 600 "$BACKUP_DIR/wg0-legacy.conf" "$BACKUP_DIR/wg0-legacy.conf.original"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/wg0-legacy.conf" "$BACKUP_DIR/wg0-legacy.conf.original"
|
||||||
|
PEER_COUNT=$(grep -c "^\[Peer\]" "$BACKUP_DIR/wg0-legacy.conf" || echo 0)
|
||||||
|
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
|
||||||
|
_save /etc/nginx/nginx.conf nginx/nginx.conf
|
||||||
|
chown -R "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/nginx/"
|
||||||
|
ok "Nginx configs backed up."
|
||||||
|
|
||||||
|
# ─── BACKUP SSL CERTIFICATES ──────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Backing up SSL certificates..."
|
||||||
|
mkdir -p "$BACKUP_DIR/letsencrypt"
|
||||||
|
if [ -d /etc/letsencrypt ]; then
|
||||||
|
cp -r /etc/letsencrypt/. "$BACKUP_DIR/letsencrypt/"
|
||||||
|
chown -R "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/letsencrypt/"
|
||||||
|
ok "Certificates saved."
|
||||||
|
else
|
||||||
|
warn "/etc/letsencrypt not found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─── BACKUP UFW ───────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Backing up UFW rules..."
|
||||||
|
ufw status verbose > "$BACKUP_DIR/ufw-snapshot.txt" 2>/dev/null || true
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/ufw-snapshot.txt"
|
||||||
|
ok "UFW snapshot saved."
|
||||||
|
|
||||||
|
# ─── BACKUP LEGACY ENV ────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Backing up legacy .env..."
|
||||||
|
_save "$LEGACY_COMPOSE_DIR/.env" legacy.env
|
||||||
|
|
||||||
|
# ─── DETECT NETWORK ───────────────────────────────────────────────────────────
|
||||||
|
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"
|
||||||
|
ok "IPv6 detected."
|
||||||
|
else
|
||||||
|
echo "ipv6=false" > "$BACKUP_DIR/network_info"
|
||||||
|
info "IPv4 only."
|
||||||
|
fi
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$BACKUP_DIR/network_info"
|
||||||
|
|
||||||
|
# ─── SSH KEY ──────────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Adding $LINUX_USER to docker group..."
|
||||||
|
usermod -aG docker "$LINUX_USER" 2>/dev/null || true
|
||||||
|
ok "$LINUX_USER added to docker group. Changes take effect on next login."
|
||||||
|
|
||||||
|
info "Checking SSH key for private repo..."
|
||||||
|
mkdir -p "$LINUX_HOME/.ssh"
|
||||||
|
chmod 700 "$LINUX_HOME/.ssh"
|
||||||
|
chown "$LINUX_USER":"$LINUX_USER" "$LINUX_HOME/.ssh"
|
||||||
|
if [ ! -f "$LINUX_HOME/.ssh/id_ed25519" ]; then
|
||||||
|
sudo -u "$LINUX_USER" ssh-keygen -t ed25519 -f "$LINUX_HOME/.ssh/id_ed25519" -N "" -q
|
||||||
|
ok "SSH key generated."
|
||||||
|
else
|
||||||
|
ok "SSH key already exists."
|
||||||
|
fi
|
||||||
|
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."
|
||||||
|
|
||||||
|
echo "[END-00] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " Backup complete — System ready"
|
||||||
|
echo "========================================="
|
||||||
|
echo ""
|
||||||
|
echo " Backup dir : $BACKUP_DIR"
|
||||||
|
echo " Legacy stack : $LEGACY_COMPOSE_DIR"
|
||||||
|
echo " Public key : $LEGACY_PUBLIC_KEY"
|
||||||
|
echo " Peers saved : $PEER_COUNT"
|
||||||
|
echo ""
|
||||||
|
echo " SSH key for Simplified Privacy:"
|
||||||
|
echo " $SSH_PUBKEY"
|
||||||
|
echo ""
|
||||||
|
echo " Once SP authorizes access, run:"
|
||||||
|
echo " bash 01-migrate-user.sh"
|
||||||
|
echo ""
|
||||||
|
echo " Log: cat $LOG"
|
||||||
|
echo "========================================="
|
||||||
277
steps/02-peers.sh
Normal file
277
steps/02-peers.sh
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
#!/bin/bash -eu
|
||||||
|
# =============================================================================
|
||||||
|
# 02-migrate-peers.sh — Run as Linux user after 01
|
||||||
|
# 1. Shuts down legacy WireGuard
|
||||||
|
# 2. Injects legacy private key into new wg0.conf
|
||||||
|
# 3. Starts new WireGuard
|
||||||
|
# 4. Verifies public key is identical
|
||||||
|
# 5. Migrates peers via API
|
||||||
|
# 6. Destroys private key
|
||||||
|
# Auto-rollback: restores legacy if anything fails
|
||||||
|
# =============================================================================
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "[X] Run as your Linux user, not root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; RESET='\033[0m'
|
||||||
|
|
||||||
|
BACKUP_DIR="$HOME/.wg-migration"
|
||||||
|
LOG="$BACKUP_DIR/migration.log"
|
||||||
|
OPERATOR_DIR="$HOME/operator-docker"
|
||||||
|
WG_CONF="$OPERATOR_DIR/services/wireguard/config/wg_confs/wg0.conf"
|
||||||
|
WG_CONF_BAK=""
|
||||||
|
|
||||||
|
ok() { echo -e "${GREEN}[OK]${RESET} $1"; echo "[OK] $1" >> "$LOG"; }
|
||||||
|
info() { echo -e "${CYAN}[i]${RESET} $1"; echo "[i] $1" >> "$LOG"; }
|
||||||
|
warn() { echo -e "${YELLOW}[!]${RESET} $1"; echo "[!] $1" >> "$LOG"; }
|
||||||
|
fail() { echo -e "${RED}[X]${RESET} $1"; echo "[X] $1" >> "$LOG"; exit 1; }
|
||||||
|
sep() { echo -e "\n${CYAN}------------------------------------${RESET}"; }
|
||||||
|
|
||||||
|
rollback_02() {
|
||||||
|
echo ""
|
||||||
|
warn "Error detected — starting rollback..."
|
||||||
|
echo "[ROLLBACK-02] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
[ -n "$WG_CONF_BAK" ] && [ -f "$WG_CONF_BAK" ] && \
|
||||||
|
cp "$WG_CONF_BAK" "$WG_CONF" && warn "wg0.conf restored."
|
||||||
|
|
||||||
|
cd "$OPERATOR_DIR" 2>/dev/null || true
|
||||||
|
docker compose stop wireguard 2>/dev/null || true
|
||||||
|
|
||||||
|
LEGACY_COMPOSE_DIR=$(cat "$BACKUP_DIR/legacy_compose_dir" 2>/dev/null || true)
|
||||||
|
if [ -n "$LEGACY_COMPOSE_DIR" ] && [ -d "$LEGACY_COMPOSE_DIR" ]; then
|
||||||
|
sudo modprobe ip6table_filter 2>/dev/null || true
|
||||||
|
cd "$LEGACY_COMPOSE_DIR"
|
||||||
|
docker compose up -d 2>/dev/null || true
|
||||||
|
sleep 5
|
||||||
|
LEGACY_UP=$(docker ps --format '{{.Names}}' | grep -i wireguard | head -1 || true)
|
||||||
|
[ -n "$LEGACY_UP" ] && ok "Legacy restored: $LEGACY_UP" || \
|
||||||
|
warn "Legacy failed to start. Run manually: cd $LEGACY_COMPOSE_DIR && docker compose up -d"
|
||||||
|
fi
|
||||||
|
warn "Rollback complete. Check: cat $LOG"
|
||||||
|
}
|
||||||
|
trap rollback_02 ERR
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " 02 - Identity and peer migration"
|
||||||
|
echo " $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
echo "========================================="
|
||||||
|
echo "[START-02] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
# ─── PREREQUISITES ────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Checking prerequisites..."
|
||||||
|
|
||||||
|
if ! docker info &>/dev/null; then
|
||||||
|
if groups | grep -q docker; then
|
||||||
|
fail "Docker socket not accessible. Try logging out and back in."
|
||||||
|
else
|
||||||
|
warn "No Docker access — re-launching with docker group..."
|
||||||
|
exec newgrp docker "$0" "$@"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -f "$BACKUP_DIR/private_key" ] || fail "No private key backup found."
|
||||||
|
[ -f "$BACKUP_DIR/wg0-legacy.conf" ] || fail "No peer backup found."
|
||||||
|
[ -f "$BACKUP_DIR/public_key" ] || fail "No public key backup found."
|
||||||
|
[ -f "$BACKUP_DIR/legacy_compose_dir" ] || fail "No legacy snapshot found."
|
||||||
|
ok "Backups found."
|
||||||
|
|
||||||
|
[ -d "$OPERATOR_DIR" ] || fail "operator-docker not found. Run 01 first."
|
||||||
|
[ -f "$WG_CONF" ] || fail "wg0.conf not found: $WG_CONF"
|
||||||
|
ok "operator-docker found."
|
||||||
|
|
||||||
|
for CONTAINER in operator-api mysql; do
|
||||||
|
STATUS=$(docker inspect -f '{{.State.Running}}' "$CONTAINER" 2>/dev/null || echo "false")
|
||||||
|
[ "$STATUS" = "true" ] || fail "Container '$CONTAINER' is not running."
|
||||||
|
ok "Running: $CONTAINER"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ─── LOAD CREDENTIALS ─────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Loading credentials..."
|
||||||
|
set -a; source "$OPERATOR_DIR/.env"; set +a
|
||||||
|
|
||||||
|
[ -z "${API_TOKEN:-}" ] && fail "API_TOKEN not found in .env"
|
||||||
|
[ -z "${BASE_DOMAIN:-}" ] && fail "BASE_DOMAIN not found in .env"
|
||||||
|
[ -z "${API_SUBDOMAIN:-}" ] && fail "API_SUBDOMAIN not found in .env"
|
||||||
|
|
||||||
|
echo "$BASE_DOMAIN" | grep -qE '[/;|&<> ]|^[0-9]+-' && \
|
||||||
|
fail "Invalid BASE_DOMAIN in .env: '$BASE_DOMAIN'"
|
||||||
|
|
||||||
|
API_URL="https://${API_SUBDOMAIN}.${BASE_DOMAIN}"
|
||||||
|
ok "API URL: $API_URL"
|
||||||
|
|
||||||
|
# ─── STOP LEGACY WIREGUARD ────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Stopping legacy WireGuard..."
|
||||||
|
LEGACY_COMPOSE_DIR=$(cat "$BACKUP_DIR/legacy_compose_dir")
|
||||||
|
[ -d "$LEGACY_COMPOSE_DIR" ] || fail "Legacy directory not found: $LEGACY_COMPOSE_DIR"
|
||||||
|
|
||||||
|
cd "$LEGACY_COMPOSE_DIR"
|
||||||
|
docker compose stop wireguard 2>/dev/null || true
|
||||||
|
sleep 3
|
||||||
|
STILL_UP=$(docker compose ps --services --filter "status=running" 2>/dev/null | grep -i wireguard || true)
|
||||||
|
[ -n "$STILL_UP" ] && fail "Legacy WireGuard is still running."
|
||||||
|
ok "Legacy WireGuard stopped."
|
||||||
|
|
||||||
|
# ─── BACKUP NEW CONF ──────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Backing up new wg0.conf..."
|
||||||
|
WG_CONF_BAK="$WG_CONF.bak.$(date +%s)"
|
||||||
|
cp "$WG_CONF" "$WG_CONF_BAK"
|
||||||
|
ok "Backup: $WG_CONF_BAK"
|
||||||
|
|
||||||
|
# ─── INJECT PRIVATE KEY ───────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Injecting legacy private key..."
|
||||||
|
LEGACY_PRIVATE_KEY=$(cat "$BACKUP_DIR/private_key" | tr -d '[:space:]')
|
||||||
|
LEGACY_PUBLIC_KEY=$(cat "$BACKUP_DIR/public_key" | tr -d '[:space:]')
|
||||||
|
[ -z "$LEGACY_PRIVATE_KEY" ] && fail "Private key is empty."
|
||||||
|
[ -z "$LEGACY_PUBLIC_KEY" ] && fail "Public key is empty."
|
||||||
|
|
||||||
|
sed -i "s|^PrivateKey = .*|PrivateKey = $LEGACY_PRIVATE_KEY|" "$WG_CONF"
|
||||||
|
ok "Private key written to wg0.conf."
|
||||||
|
|
||||||
|
WG_SERVER_KEY="$OPERATOR_DIR/services/wireguard/config/server/privatekey-server"
|
||||||
|
WG_SERVER_PUB="$OPERATOR_DIR/services/wireguard/config/server/publickey-server"
|
||||||
|
mkdir -p "$(dirname "$WG_SERVER_KEY")"
|
||||||
|
echo "$LEGACY_PRIVATE_KEY" > "$WG_SERVER_KEY"
|
||||||
|
echo "$LEGACY_PUBLIC_KEY" > "$WG_SERVER_PUB"
|
||||||
|
ok "Private key written to server keyfile."
|
||||||
|
|
||||||
|
# ─── START NEW WIREGUARD ──────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Starting new WireGuard with legacy identity..."
|
||||||
|
echo "[WIREGUARD-START] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
cd "$OPERATOR_DIR"
|
||||||
|
sudo modprobe ip6table_filter 2>/dev/null || true
|
||||||
|
docker compose up -d --force-recreate wireguard
|
||||||
|
info "Waiting for startup..."
|
||||||
|
sleep 8
|
||||||
|
|
||||||
|
STATUS=$(docker inspect -f '{{.State.Running}}' wireguard 2>/dev/null || echo "false")
|
||||||
|
[ "$STATUS" = "true" ] || fail "New WireGuard failed to start. Check: docker logs wireguard"
|
||||||
|
ok "New WireGuard running."
|
||||||
|
|
||||||
|
# ─── VERIFY PUBLIC KEY ────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Verifying server identity..."
|
||||||
|
|
||||||
|
NEW_PUBLIC_KEY=$(docker exec wireguard cat /config/server/publickey-server 2>/dev/null | \
|
||||||
|
tr -d '[:space:]' || true)
|
||||||
|
if [ -z "$NEW_PUBLIC_KEY" ]; then
|
||||||
|
NEW_PUBLIC_KEY=$(docker exec wireguard wg show wg0 2>/dev/null | \
|
||||||
|
grep "public key" | awk '{print $NF}' | tr -d '[:space:]' || true)
|
||||||
|
fi
|
||||||
|
[ -z "$NEW_PUBLIC_KEY" ] && fail "Could not retrieve public key from new WireGuard."
|
||||||
|
|
||||||
|
if [ "$NEW_PUBLIC_KEY" != "$LEGACY_PUBLIC_KEY" ]; then
|
||||||
|
warn "Public key MISMATCH!"
|
||||||
|
warn " Expected : $LEGACY_PUBLIC_KEY"
|
||||||
|
warn " Got : $NEW_PUBLIC_KEY"
|
||||||
|
fail "Server identity was not preserved."
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok "Public key verified: $NEW_PUBLIC_KEY"
|
||||||
|
ok "Existing users will reconnect automatically."
|
||||||
|
|
||||||
|
# ─── VERIFY API ───────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Verifying API..."
|
||||||
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN" \
|
||||||
|
"$API_URL/wireguard/peers" 2>/dev/null || echo "000")
|
||||||
|
[ "$HTTP_CODE" = "200" ] || fail "API not responding (HTTP $HTTP_CODE)."
|
||||||
|
ok "API responding."
|
||||||
|
|
||||||
|
# ─── MIGRATE PEERS ────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Migrating peers to new API..."
|
||||||
|
|
||||||
|
LEGACY_CONF=$(cat "$BACKUP_DIR/wg0-legacy.conf")
|
||||||
|
MIGRATED=0
|
||||||
|
FAILED=0
|
||||||
|
CURRENT_PUBKEY=""
|
||||||
|
CURRENT_IPS=""
|
||||||
|
|
||||||
|
migrate_peer() {
|
||||||
|
local PUBKEY="$1"
|
||||||
|
local IPS="$2"
|
||||||
|
|
||||||
|
IPS_JSON=$(echo "$IPS" | tr ',' '\n' | \
|
||||||
|
sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//' | \
|
||||||
|
awk 'NF {print "\"" $0 "\""}' | paste -sd ',' | \
|
||||||
|
sed 's/^/[/' | sed 's/$/]/')
|
||||||
|
|
||||||
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 \
|
||||||
|
-X POST "$API_URL/wireguard/peers" \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"public_key\": \"$PUBKEY\", \"allowed_ips\": $IPS_JSON}" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
|
ok "Peer migrated: ${PUBKEY:0:20}... → $IPS"
|
||||||
|
MIGRATED=$((MIGRATED + 1))
|
||||||
|
else
|
||||||
|
warn "Peer failed: ${PUBKEY:0:20}... (HTTP $HTTP_CODE)"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" == "[Peer]" ]]; then
|
||||||
|
if [ -n "$CURRENT_PUBKEY" ] && [ -n "$CURRENT_IPS" ]; then
|
||||||
|
migrate_peer "$CURRENT_PUBKEY" "$CURRENT_IPS"
|
||||||
|
fi
|
||||||
|
CURRENT_PUBKEY=""
|
||||||
|
CURRENT_IPS=""
|
||||||
|
elif [[ "$line" =~ ^PublicKey\ =\ (.+)$ ]]; then
|
||||||
|
CURRENT_PUBKEY="${BASH_REMATCH[1]}"
|
||||||
|
elif [[ "$line" =~ ^AllowedIPs\ =\ (.+)$ ]]; then
|
||||||
|
CURRENT_IPS="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
done <<< "$LEGACY_CONF"
|
||||||
|
|
||||||
|
[ -n "$CURRENT_PUBKEY" ] && [ -n "$CURRENT_IPS" ] && migrate_peer "$CURRENT_PUBKEY" "$CURRENT_IPS"
|
||||||
|
|
||||||
|
# ─── VERIFY PEERS ─────────────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Verifying peers in WireGuard..."
|
||||||
|
REGISTERED=$(docker exec wireguard wg show wg0 | grep -c "^ peer:" 2>/dev/null || echo 0)
|
||||||
|
ok "$REGISTERED peers active in wg0."
|
||||||
|
|
||||||
|
# ─── DESTROY PRIVATE KEY ──────────────────────────────────────────────────────
|
||||||
|
sep
|
||||||
|
info "Destroying private key..."
|
||||||
|
command -v shred &>/dev/null && \
|
||||||
|
shred -u "$BACKUP_DIR/private_key" 2>/dev/null || \
|
||||||
|
rm -f "$BACKUP_DIR/private_key"
|
||||||
|
ok "Private key deleted from disk."
|
||||||
|
|
||||||
|
trap - ERR
|
||||||
|
echo "[END-02] $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo " Migration complete"
|
||||||
|
echo "========================================="
|
||||||
|
echo ""
|
||||||
|
echo " Public key : $NEW_PUBLIC_KEY"
|
||||||
|
echo " API : $API_URL"
|
||||||
|
echo " Peers migrated : $MIGRATED"
|
||||||
|
if [ "$FAILED" -gt 0 ]; then
|
||||||
|
echo -e " ${RED}Peers failed : $FAILED${RESET}"
|
||||||
|
echo " Check: cat $LOG"
|
||||||
|
else
|
||||||
|
echo " Errors : none"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo " Existing users reconnect automatically"
|
||||||
|
echo " without new configuration."
|
||||||
|
echo ""
|
||||||
|
echo " Log: cat $LOG"
|
||||||
|
echo "========================================="
|
||||||
Loading…
Reference in a new issue