Skip to content
Thaumic Cast

Run Thaumic Cast Server

Thaumic Cast Server is the desktop app with the window taken off, for the sort of computer that is kept in a cupboard and visited twice a year: a home server, a NAS, a Proxmox container. It does the same job, finding the speakers and serving them the audio, and every browser in the house can cast through it.

  • A Linux machine, x86_64 or arm64, with glibc 2.35 or newer (Debian 12, Ubuntu 22.04 and later). The installer needs systemd.
  • On the same network as the speakers, without NAT between them. The speakers fetch the audio from the server, so they must be able to reach it.
  • Incoming 49400/tcp allowed from your network, if the machine runs a firewall.
  1. Run the installer, as root or with sudo:

    Install or update
    curl -fsSL https://raw.githubusercontent.com/brew-lab/thaumic-cast/main/apps/server/install.sh | sudo bash

    It downloads the latest release and its checksum from GitHub, checks one against the other, creates a thaumic system user, installs the server with its config at /etc/thaumic-server/config.yaml, and starts the thaumic-server service. It talks to GitHub and to nothing else.

  2. Check it is running. Replace the address with the server’s own:

    Is it running?
    curl http://192.168.1.50:49400/health

    It answers with JSON that includes "status":"ok" and "appType":"server". To see the speakers it found:

    Speakers it found
    curl http://192.168.1.50:49400/api/speakers
  3. Point the extension at it. In the extension’s Settings, under Companion, choose Enter the address, type http://192.168.1.50:49400 (the server’s address), and select Connect. Your browser asks whether the extension may use that address; say yes. More in Use an app on another computer.

The top of the popup now says Connected to the server.

Pass them after bash -s --, for example ... | sudo bash -s -- --check.

Option What it does
--check Shows the installed and the latest version, and changes nothing.
--version X.Y.Z Installs a particular release.
--tarball PATH Installs from a release tarball you downloaded, with no network.
--no-start Installs without starting the service, so you can edit the config first.
--uninstall Removes the service and the server, and keeps the config and data.
--purge With --uninstall: removes the config, the data and the user too.

Without the internet on that machine, download thaumic-server-vX.Y.Z-linux-x64.tar.gz (or -linux-arm64) from the download page, copy it over, unpack it, and run the installer inside it:

Install from a tarball
tar -xzf thaumic-server-vX.Y.Z-linux-x64.tar.gz
sudo bash thaumic-server-vX.Y.Z-linux-x64/install.sh --tarball thaumic-server-vX.Y.Z-linux-x64.tar.gz
The service
sudo systemctl status thaumic-server
journalctl -u thaumic-server -f
sudo systemctl edit thaumic-server # your own changes, kept across updates

To update, run the installer again: see Update Thaumic Cast.

Use an LXC container, not a VM. The server is one program with no kernel modules to load, and a container shares the host’s bridge, so finding the speakers works without arranging anything.

On the Proxmox host, as root, this creates an unprivileged Debian 12 container and runs the installer inside it:

Create a Proxmox container
curl -fsSL https://raw.githubusercontent.com/brew-lab/thaumic-cast/main/apps/server/proxmox-lxc.sh -o proxmox-lxc.sh
BRIDGE=vmbr0 bash proxmox-lxc.sh

Set BRIDGE (and VLAN, if any) to wherever your speakers are. It uses the next free container id, the hostname thaumic-cast, DHCP, 1 core, 512 MB and 4 GB on local-lvm; each gives way to a variable, for example CTID=120 IP=192.168.1.50/24 GATEWAY=192.168.1.1 VLAN=20 STORAGE=local-zfs bash proxmox-lxc.sh. At the end it prints the container’s address, the root password if you did not set PASSWORD, and the command to update it later.

Setting a container up by hand? Debian 12, unprivileged, with the nesting feature on, attached to the speakers’ bridge; then run the installer inside it. Without nesting, the installer skips the service’s sandbox, says so, and puts it back when you turn nesting on and run it again.

There is no published image: build one from a copy of the source, from the top of the repository.

Build and run
git clone https://github.com/brew-lab/thaumic-cast.git
cd thaumic-cast
docker build -f apps/server/Dockerfile -t thaumic-server .
docker run -d --name thaumic-server --restart unless-stopped \
--network host \
-e THAUMIC_ADVERTISE_IP=192.168.1.50 \
-v thaumic-data:/var/lib/thaumic-server \
thaumic-server

The installer writes /etc/thaumic-server/config.yaml, with every setting described in it. The server reads it once, when it starts: restart it after a change (sudo systemctl restart thaumic-server).

Setting Default What it does
bind_port 49400 The port the extension and the speakers connect to.
advertise_ip Worked out The address the speakers are told to fetch from. Set it on a machine with more than one network (a VPN, Docker, two cards), to the address the speakers can reach.
data_dir None; the installer’s service sets /var/lib/thaumic-server Where speakers added by IP address are kept. Without it, none can be added.
topology_refresh_interval 30 Seconds between checks on how the speakers are grouped.
artwork_url None A picture for the Sonos app to show while casting. An HTTPS address works best.
speaker_monitor true Asks each speaker how much audio it has in reserve; the speaker notices come from this.
pcm_connect_burst_ms 500 The speaker head start, 0 (off) to 2000 ms. Raise it if one speaker cuts out. PCM casts only.
drift_compensation on Clock drift correction: on, observe (work it out and log it, change nothing) or off. Needs speaker_monitor.
strict_stream_access false Refuses audio fetches from addresses a cast is not playing on. Turn it on only once the log shows no unexpected addresses: a wrongly refused fetch is silence, with nothing to explain it.

speaker_monitor, pcm_connect_burst_ms and drift_compensation are the same as the desktop app’s Speakers settings: see Advanced audio settings. The extension shows the server’s head start as “set in the server’s config”.

Each setting can also come from an environment variable or a flag. A flag beats an environment variable, which beats the config file, which beats the default.

Flag Environment variable
-c, --config <FILE> None
-p, --port <PORT> THAUMIC_BIND_PORT
-a, --advertise-ip <IP> THAUMIC_ADVERTISE_IP
-d, --data-dir <DIR> THAUMIC_DATA_DIR
-l, --log-level <LEVEL> THAUMIC_LOG_LEVEL (error, warn, info, debug, trace)
--speaker-monitor <on|off> THAUMIC_SPEAKER_MONITOR
--pcm-connect-burst-ms <MS> THAUMIC_PCM_CONNECT_BURST_MS
--drift-compensation <on|observe|off> THAUMIC_DRIFT_COMPENSATION
--strict-stream-access <BOOL> THAUMIC_STRICT_STREAM_ACCESS
--topology-refresh-interval <SECS> THAUMIC_TOPOLOGY_REFRESH_INTERVAL
--artwork-url <URL> THAUMIC_ARTWORK_URL

The server’s README lists a few more variables, for experiments and tests. They are not settings; leave them alone.

The least trouble is the same network as the speakers. Another subnet works too, provided traffic is routed both ways and either your router passes mDNS between the subnets (an Avahi reflector, UniFi’s mDNS setting and the like), or you add the speakers by IP address. The server has no window to do that in, so ask it directly:

Add a speaker by IP address
curl -X POST http://192.168.1.50:49400/api/speakers/manual \
-H 'Content-Type: application/json' -d '{"ip":"192.168.20.10"}'

It is kept in data_dir, and asked again on every refresh. One speaker is enough: the server asks it for the rest of your Sonos system.