Admin & Setup console: migration, settings, accounts, and diagnostics.

## Welcome to AfterTouch

This toolkit helps you keep your Bose SoundTouch speakers functional even after the Bose Cloud shutdown in May 2026. It emulates the necessary cloud services locally on your network.

### Migration Process at a Glance

🔌 Speaker shell access
The wizard talks to the speaker over one of two transports. The Migration tab probes both automatically and uses whichever your device exposes — you don't have to choose manually.

- SSH (richest option — required for the XML migration, the `/etc/resolv.conf` DNS hook, and installing the local CA). Enable it by creating an empty `remote_services` file on a USB stick, inserting it into the speaker's SERVICE port, and rebooting. Verify on the Migration tab — SSH in the state card's Transports row should show ✅ Reachable. Manual check: `ssh -oHostKeyAlgorithms=+ssh-rsa root@<SPEAKER-IP>` (no password).
- Telnet (Port 17000) — the SSH-less fallback. Most SoundTouch firmware exposes a diagnostic shell on TCP/17000 automatically, no USB-stick setup required. Limited to HTTP migrations (no CA install possible without SSH). The state card surfaces this in the same Transports row.

1. Settings: Review the Settings tab. Ensure the "Target Domain" and "Proxy Domain" use an IP address or domain name that is accessible from your speakers (usually the IP of this server on your local network). You can also edit the Target URL directly from the Migration tab with a Save as default button.
2. Discovery: Go to the Devices tab to find your speakers on the network. Ensure your speakers are powered on and connected to the same network.
3. Data Sync: In the Data Sync tab, fetch your current presets, recents, and sources. This step is critical to ensure your local service has all your personalized data before you disconnect from the Bose cloud.
4. Migration: In the Migration tab the wizard offers a one-click Apply Suggested Plan that picks the right recipe for your speaker (XML over SSH when SSH is available, telnet URL flip otherwise). For mix-and-match across the three independent axes — URL flip transport, DNS interception, CA install — expand Customize this migration. A visible pre-flight check runs before any backend operation touches the speaker.
5. Verification: After migration and reboot, your speaker will communicate with this toolkit instead of Bose servers.

⚠️ Safety First: Before starting any migration, please read our Professional Migration & Safety Guide. The toolkit automatically creates backups, but understanding the process is key to a smooth transition.

### Useful Links

- Cloud Shutdown Survival Guide
- CLI Reference

## System Settings

Data directory: `-`

Service URLs

Note: These URLs must be accessible from your SoundTouch devices. Use the IP address of this server on your local network (e.g., `http://192.0.2.100:8000`) rather than `localhost`.

Target Domain: (Standard services URL)
HTTPS URL: `—` ⓘ

AfterTouch's HTTPS endpoint is only needed for certain features — the DNS-based redirect, music-service (Spotify/Amazon) login, and certificate trust. When you use them, its URL is derived from the Target Domain above by default (same host, on the HTTPS port), so you normally don't set anything here. If you don't need plain HTTP at all, you can set the Target Domain itself to an `https://` URL and it's used as the HTTPS endpoint as-is. Otherwise, set an override only when a reverse proxy serves HTTPS on a different host or port. Leave it empty to derive automatically. Takes effect after saving.

