diff --git a/Partnership/partnership_onboard.sh b/Partnership/partnership_onboard.sh index 9d97a86..cd9a563 100755 --- a/Partnership/partnership_onboard.sh +++ b/Partnership/partnership_onboard.sh @@ -559,8 +559,47 @@ MASTER_PUSH_OK=false echo "━━━ Step 1 — SSH Key Setup ━━━" if [[ "$SKIP_SSH" == true ]]; then - warn "Skipping (--skip-ssh / --phase2-only)" + warn "Skipping (--skip-ssh)" STEP_SSH_OK=true +elif [[ "$PHASE1_ONLY" == true ]]; then + # Phase 1 in background: test if SSH already works first — avoids ssh-copy-id + # hanging for a password prompt with no TTY. + if timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \ + -o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$MIRROR_IP" exit 0 2>/dev/null; then + log "SSH to $MIRROR already works ✅ — skipping key install" + STEP_SSH_OK=true + else + # Key not yet on HOST2 — try ssh_setup.sh (works interactively, may fail in background) + if bash "$SCRIPT_DIR/ssh_setup.sh" "${EXTRA_FLAGS[@]}"; then + log "SSH keys ready ✅" + STEP_SSH_OK=true + else + # Soft-fail: generate key locally if not present, then tell user to install manually + warn "Could not install key on $MIRROR automatically (no terminal for password prompt)" + if [[ -f "$SSH_KEY" ]]; then + log "Local key exists at: $SSH_KEY" + else + bash "$SCRIPT_DIR/ssh_setup.sh" --key-only "${EXTRA_FLAGS[@]}" 2>/dev/null || true + fi + if [[ -f "${SSH_KEY}.pub" ]]; then + echo "" + echo " Install this key on $MIRROR to complete SSH setup:" + echo " ┌─────────────────────────────────────────────────────" + cat "${SSH_KEY}.pub" | sed 's/^/ │ /' + echo " └─────────────────────────────────────────────────────" + echo " Run on a terminal: ssh-copy-id -i ${SSH_KEY}.pub root@${MIRROR_IP}" + echo " Then click 'Push Conf' in the Partnership tab." + # Write key-ready flag so UI can show the manual-install state + [[ "$DRY_RUN" == false ]] && { + local kflag="${MIRROR_ID}_KEY_READY" + grep -q "^${kflag}=" /boot/config/varaverk_setup.db 2>/dev/null \ + && sed -i "s|^${kflag}=.*|${kflag}=true|" /boot/config/varaverk_setup.db \ + || echo "${kflag}=true" >> /boot/config/varaverk_setup.db + } + fi + STEP_SSH_OK=false + fi + fi elif bash "$SCRIPT_DIR/ssh_setup.sh" "${EXTRA_FLAGS[@]}"; then log "SSH keys ready ✅" STEP_SSH_OK=true @@ -574,6 +613,30 @@ fi # --phase1-only: SSH + conf push is all HOST1 needs to do before HOST2 installs Varaverk. # HOST2's wizard will detect the pushed master.conf + state file and take the correct path. if [[ "$PHASE1_ONLY" == true ]]; then + if [[ "$STEP_SSH_OK" == false ]]; then + # SSH key not yet installed on HOST2 — can't push conf, but local setup still runs. + # UI will show "key ready, install manually" state via HOST2_KEY_READY flag. + echo "" + echo "━━━ Phase 1 — HOST1 Local Setup (SSH pending) ━━━" + bash "$SCRIPT_DIR/partnership_manager.sh" --onboard --local-only "${EXTRA_FLAGS[@]}" || \ + warn "Local setup had issues — FolderView3 may need manual setup" + + END=$(date +%s) + echo "" + echo "━━━━━ $ICON_SUMMARY PHASE 1 — SSH PENDING ━━━━━" + echo " SSH keys: key generated ✅ — NOT yet installed on $MIRROR ⚠" + echo " Conf push: skipped (needs SSH access to $MIRROR)" + echo " HOST1 setup: done ✅" + echo " Duration: $(format_duration $(( END - START )))" + echo "" + echo " ACTION NEEDED: install the key on $MIRROR:" + echo " ssh-copy-id -i ${SSH_KEY}.pub root@${MIRROR_IP}" + echo " Then click 'Push Conf' in Partnership tab, or run:" + echo " bash Partnership/partnership_onboard.sh --phase1-only --skip-ssh" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 + fi + echo "" echo "━━━ Phase 1 — Conf Push ━━━" diff --git a/Plugin/unraid/include/partnership.php b/Plugin/unraid/include/partnership.php index 08cb71e..791b143 100644 --- a/Plugin/unraid/include/partnership.php +++ b/Plugin/unraid/include/partnership.php @@ -156,6 +156,8 @@ function vv_pt_nodes(): array { $onboardPhase = $isMe ? null : (($setupDb[$nodeIdUpper . '_PHASE2_DONE'] ?? '') === 'true' ? 2 : (($setupDb[$nodeIdUpper . '_PHASE1_DONE'] ?? '') === 'true' ? 1 : 0)); + // key_ready: local key generated but not yet installed on HOST2 (SSH pending manual step) + $keyReady = !$isMe && ($setupDb[$nodeIdUpper . '_KEY_READY'] ?? '') === 'true'; // For self: local setup complete flag (set by partnership_manager --onboard --local-only) $localDone = $isMe && ($setupDb[$nodeIdUpper . '_LOCAL_DONE'] ?? '') === 'true'; @@ -172,6 +174,7 @@ function vv_pt_nodes(): array { 'partnership' => $ptDb, 'system' => $system, 'onboard_phase' => $onboardPhase, + 'key_ready' => $keyReady, 'local_done' => $localDone, ]; } diff --git a/Plugin/unraid/pages/partnership.php b/Plugin/unraid/pages/partnership.php index ab72d92..03a87a9 100644 --- a/Plugin/unraid/pages/partnership.php +++ b/Plugin/unraid/pages/partnership.php @@ -106,6 +106,16 @@ function vvPtOnboard(btn) { .finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Onboard (Mirror)'; }, 4000)); } +function vvPtPushConf(btn, hostId) { + if (!confirm(`Push conf to ${hostId}?\n\nAssumes SSH key is already installed on ${hostId}.\nSkips key generation/install, goes straight to conf push + local setup.`)) return; + btn.disabled = true; + btn.textContent = '⟳ Pushing…'; + _vvPtRun('Partnership/partnership_onboard.sh', '--phase1-only --skip-ssh') + .then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); }) + .catch(e => alert('Error: ' + e)) + .finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Push Conf (key installed)'; }, 4000)); +} + function vvPtLocalSetup(btn) { if (!confirm('Complete HOST1 local setup?\n\nRuns FolderView3 integration and marks HOST1 as locally ready.\nDoes not require HOST2 to be online.')) return; btn.disabled = true; @@ -245,7 +255,8 @@ function _nodeCard(node) { : '') : (phase === 2 ? '' : phase === 1 ? `
⏳ SSH ready · awaiting onboard
` : - `
○ Not yet provisioned
`); + node.key_ready ? `
🔑 Key generated · install on HOST2 then Push Conf
` : + `
○ Not yet provisioned
`); let body = ''; @@ -328,9 +339,15 @@ function _renderActions(nodes, cfg) { if (phase === 0) { // Not yet provisioned — offer Phase 1 (safe before HOST2 has Varaverk) html += ``; + if (remote.key_ready) { + html += ``; + } html += `