From f3792a38fc4a5453511b5f6a91ba3a21bcfb08e9 Mon Sep 17 00:00:00 2001 From: Justin Oros Date: Sat, 18 Apr 2026 14:25:24 -0700 Subject: [PATCH] setup-spoke.sh: fix port scan range and user@host sed regex, offboard/onboard-spoke.sh: fix registry grep-v empty-output clobber, setup-network.sh: fix wifi password colon handling --- hub/offboard-spoke.sh | 8 ++------ hub/onboard-spoke.sh | 16 +++++++-------- hub/setup-hub.sh | 1 + spoke/setup-network.sh | 4 ++-- spoke/setup-spoke.sh | 44 ++++++++++++++++++------------------------ 5 files changed, 31 insertions(+), 42 deletions(-) diff --git a/hub/offboard-spoke.sh b/hub/offboard-spoke.sh index 59d7405..6a9d3e2 100755 --- a/hub/offboard-spoke.sh +++ b/hub/offboard-spoke.sh @@ -134,12 +134,8 @@ else fi header "Removing from Registry" -if grep -v "^${SPOKE_NAME} " "$REGISTRY" > "${REGISTRY}.tmp" 2>/dev/null || true; then - mv "${REGISTRY}.tmp" "$REGISTRY" -else - rm -f "${REGISTRY}.tmp" - die "Failed to update registry" -fi +grep -v "^${SPOKE_NAME} " "$REGISTRY" > "${REGISTRY}.tmp" 2>/dev/null || true +mv "${REGISTRY}.tmp" "$REGISTRY" info "$SPOKE_NAME removed from registry." header "Offboarding Complete" diff --git a/hub/onboard-spoke.sh b/hub/onboard-spoke.sh index 73b57f8..5afeb2a 100755 --- a/hub/onboard-spoke.sh +++ b/hub/onboard-spoke.sh @@ -77,10 +77,12 @@ header "Checking Tunnel" info "Scanning spoke host key..." KEYSCAN=$(ssh-keyscan -p "$TUNNEL_PORT" -H localhost 2>/dev/null) [ -n "$KEYSCAN" ] || die "Spoke not reachable on port $TUNNEL_PORT — is the tunnel up?" -KEYSCAN_KEY=$(echo "$KEYSCAN" | awk '{print $3}') -if ! grep -qF "$KEYSCAN_KEY" "$SSH_DIR/known_hosts" 2>/dev/null; then - echo "$KEYSCAN" >> "$SSH_DIR/known_hosts" -fi +while IFS= read -r KEYSCAN_LINE; do + KEYSCAN_KEY=$(echo "$KEYSCAN_LINE" | awk '{print $3}') + if ! grep -qF "$KEYSCAN_KEY" "$SSH_DIR/known_hosts" 2>/dev/null; then + echo "$KEYSCAN_LINE" >> "$SSH_DIR/known_hosts" + fi +done <<< "$KEYSCAN" info "Verifying spoke is reachable on port $TUNNEL_PORT..." retry_or_abort \ @@ -150,12 +152,8 @@ MOUNT_POINT="${HOME}/mnt/${SPOKE_NAME}" mkdir -p "$MOUNT_POINT" if grep -q "^${SPOKE_NAME} " "$REGISTRY" 2>/dev/null; then warn "$SPOKE_NAME already in registry, updating." - if grep -v "^${SPOKE_NAME} " "$REGISTRY" > "${REGISTRY}.tmp" 2>/dev/null || true; then + grep -v "^${SPOKE_NAME} " "$REGISTRY" > "${REGISTRY}.tmp" 2>/dev/null || true mv "${REGISTRY}.tmp" "$REGISTRY" -else - rm -f "${REGISTRY}.tmp" - die "Failed to update registry" -fi fi echo "${SPOKE_NAME} ${TUNNEL_PORT} ${KEY_PATH} ${MOUNT_POINT}" >> "$REGISTRY" info "$SPOKE_NAME registered." diff --git a/hub/setup-hub.sh b/hub/setup-hub.sh index 7930c50..39243c1 100755 --- a/hub/setup-hub.sh +++ b/hub/setup-hub.sh @@ -247,6 +247,7 @@ info "Checking SSH directory permissions..." check_permissions "$SSH_DIR/authorized_keys" "authorized_keys" check_permissions "$RCLONE_CONF" "rclone.conf" for PRIVKEY in "$SSH_DIR"/*; do + [ -e "$PRIVKEY" ] || continue [[ "$PRIVKEY" == *.pub ]] && continue [ -f "$PRIVKEY" ] || continue case "$(file -b "$PRIVKEY" 2>/dev/null)" in diff --git a/spoke/setup-network.sh b/spoke/setup-network.sh index 4eee27c..23fc0e6 100755 --- a/spoke/setup-network.sh +++ b/spoke/setup-network.sh @@ -116,7 +116,7 @@ if $IS_WIFI; then [ -n "$WIFI_PASS" ] || die "Password cannot be empty" else WIFI_SSID="$CURRENT_SSID" - WIFI_PASS=$(grep -FA2 "\"${WIFI_SSID}\"" "$NETPLAN_FILE" 2>/dev/null | grep password | awk -F': ' '{print $2}' | tr -d '"' || true) + WIFI_PASS=$(grep -FA2 "\"${WIFI_SSID}\"" "$NETPLAN_FILE" 2>/dev/null | grep -F "password" | sed 's/^[^:]*: *//' | tr -d '"' || true) [ -n "$WIFI_PASS" ] || die "Could not extract WiFi password from existing config — please re-enter credentials." fi fi @@ -182,7 +182,7 @@ for i in $(seq 1 6); do warn "Network check $i/6 failed, retrying..." done -if $CONNECTED; then +if [ "$CONNECTED" = "true" ]; then info "Network connectivity confirmed — config applied permanently." else warn "No network connectivity detected after 30 seconds — reverting to backup config." diff --git a/spoke/setup-spoke.sh b/spoke/setup-spoke.sh index 488fe68..874d193 100755 --- a/spoke/setup-spoke.sh +++ b/spoke/setup-spoke.sh @@ -270,9 +270,6 @@ fi info "Checking SSH key permissions..." check_permissions "$KEY_PATH" "spoke SSH private key" -if [ -f "$KEY_PATH.pub" ]; then - check_permissions "$KEY_PATH.pub" "spoke SSH public key" -fi info "Scanning hub host key..." sudo -u "$SPOKE_USER" touch "$SSH_DIR/known_hosts" @@ -297,19 +294,22 @@ retry_or_abort \ header "Finding Available Tunnel Port" info "Scanning for a free port on $HUB_HOST starting from $START_PORT..." -TUNNEL_PORT="" -for PORT in $(seq "$START_PORT" $((START_PORT + 20))); do - RESULT=$(sudo -u "$SPOKE_USER" ssh -i "$KEY_PATH" "$HUB_USER@$HUB_HOST" "ss -tlnp | grep :$PORT" 2>/dev/null || true) - if [ -z "$RESULT" ]; then - TUNNEL_PORT="$PORT" - info "Port $TUNNEL_PORT is available." - break - else - warn "Port $PORT is in use, trying next..." - fi -done -[ -n "$TUNNEL_PORT" ] || die "Could not find a free port between $START_PORT and $((START_PORT + 20)). Ask the hub owner to free up a port." +find_free_port() { + local start="$1" + for PORT in $(seq "$start" $((start + 99))); do + RESULT=$(sudo -u "$SPOKE_USER" ssh -i "$KEY_PATH" "$HUB_USER@$HUB_HOST" "ss -tlnp | grep :$PORT" 2>/dev/null || true) + if [ -z "$RESULT" ]; then + echo "$PORT" + return 0 + fi + warn "Port $PORT is in use, trying next..." + done + return 1 +} + +TUNNEL_PORT=$(find_free_port "$START_PORT") || die "Could not find a free port starting from $START_PORT. Ask the hub owner to free up a port." +info "Port $TUNNEL_PORT is available." header "Configuring compose.yaml" info "Setting port to $TUNNEL_PORT and key to $KEY_NAME..." @@ -325,7 +325,7 @@ sed -i "s|-R [0-9]*:localhost:22|-R ${TUNNEL_PORT}:localhost:22|g" "$COMPOSE" sed -i "s|-i /home/[^ ]*/\.ssh/[^ ]*|-i ${SSH_DIR}/${KEY_NAME}|g" "$COMPOSE" sed -i "/known_hosts/!s|/home/[^/]*/\.ssh/[^:]*:/home/[^/]*/\.ssh/[^:]*:ro|${SSH_DIR}/${KEY_NAME}:${SSH_DIR}/${KEY_NAME}:ro|g" "$COMPOSE" sed -i "s|/home/[^/]*/\.ssh/known_hosts|${SSH_DIR}/known_hosts|g" "$COMPOSE" -sed -i "s| [a-zA-Z0-9._-]*@[a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]*[[:space:]]*$| ${HUB_USER}@${HUB_HOST}|g" "$COMPOSE" +sed -i "s| [a-zA-Z0-9._-]*@[a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]*[[:space:]]*\$| ${HUB_USER}@${HUB_HOST}|" "$COMPOSE" sed -i "s|/home/[^/]*/st:|${SYNCTHING_MOUNT}:|g" "$COMPOSE" sed -i "s|PUID=[0-9]*|PUID=${SPOKE_UID}|g" "$COMPOSE" sed -i "s|PGID=[0-9]*|PGID=${SPOKE_GID}|g" "$COMPOSE" @@ -351,15 +351,9 @@ for ATTEMPT in 1 2 3; do if echo "$LOGS" | grep -q "remote port forwarding failed"; then warn "Tunnel failed on attempt $ATTEMPT — port $TUNNEL_PORT may have been taken." docker compose down 2>/dev/null || true - NEXT_PORT=$((TUNNEL_PORT + 1)) - RESULT=$(sudo -u "$SPOKE_USER" ssh -i "$KEY_PATH" "$HUB_USER@$HUB_HOST" "ss -tlnp | grep :$NEXT_PORT" 2>/dev/null || true) - if [ -z "$RESULT" ]; then - TUNNEL_PORT=$NEXT_PORT - warn "Retrying with port $TUNNEL_PORT..." - sed -i "s|-R [0-9]*:localhost:22|-R ${TUNNEL_PORT}:localhost:22|g" "$COMPOSE" - else - warn "Next port also in use. Waiting before retry..." - fi + TUNNEL_PORT=$(find_free_port $((TUNNEL_PORT + 1))) || die "Could not find a free port. Ask the hub owner to free up a port." + warn "Retrying with port $TUNNEL_PORT..." + sed -i "s|-R [0-9]*:localhost:22|-R ${TUNNEL_PORT}:localhost:22|g" "$COMPOSE" else TUNNEL_UP="true" break