Documentation for controlling and preserving Bose SoundTouch devices
This guide walks through the complete process of migrating your SoundTouch speakers from Bose’s cloud services to AfterTouch, the local replacement provided by soundtouch-service. By the end, your speakers will work fully independently of Bose’s servers.
For a shorter overview, see the Survival Guide. For safety considerations and rollback options, see the Migration & Safety Guide.
Choose the option that fits your setup.
go install github.com/gesellix/bose-soundtouch/cmd/soundtouch-service@latest
soundtouch-service
The service starts on port 8000. Open http://localhost:8000 in your browser.
The repository ships a docker-compose.yml ready for this use case. Clone or download it, copy the example config, then edit .env before starting:
cp .env.example .env
# Edit .env:
# SOUNDTOUCH_HOSTNAME=192.168.1.100 ← your server's address
# SOUNDTOUCH_VERSION=v0.70.0 ← pin to a release tag instead of 'latest'
docker compose up -d
SOUNDTOUCH_HOSTNAME is the address your speakers will use to reach the service — use a hostname or IP reachable from the speaker, not localhost.
On Linux (Debian, Proxmox VE, Raspberry Pi OS, etc.) you can enable host networking for automatic speaker discovery. Uncomment the network_mode: host line in docker-compose.yml and remove the ports: section (they conflict with host networking). Without host networking, add your speakers by IP address in Step 4 instead.
For local overrides (e.g. switching to build: . during development), create a docker-compose.override.yml — Docker Compose picks it up automatically and it is not tracked in version control.
Note on
docker-compose.ci.yml: this file contains mock services used only for automated integration tests. It is not needed for your own deployment.
docker run -d \
--name soundtouch-service \
--network host \
-v $(pwd)/data:/app/data \
ghcr.io/gesellix/bose-soundtouch:latest
docker run -d \
--name soundtouch-service \
-p 8000:8000 -p 8443:8443 \
-v $(pwd)/data:/app/data \
--env SERVER_URL=http://soundtouch.local:8000 \
--env HTTPS_SERVER_URL=https://soundtouch.local:8443 \
ghcr.io/gesellix/bose-soundtouch:latest
On macOS/Windows, device discovery via mDNS won’t work inside the container — you’ll add devices by IP address in Step 4.
See Raspberry Pi Setup and the SoundTouch Service Guide for more deployment options.
Open http://<server>:8000 and go to the Settings tab.

Set the Target Domain to the address your speakers can reach — for example https://soundtouch.fritz.box or http://192.168.1.100:8000. This must be the host’s address on your local network, not localhost.
If you plan to use DNS/DHCP redirect, enable the DNS Discovery Server and set the DNS Bind Address to :53. The upstream DNS should be your router’s IP, not the service’s own address.
Tip: If you change settings and they don’t seem to take effect, check
data/settings.json— settings saved in the UI take precedence over environment variables.
The wizard supports two transports for talking to the speaker. Pick whichever your device exposes:
The XML migration writes updated configuration to the speaker’s filesystem, which requires SSH access. Enable it once per device:
remote_services (no extension) in the root of the drive.ssh -oHostKeyAlgorithms=+ssh-rsa root@<SPEAKER-IP>You only need to do this once per speaker. SSH can remain enabled for future maintenance or be disabled after migration — your choice.
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.
Telnet-only migrations are limited to HTTP (no CA install possible without SSH). The wizard surfaces this clearly when it applies.
The service scans for SoundTouch devices automatically every few minutes. Check the Devices tab in the web UI. If your speaker doesn’t appear, click Scan Again to trigger an immediate scan, or enter the IP address manually and click Add Device.

Once the speaker appears, click Sync Data. This connects to the speaker and pulls its current presets, recently played items, and configured sources into the local service’s datastore. It also creates an off-device backup of the speaker’s configuration.

If the Bose cloud is still running, Sync also fetches your account data from Bose’s servers. This is your preservation step — do it before the cloud shuts down.
Click Migrate next to a device on the Devices tab to open the Migration tab. The tab opens with a Migration Summary that shows where your speaker currently stands, then offers a one-click suggested plan and a fully customizable form underneath.

Three rows tell you the speaker’s current state at a glance:
/etc/resolv.conf hook active.Trust CA Now and Download CA cert actions inline.remote_services persistence, account pairing state, and XML config backup presence.Below the state card is the Plan card. For most users this is the only thing you’ll touch:
/marge to margeServerUrl. URL validation runs on every keystroke.The wizard switches to a visible Pre-flight checks panel and runs every applicable verification before touching the speaker:
curl from the speaker to your service.:8090/swUpdateCheck on the device and watches for any request from the speaker to land on the service. Used when the speaker is already migrated and the service is the natural target of its outbounds.On all-green, the wizard auto-proceeds. On any failure, it pauses with Proceed Anyway / Cancel buttons so you can override on a known-false-positive (slow DNS, etc.) or fix the underlying issue and retry.
Expand the ▸ Customize this migration section to pick any combination of three independent axes:
/etc/resolv.conf hookEach option carries a per-axis availability hint (e.g. (SSH unreachable), (already trusted)) so you see why an option is disabled before you pick. Apply Custom Plan runs the chosen combination as a sequence; the same pre-flight panel gates the execution.
Note: DNS interception bundles the CA install on the backend, so a standalone CA-install step is skipped automatically when DNS is part of the plan. The wizard handles this for you.
After a successful Apply the wizard auto-expands the Customize section and highlights the Reboot Speaker button. Click it (or power-cycle the speaker manually) to apply all configuration changes. The reboot transport is picked automatically from your URL flip choice — telnet reboot for SSH-less speakers, SSH reboot otherwise.
After reboot:
If something doesn’t work, check the Interactions tab in the web UI for failed requests, and the Troubleshooting section in the SoundTouch Service Guide.
Each speaker is migrated independently. You can run multiple migrations in parallel, but migrating one at a time makes it easier to diagnose issues.
If you need to undo a migration:
.original backup files created on the speaker during the XML migration.sys configuration …) and the persistent layer (envswitch boseurls set …) so the migration survives reboot. If you want to revert quickly, the cleanest path is to re-run the wizard with the original Bose URLs in the URL editor..original suffix. Restore it manually if the UI is unreachable.Once all speakers are migrated, the data/ directory is the source of truth for your presets, recents, and device state. Back it up periodically. The web UI at http://<server>:8000 is your management interface from this point on.
For the Bose cloud backup you created in Step 4, keep the .tar.gz archive in case you need to restore credentials or presets later.