Override:
Landing page (`/`):
What a browser sees at the root URL. The Player and Admin pages stay reachable at `/app` and `/admin` either way.
Admin area login:
Today, only Spotify/Amazon linking and the Local Account tab require login (the same credentials as `MGMT_USERNAME`/`MGMT_PASSWORD`). This setting extends that login to the entire admin area — Overview, Devices, Settings, Migration, Health, Logs. A future release is expected to make this the default; set it to "Keep the admin area open" now if you want to opt out ahead of that. See issue #419 for background. Requires non-default management credentials to enable.
TLS extra hosts: ⓘ
When you need this: rarely. The TLS certificate already covers AfterTouch's configured server URL, HTTPS URL, and the host's own name. Add entries here only when a speaker can't reach AfterTouch over TLS — typical symptoms include presets resetting on reboot, the BoseApp showing the speaker as offline, or `CURLE_SSL_CACERT (60)` in the speaker syslog.
How to tell: open the Health tab and look for `speaker_marge_url` warnings. Each warning names the host a speaker is pointing at; clicking the Add <host> to TLS hosts QuickFix fills this list for you. If that check is clean, this list can stay empty.
Manual path: add one host per line and save. The TLS certificate is regenerated at startup from the merged list of `--server-url` host, `--https-server-url` host, the system hostname, any `--tls-extra-host` / `TLS_EXTRA_HOST` CLI/env values, and the hosts persisted here. CLI/env wins over persisted on overlap.
Applying changes requires a service restart.
Usually empty. Add a host here only if the Health tab flags a `speaker_marge_url` warning — or use the one-click QuickFix on that warning to fill it for you.
Device Discovery:
Enable Periodic Discovery
Discovery Interval: ⓘ
Go duration syntax: a number followed by a unit, optionally combined (e.g. `5m`, `90s`, `1h30m`).
Units: `h` (hours), `m` (minutes), `s` (seconds).
Update Check:
Check GitHub for new releases
Check Interval: ⓘ
Go duration syntax: a number followed by a unit, optionally combined (e.g. `24h`, `90m`, `1h30m`, `45s`).
Units: `h` (hours), `m` (minutes), `s` (seconds).
Makes one unauthenticated GET request to api.github.com per interval when enabled. No other data leaves this install. Applies live, no restart needed — takes effect within a minute (worst case).
DNS Discovery:
Enable DNS Discovery Server
Upstream DNS: ⓘ
Optional: comma-separated list of DNS servers (e.g., `1.1.1.1, 8.8.8.8`).
If empty, AfterTouch defaults to the system nameservers (e.g. from `/etc/resolv.conf`).
DNS Bind Address: (e.g., :53 or 0.0.0.0:53. Port 53 is required for actual migration)
Integrations:
Spotify …
Client ID:
Client Secret:
Redirect URI:
Checking configuration...
Amazon Music …
Client ID:
Client Secret:
Redirect URI:
Checking configuration...
Google Cloud TTS …
Text-to-speech for speaker announcements. The translate provider needs no credentials; google-cloud needs an API key. Either way, an app key is required to play on the speaker (see the Speaker endpoint docs).
Provider:
Google API Key:
Speaker app_key:
Default language:
Default voice:
Default volume:
Checking configuration...
Logging:
Redact Sensitive Headers Log Bodies Record Interactions(View in 5. Interactions tab)
Internal Paths (skip recording for these patterns):
Requests matching these patterns will be excluded from recording. Use one pattern per line.
Root CA Certificate:
Import this certificate into your OS or browser trust store to trust HTTPS connections to this AfterTouch server from other clients (e.g. curl, Python scripts, browsers).

## Known Devices 🔍 Scanning...

Spotify: Not Linked
Loading devices...

## Initial Data Sync

Before migrating, fetch your presets, recents, and configured sources from the device to ensure they are available locally.

Device:

### Sync Results

## Device Migration

Device:

### Command Output

### Migration Summary for

Migration Status:

#### Transports

SSH:
Telnet (Port 17000):

#### Migration State

URL Configuration |
DNS Interception |
CA / TLS | Download CA cert

#### Preconditions

SSH (remote_services) |
Account paired |
XML config backup |

#### Speaker controls

#### Pre-flight checks

Cross-check warnings:

HTTPS Connection Test:
Verify the device can reach the server over HTTPS.
URL: ``
Preliminary DNS Test:
Verify the device can resolve domains via the AfterTouch DNS server.
Domain: `aftertouch.test`

### Plan

Target service URL:

#### Capabilities

This speaker exposes:
AfterTouch can offer:

#### Service URLs

