Self-contained boot-time Spotify primer that runs directly on the speaker. No Spotify credentials on the device — it fetches a fresh token from a soundcork server at boot.
No jq, no rootfs modification — just files on persistent storage.
Bose SoundTouch speakers run embedded Linux with a persistent writable volume
at /mnt/nv. The init script shelby_local (S97) has a built-in hook:
[ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local
This runs before SoundTouch itself (S99), so we background a primer script that waits for the Spotify Connect ZeroConf endpoint (port 8200) to come up, fetches a fresh Spotify token from soundcork, and primes the speaker — all within ~30 seconds of boot.
/mnt/nv/
rc.local boot hook (S97 checks this)
.profile PATH setup for interactive SSH
bin/
spotify-boot-primer main script
BoseApp-Persistence/1/
spotify-primer.conf soundcork credentials (mode 600)
Sources.xml, Presets.xml, ... existing speaker data
Scripts live in /mnt/nv/bin/ (added to PATH via .profile), config lives
alongside the speaker's own persistence files in /mnt/nv/BoseApp-Persistence/1/.
Tested on SoundTouch 20. Other SoundTouch models likely similar.
| Item | Detail |
|---|---|
| OS | Linux 3.14.43+ ARM (hostname spotty) |
| Root FS | Read-only ubifs (can be remounted rw) |
| Persistent storage | /mnt/nv — writable ubifs, ~24M free |
| curl | 7.50.3 with OpenSSL (HTTPS works) |
| bash/grep/sed/awk | Available via busybox |
| jq | Not available (not needed) |
| Init | SysV, runlevel 5 |
| Production mode | Yes — cron is disabled |
-
SSH access to the speaker:
ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa root@SPEAKER_IP -
A running soundcork server with:
- A linked Spotify account (via the management API OAuth flow)
- The
GET /mgmt/spotify/tokenendpoint (returns{accessToken, username}) - Management API credentials (HTTP Basic Auth)
SSH into the speaker and run:
# 1. Create bin directory
mkdir -p /mnt/nv/bin
# 2. Create the config file with your soundcork connection info
cat > /mnt/nv/BoseApp-Persistence/1/spotify-primer.conf << 'EOF'
SOUNDCORK_URL=https://soundcork.example.com
SOUNDCORK_USER=admin
SOUNDCORK_PASS=secret
EOF
chmod 600 /mnt/nv/BoseApp-Persistence/1/spotify-primer.conf
# 3. Copy spotify-boot-primer to the speaker (see file in this gist)
# From your local machine:
# cat spotify-boot-primer | ssh root@SPEAKER_IP "cat > /mnt/nv/bin/spotify-boot-primer"
chmod +x /mnt/nv/bin/spotify-boot-primer
# 4. Create the boot hook
cat > /mnt/nv/rc.local << 'EOF'
#!/bin/bash
/mnt/nv/bin/spotify-boot-primer &
EOF
chmod +x /mnt/nv/rc.local
# 5. Set up PATH for interactive SSH sessions (optional but convenient)
cat > /mnt/nv/.profile << 'EOF'
export PATH="/mnt/nv/bin:$PATH"
EOFIf activeUser is set but presets still fail, check spotify-primer logs for the activate-speaker step.
# Manual test (speaker must be running):
/mnt/nv/bin/spotify-boot-primer
# Check logs:
logread | grep spotify-primer
# Full test — reboot the speaker:
reboot
# Wait ~30s, then SSH back in and check:
logread | grep spotify-primer
curl -s "http://localhost:8200/zc?action=getInfo" | grep activeUserspotify-primer[1735]: Config loaded (server=https://soundcork.example.com)
spotify-primer[1735]: Waiting for ZeroConf endpoint (max 120s)...
spotify-primer[1735]: ZeroConf endpoint is up (waited 21s)
spotify-primer[1735]: Speaker 'Bose-Woonkamer' has no active Spotify user — priming...
spotify-primer[1735]: Requesting Spotify token from soundcork...
spotify-primer[1735]: Got token for user {username} (BQDUAb0_2h...)
spotify-primer[1735]: addUser accepted (status 101) — verifying...
spotify-primer[1735]: Speaker primed successfully (activeUser={username})
Speaker boot
|
v
shelby_local (S97) -- [ -x /mnt/nv/rc.local ] && /mnt/nv/rc.local
|
v SoundTouch (S99)
rc.local |
| v
+-- spotify-boot-primer & port 8200 up
| ^
+-- wait for port 8200 ------+
|
+-- GET soundcork/mgmt/spotify/token
| (HTTP Basic Auth)
|
+-- POST localhost:8200/zc
| action=addUser
|
v
Speaker primed for Spotify
- Added a post-prime activation call to soundcork:
POST /mgmt/spotify/activate-speaker?device_name=Bose
- Reason:
addUser(ZeroConf) can setactiveUserbut still leave the speaker in an idle/unselected Spotify state, causing SoundTouch presets to fail. - New behavior:
- Prime with ZeroConf (
addUser) - Verify
activeUser - Trigger activation via soundcork for more reliable preset playback
- Prime with ZeroConf (
- Activation failure is non-fatal: script logs a warning and exits
0(Spotify Connect priming still succeeded).
- The script is idempotent — if the speaker is already primed, it exits immediately
- No Spotify credentials stored on the speaker — only the soundcork URL and management credentials
- Soundcork handles all Spotify OAuth token refresh logic
- The speaker needs network access to reach your soundcork server
/mnt/nvholds all user presets/config, so firmware updates should preserve it — but back up your files just in case
- soundcork — Replacement Bose cloud server with Spotify support
- soundtouch-device-survival — Tools for keeping SoundTouch speakers alive
- Bose-SoundTouch — Comprehensive Go toolkit with migration automation
Good point about jq! I SSH'd into my SoundTouch 20 and explored what's available:
grep -o+sedcan parse the JSON we need/mnt/nvis a persistent writable volume (24.6M free, survives reboots)And the best part:
shelby_local(init.d script at S97) already has a hook:So we can drop a script in
/mnt/nv/rc.localand it runs at boot — no rootfs modification needed. SoundTouch itself starts at S99, so the script needs to background and wait for port 8200 to come up before priming.I'm going to try building a self-contained boot primer that:
/mnt/nv/Will report back whether it works. This could be a nice addition to the survival repo if it does.