docs+ui: surface SSH context for remote_services (closes #409)

Migration guide: expand the one-liner after SSH setup into a concrete
'To disable SSH' section covering both the USB-stick and persistent-file
cases, with the button name and CLI command.

Admin UI:
- Preconditions label: 'remote_services' → 'SSH (remote_services)'
  with a tooltip explaining the connection
- Buttons: 'Enable/Remove Persistent Remote Services' →
  'Enable SSH (Persist remote_services)' /
  'Disable SSH (Remove remote_services)'
- Confirm dialog: mentions SSH and reboot requirement explicitly
- Verdict text: all three states now lead with 'SSH ...' so users
  recognise what the check controls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-25 21:46:57 +02:00
co-authored by Claude Sonnet 4.6
parent bec52b87a5
commit d93d9a3e26
3 changed files with 18 additions and 7 deletions
@@ -132,6 +132,15 @@ The XML migration writes updated configuration to the speaker's filesystem, whic
You only need to do this once per speaker. SSH can remain enabled for future maintenance or be disabled after migration — your choice.
**To disable SSH after migration:**
- **USB stick only (no persistent file written):** remove the stick and reboot the speaker — SSH will not be available after the next boot.
- **Persistent `remote_services` file** (written automatically during XML migration): remove it via the admin UI → *Migrate* tab → **Disable SSH (Remove remote_services)** button, then reboot. Or via the CLI:
```shell
soundtouch-cli --host <SPEAKER-IP> setup remote-services --remove
```
Then reboot the speaker for the change to take effect.
### Telnet:17000 (fallback when SSH isn't possible)
If the USB-stick unlock doesn't work on your speaker (some firmware revisions refuse it — notably SA-5, ST520, and recent ST Portables), the wizard falls back to the speaker's **built-in diagnostic shell on TCP port 17000**. No setup required — most SoundTouch firmware exposes it automatically. The wizard detects which transports are available and picks the right one; you don't have to choose manually.
+4 -3
View File
@@ -589,7 +589,7 @@
<table style="width: 100%; border-collapse: collapse">
<tbody>
<tr style="border-top: 1px solid #eee">
<td style="padding: 4px 8px; width: 170px; color: #555">remote_services</td>
<td style="padding: 4px 8px; width: 170px; color: #555" title="The remote_services file controls whether SSH is available after reboot">SSH (remote_services)</td>
<td id="state-remote-services-cell" style="padding: 4px 8px"></td>
</tr>
<tr style="border-top: 1px solid #eee">
@@ -1099,10 +1099,11 @@
padding: 10px 20px;
"
>
Enable Persistent Remote Services
Enable SSH (Persist remote_services)
</button>
<button
id="remove-remote-btn"
title="Removes the remote_services file — SSH will be disabled after the next reboot"
style="
background-color: #f44336;
color: white;
@@ -1110,7 +1111,7 @@
padding: 10px 20px;
"
>
Remove Persistent Remote Services
Disable SSH (Remove remote_services)
</button>
<button
onclick="
+5 -4
View File
@@ -2454,7 +2454,7 @@ async function removeRemoteServices(deviceId, ip) {
return;
}
const display = getDeviceDisplayName(deviceId);
if (!confirm("Are you sure you want to remove remote services from " + display + "?",)) {
if (!confirm("Remove the remote_services file from " + display + "? SSH will be disabled after the next reboot.")) {
return;
}
const summaryDiv = document.getElementById("migration-summary");
@@ -3772,9 +3772,10 @@ function caVerdict(summary) {
function remoteServicesVerdict(summary) {
if (!summary.ssh_success) return {icon: "❓", text: "Unknown", note: "(SSH not reachable)"};
if (!summary.remote_services_enabled) return {icon: "❌", text: "Not enabled", note: "(SSH/telnet shells will not survive a reboot until USB-stick unlock is reapplied)"};
if (!summary.remote_services_persistent) return {icon: "⚠️", text: "Enabled but not persistent", note: "(will be lost on reboot)"};
return {icon: "✅", text: "Persistent", note: ""};
if (!summary.remote_services_enabled) return {icon: "❌", text: "SSH not enabled", note: "(insert USB stick with remote_services file and reboot to enable)"};
if (!summary.remote_services_persistent) return {icon: "⚠️", text: "SSH enabled (not persistent)", note: "(will be lost on reboot — use 'Enable SSH' button to persist)"};
return {icon: "✅", text: "SSH enabled (persistent)", note: ""};
}
// parseTelnetVerifiedConfig extracts field values from the device's