Pre-filled from the target URL above. Edit any field for advanced setups (e.g. soundcork users append `/marge` to `margeServerUrl`). These overrides apply to both XML and Telnet migrations.

Field | Current on Device | Target URL
--- | --- | ---
margeServerUrl | — |
statsServerUrl | — |
swUpdateUrl | — |
bmxRegistryUrl | — |

Soundcork mode (append `/marge` to `margeServerUrl`)

#### Account pairing

—

Account ID:

#### Suggested plan

Customize this migration

Pick any combination of the three axes — the wizard runs the matching backend operations in order. Disabled options require a transport this speaker doesn't expose.

URL flip transport XML over SSH Telnet (Port 17000) Skip — leave URLs at the Bose cloud (DNS interception will redirect them instead)
DNS interception None `/etc/resolv.conf` hook (also installs the local CA — needed when URLs stay at `https://*.bose.com`)
Local CA install Install local root CA on the device via SSH (only needed when targeting `https://`)

#### Telnet Migration (Port 17000)

Drives the speaker's diagnostic shell over TCP/17000. Requires no SSH access. Works on most ST 10/20/300 and Wave III/IV firmware (27.0.6.x).

Limitation: HTTP-only redirection — telnet has no way to install a custom CA. If you need end-to-end TLS, use the XML or DNS method instead.

Current Config (on Speaker)

Planned Config (AfterTouch)

⚠️ Hostname resolution warning:
The planned IP shown above may be incorrect. Migration methods that write IPs to the device (hosts, resolv.conf) will refuse to proceed until the hostname can be resolved from the device itself. Learn more →
Current /etc/resolv.conf

Planned /etc/resolv.conf Hook

Note: This method injects a persistent DNS priority hook into the DHCP logic (`/etc/udhcpc.d/50default`). It preserves your router's search domain and secondary DNS servers. It also injects the Local Root CA.

## Recorded Interactions & Device Events

Analysis of traffic handled by this service (self), proxied to Bose (upstream), and internal device events (telemetry).

Total Requests: 0

Keeps only the 10 most recent sessions

### By Service

### Sessions

### Browse Recordings

Session:
Category:
Since (YYYY-MM-DD HH:mm:ss):

# | Time | Method | Path | Status | Category | Event Details | Action
--- | --- | --- | --- | --- | --- | --- | ---
No interactions found.

### DNS Discoveries

Hosts discovered via the AfterTouch DNS server. "Self" means the domain was intercepted and redirected to this service.

Hostname | Last Seen | Queries | Bose? | Category | Last Client IP
--- | --- | --- | --- | --- | ---
No DNS discoveries found.

### Recording Viewer:

### App & Device Events

Time | Type | Data
--- | --- | ---
Select a device to view events.

## Local Account Details

Account:

### Account Overview

Loading...

### Spotify Integration

Register a new Spotify source for this local account. This mimics the official SoundTouch app flow:

1. Exchange OAuth code for a Bose-mediated token.
2. Register the source in the local Marge cloud profile.

### Amazon Music Integration

Register a new Amazon Music source for this local account. This mimics the official SoundTouch app flow:

1. Exchange OAuth code for an Amazon LWA token.
2. Register the source in the local Marge cloud profile.

### Connected Devices

Select an account to view devices.

## Service Health Checks

Runs a set of checks against the local datastore and flags findings that may need attention. Quick fixes are offered for issues the service knows how to remediate.

Share a diagnostic snapshot with the project maintainer.
What does the diagnostic report contain?

- Health check results and current device state
- Device XML files from the datastore (no passwords)
- HTTP response samples from speaker endpoints
- System files: CA bundle, DNS resolver config
- Speaker CA bundle and kernel log (via SSH, if reachable)
- Service log tail
- Settings file with secrets redacted

The archive is encrypted with the project maintainer's public key — only they can open it.

Loading…

## Service Logs

Follow tail

Live mirror of the service's stderr log. Stderr still receives every line — this is a read-only view for convenience.

Idle.