#!/usr/bin/env bash set -euo pipefail script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # shellcheck source=scripts/cluster/common.sh source "$script_dir/common.sh" load_cluster_env require_commands ssh scp hosts=("$CLUSTER_NINGBO_HOST" "$CLUSTER_HONGKONG_HOST" "$CLUSTER_LOS_ANGELES_HOST") public_endpoints=("${CLUSTER_NINGBO_HOST#*@}" "${CLUSTER_HONGKONG_HOST#*@}" "${CLUSTER_LOS_ANGELES_HOST#*@}") wireguard_ips=(10.77.0.1 10.77.0.2 10.77.0.3) wireguard_ports=(51820 51820 51820) if [[ -n $CLUSTER_NINGBO_WORKER_HOST ]]; then hosts+=("$CLUSTER_NINGBO_WORKER_HOST") public_endpoints+=("${CLUSTER_NINGBO_WORKER_HOST#*@}") wireguard_ips+=(10.77.0.4) wireguard_ports+=(443) fi public_keys=() for host in "${hosts[@]}"; do echo "[wireguard] preparing $host" public_key=$(cluster_ssh "$host" 'bash -s' <<'REMOTE' | tail -n 1 set -euo pipefail export DEBIAN_FRONTEND=noninteractive if ! command -v wg >/dev/null 2>&1; then apt-get update -qq apt-get install -y -qq wireguard-tools fi install -d -m 0700 /etc/wireguard if [[ ! -s /etc/wireguard/privatekey ]]; then umask 077 wg genkey >/etc/wireguard/privatekey fi chmod 0600 /etc/wireguard/privatekey wg pubkey /etc/wireguard/publickey cat /etc/wireguard/publickey REMOTE ) [[ $public_key =~ ^[A-Za-z0-9+/]{43}=$ ]] || { echo "invalid WireGuard public key returned by $host" >&2 exit 1 } public_keys+=("$public_key") done for local_index in "${!hosts[@]}"; do peer_arguments=() for candidate in "${!hosts[@]}"; do if [[ $candidate -ne $local_index ]]; then peer_arguments+=( "${public_keys[$candidate]}" "${public_endpoints[$candidate]}" "${wireguard_ports[$candidate]}" "${wireguard_ips[$candidate]}" ) fi done echo "[wireguard] configuring ${hosts[$local_index]} as ${wireguard_ips[$local_index]}" cluster_ssh "${hosts[$local_index]}" bash -s -- \ "${wireguard_ips[$local_index]}" \ "${wireguard_ports[$local_index]}" \ "${peer_arguments[@]}" <<'REMOTE' set -euo pipefail local_ip=$1 local_port=$2 shift 2 private_key=$(cat /etc/wireguard/privatekey) umask 077 temporary_config=$(mktemp /etc/wireguard/wg0.conf.XXXXXX) cat >"$temporary_config" <= 4 )); do cat >>"$temporary_config" </dev/null systemctl restart wg-quick@wg0 REMOTE done for source_index in "${!hosts[@]}"; do for target_index in "${!hosts[@]}"; do [[ $source_index -eq $target_index ]] && continue cluster_ssh "${hosts[$source_index]}" \ "ping -c 3 -W 2 ${wireguard_ips[$target_index]} >/dev/null" done done for host in "${hosts[@]}"; do latest_handshake=$(cluster_ssh "$host" \ "wg show wg0 latest-handshakes | awk '\$2 > 0 { count++ } END { print count + 0 }'") [[ $latest_handshake == $((${#hosts[@]} - 1)) ]] || { echo "WireGuard handshake verification failed on $host" >&2 exit 1 } done echo "wireguard_bootstrap=PASS peers=${#hosts[@]} routing=direct"