Bundles the install-time hygiene work for issues #268 and #250. # Install location — #268 Stock SoundTouch rootfs has only a few MB free (~4 MB on the ST20 the reporter captured); the AfterTouch binary is ~12 MB. The previous flow downloaded into tmpfs (/media/aftertouch) and then `mv`'d the binary into /opt/aftertouch on rootfs — which fails with "No space left on device" on any speaker with the standard layout. install.sh now installs to /mnt/nv/aftertouch by default (the persistent partition, ~30 MB free on the same captures) and points /opt/aftertouch at it via a symlink so the init script's hardcoded DAEMON path keeps working unchanged. Power users can override with INSTALL_DIR=/some/other/path. The interactive prompt from the community patch in #268's thread is dropped — STDIN is the curl pipe under the documented `curl | sh` invocation, so a read prompt would hang or read garbage. uninstall.sh is updated to resolve the symlink and remove the target before unlinking, so the 12 MB binary doesn't get orphaned on /mnt/nv when users uninstall. # Logging — #250 Issue #250 surfaced a "running but unreachable" state: the install script reported AfterTouch as running, the init script's status agreed, but `curl :8000` returned connection-refused. start-stop- daemon's --background detaches stdout/stderr, so any panic the daemon emitted before dying went to /dev/null with no diagnostic trail. The fix is to route the daemon's stdout/stderr through `logger -t aftertouch` so output lands in BusyBox syslog — a bounded in-memory ring buffer that never grows on disk (writing to a file in /mnt/nv would have eaten the volume over months). Diagnostic flow is now: logread | grep aftertouch | tail -20 logread -f | grep aftertouch # live tail Matches the recipe already documented in TROUBLESHOOTING.md for the speaker's own logs (Curl 7 section). Tightening on top of the syslog change: - The init script's `status` case now also curls localhost:8000 when the PID is alive — distinguishes "PID alive, listener up" from "PID alive, listener silently died" (which is what fooled everyone on #250). A bare PID-liveness check returned "running" in both cases. - install.sh's post-install verification now does its own 10s curl probe after the init script returns; on failure it tails the aftertouch syslog so the user sees the actual error rather than the install script claiming success. - `exec` is added inside the start-stop-daemon's shell wrapper so --make-pidfile records the daemon's own PID (not the shell's), which keeps `stop` semantics correct. README updated to document the install location, INSTALL_DIR override, and the syslog tag. No automated tests — these are shell scripts the install pipeline runs once on the device. All three scripts pass `bash -n` / `sh -n` syntax checks. Real validation is end-user retest, gated on the next release. Refs #268, refs #250. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On-Device Installer
Allows to run AfterTouch on SoundTouch devices directly, eliminating the need to run and maintain a separate server on the local network.
Disclaimer
Invasiveness
AfterTouch usually normally migrates the SoundTouch devices very noninvasive, by changing the configuration of the device. Running AfterTouch on the device itself is slightly more invasive, because it needs to create a script that starts AfterTouch on boot.
AfterTouch Availability
Some devices will expose the AfterTouch port, some won't. We currently (May 2026) suspect that the newer generation devices (those with Bluetooth) will expose the port, while the older ones won't. We're still investigating how to expose AfterTouch on all devices.
If your device doesn't expose the port, you can still use the on-device installer, but you'll need to run AfterTouch on each one of your speakers individually and may only access AfterTouch via ssh port forwarding. This will also make OAuth authentication a little more tricky, but should also work via SSH port forwarding.
Space Limitation
The storage space on the SoundTouch devices is very limited — stock rootfs typically has only a few MB free (e.g. ~4 MB on the ST20, see issue #268), well below the AfterTouch binary's ~12 MB. To work around this, the installer puts everything on /mnt/nv/aftertouch by default (the persistent partition, typically ~30 MB free) and points /opt/aftertouch at it via a symlink so the init script and runtime paths stay unchanged. Override the install target with INSTALL_DIR=/some/path if you've got room elsewhere.
The space limitation also means we are currently unsure on how to update the system, because two binaries are already too large. We are currently working on this - both by checking how we can make the binaries smaller, but also on how we can extend the storage space (e.g. by running AfterTouch from a USB drive).
Logs
The daemon writes to BusyBox syslog (tagged aftertouch) rather than to a file. Disk usage stays bounded — the syslog ring buffer is in memory — and the same logread recipe used elsewhere in this project works:
logread | grep aftertouch | tail -20 # recent entries
logread -f | grep aftertouch # live tail
If the install command reports "running but :8000 not responding" or aftertouch status reports the listener is down, the syslog tail is the first place to look.
Installation
Enable SSH on your SoundTouch device using the usual "Stick with remote_services" method. Connect with the following command.
ssh -oHostKeyAlgorithms=+ssh-rsa root@<IP_ADDRESS_OF_SPEAKER>
Then, run the following command to install AfterTouch on the device.
rw && curl -sSL https://raw.githubusercontent.com/gesellix/Bose-SoundTouch/main/scripts/on-device-install/install.sh | sh
After the installation check if you can access AfterTouch from your local device by navigating to http://<IP_ADDRESS_OF_SPEAKER>:8000. If you can access the AfterTouch UI, you're good to go! If not, you may need to run AfterTouch on the speaker via SSH port forwarding.
ssh -L 8000:localhost:8000 root@<IP_ADDRESS_OF_SPEAKER>
Updating AfterTouch
To update AfterTouch, simply run the installation command again. The installer will check if there's a new version available and update it if necessary.
Uninstallation
Before uninstall, you might want to revert the migration, especially the changes to the server URLs (even though having configured an unresponsive local server probably is about as bad as having configured unresponsive Bose servers). To uninstall AfterTouch, run the following command on the speaker.
curl -sSL https://raw.githubusercontent.com/gesellix/Bose-SoundTouch/main/scripts/on-device-install/uninstall.sh | sh