Configuration Guide
SnapDog is configured using a single snapdog.toml file. The server parses this file at startup (defaults to /etc/snapdog/snapdog.toml, or specified via the --config CLI argument).
1. Global Keys
Section titled “1. Global Keys”name(String, default:"SnapDog") The display name of the audio controller server. Used as the default broadcast name formDNS, the base MQTT topic node, and system status listings.
2. Table Reference
Section titled “2. Table Reference”[system]
Section titled “[system]”Handles server execution settings, logging outputs, and local state directories.
log_level(String, default:"info") Sets logging verbosity. Options:trace,debug,info,warn,error.log_file(String, optional) Path to a local log file. If set, logs will rotate daily in addition to standard output.state_dir(String, default:platform-dependent) Directory where SnapDog saves state files like EQ configurations, current volume levels, and dynamic client mappings.- Defaults to
/var/lib/snapdogundersystemdor platform data folders (~/.local/state/snapdogon Linux,~/Library/Application Support/SnapDogon macOS).
- Defaults to
[audio]
Section titled “[audio]”Controls formatting and preemption rules for audio streams.
sample_rate(Integer, default:48000) Sets the target resampling frequency in Hz. All sources are resampled to this rate before encoding. Supported values:44100,48000,88200,96000,176400, or192000.bit_depth(Integer, default:16) PCM encoding bit depth. Options:16,24, or32bits.channels(Integer, default:2) Number of output channels (e.g.2for stereo,1for mono).source_conflict(String, default:"last_wins") Preemption rules when multiple sources try to play on the same zone:"last_wins": The newest request (e.g. starting a Spotify stream or manual radio click) overrides the active source."receiver_wins": AirPlay or Spotify Connect streams block any incoming Subsonic or radio play requests until the receiver stream stops.
zone_switch_fade_ms(Integer, default:300, max:1000) Fade duration in milliseconds when a SnapDog speaker switches between audio zones. Set to0to disable.source_switch_fade_ms(Integer, default:300, max:1000) Fade duration when changing the audio source (e.g., Radio → Spotify) within a single zone.
[http]
Section titled “[http]”Configures the REST API, WebSocket notifications, and static WebUI hosting.
port(Integer, default:5555) The TCP port on which the web server listens.bind(String, default:"::") Listen interface IP. The default::listens on IPv6 and, on dual-stack systems, IPv4 as well. Set"0.0.0.0"for IPv4-only all-interface binding or a concrete IP address for one interface.base_url(String, default:"http://localhost:5555") External base URL of the server (e.g.,http://192.168.1.50:5555orhttps://music.example.com). Used by integrations that need absolute URLs, such as MQTT discovery and some cover-art metadata.tls_cert(String, optional) Path to a PEM-formatted TLS certificate chain. Required together withtls_keyto activate HTTPS.tls_key(String, optional) Path to an unencrypted PEM TLS private key.api_keys(Array of Strings, optional) If configured, activates token authentication. REST requests useAuthorization: Bearer <key>; WebSocket connections to/wspass the same key as?token=<key>.api_docs(Boolean, default:true) Exposes the embedded Scalar API Reference UI dynamically athttp://<host>:<port>/docs. Only applicable if the binary was compiled with theapi-docsfeature flag.
[snapcast]
Section titled “[snapcast]”Manages the embedded Snapcast synchronizer backend.
address(String, default:"127.0.0.1") The hostname or IP address of the Snapcast server.jsonrpc_tcp_port(Integer, default:1705) TCP port used to communicate JSON-RPC control events.jsonrpc_portis accepted as an alias.streaming_port(Integer, default:1704) TCP port where Snapcast client devices connect to pull the encoded PCM audio data.codec(String, default:"flac") Streaming compression encoder. Options:"pcm","flac","f32lz4","f32lz4e"(encrypted floats).encryption_psk(String, optional) Pre-shared key (PSK) used to encrypt the stream whencodec = "f32lz4e"is active.group_volume_mode(String, default:"compressed") Defines how zone-level volume adjustments scale connected client speakers:"absolute": Changes the volume of all clients to match the zone volume."relative": Scales each client proportionally (client_vol * zone_vol / 100)."compressed": Soft relative scaling using a square-root curve, ensuring quiet clients do not drop too quickly.
managed(Boolean, default:true) If true, starts the built-in Rust snapcast server inside the daemon process.verbose(Boolean, default:false) Enables verbose console logging for the underlying Snapcast protocol encoder.unknown_clients(String, default:"accept") Action when an unconfigured MAC address connects:"accept": Admits the speaker and assigns it to thedefault_zone."ignore": Accepts connection but excludes the client from WebUI controls."reject": Drops connection immediately.
default_zone(String, optional) Name of the fallback zone to place new clients into. Defaults to the first defined zone.
[mdns]
Section titled “[mdns]”enabled(Boolean, default:true) Enables Bonjour/mDNS service advertisement.advertise_snapcast(Boolean, default:false) Additionally advertises the_snapcast._tcpservice type for discovery by generic Snapcast mobile apps.
[dbus]
Section titled “[dbus]”enabled(Boolean, default:true) Exposes the MPRIS2 audio control interface on Linux D-Bus.
[airplay]
Section titled “[airplay]”mode(String, default:"airplay2") AirPlay protocol compatibility:"airplay1"or"airplay2".password(String, optional) If set, requires verification to stream to the AirPlay receiver.bind(Array of Strings, optional) Restricts the AirPlay receiver to bind to specific network interfaces.
[spotify]
Section titled “[spotify]”name(String) Device name advertised to Spotify Connect clients.bitrate(Integer, default:320) Streaming bitrate. Options:96,160, or320kbps.
[subsonic]
Section titled “[subsonic]”url(String) URL of the Subsonic API endpoint (e.g. Navidrome or Gonic).username(String) Connection username.password(String) Connection password.format(String, default:"raw") Transcoding stream request format:"raw","flac","mp3", or"opus".tls_skip_verify(Boolean, default:false) Skips certificate checks for self-signed certificates.refresh_secs(Integer, default:60) Seconds between reads of the Subsonic playlist list. A change sends the WebSocket eventplaylists_changed. Subsonic cannot push, so a change made in another Subsonic client shows up within this interval. Each read is one request to the Subsonic server.0turns the background read off, the list is then only read on demand. A failed read keeps the last good list and logs a warning.playlist_write(Boolean, default:false) Lets the REST API create, rename, reorder and delete Subsonic playlists (POST,PATCH,PUTandDELETEunder/api/v1/media/playlists, see Media & Subsonic Playlists). Off by default: authentication is optional in SnapDog, so with this on anyone who can reach the API can change the playlists of your music library, within the rights of the Subsonic user above. The radio list in the configuration file is never writable through the API.
[subsonic.cache]
Section titled “[subsonic.cache]”path(String) Local folder for pre-caching track streams. Defaults to the platform cache directory (~/Library/Caches/SnapDog/trackson macOS,$XDG_CACHE_HOME/snapdog/tracksor~/.cache/snapdog/trackson Linux).max_size_mb(Integer, default:2048) Maximum size in MB before LRU track eviction occurs.
[mqtt]
Section titled “[mqtt]”broker(String) MQTT broker host and port (e.g.192.168.1.10:1883).client_id(String, default:"snapdog") Unique client ID.username(String, optional) Broker username.password(String, optional) Broker password.base_topic(String, default:"snapdog/") Base namespace path under which states are published and commands are received. A trailing slash is added automatically if omitted.
Playlist topics
Section titled “Playlist topics”The zone state (zones/<n>/state) carries playlist_index and playlist_id (null while no playlist is active). playlist_id is snapdog:radio or subsonic:<subsonic id> and stays valid when the list changes. playlist_index moves when a playlist is added or removed.
zones/<n>/playlist/set— takes the playlist index as a non-negative integer.zones/<n>/playlist/by-id/set— takes theplaylist_idas plain text, for examplesubsonic:42. An unknown id is logged and ignored.
Use playlist/by-id/set to select a playlist in a way that survives changes to the list. <n> is the 1-based position of the zone in snapdog.toml.
role(String, default:"client") KNX integration mode:"client"(connects to gateway tunnel) or"device"(registers as an ETS-programmable device). The older key namemodeis accepted as an alias.url(String, optional) Gateway connection URL (e.g.udp://192.168.1.50:3671).individual_address(String, optional) KNX individual address (e.g.1.1.100) for ETS programming.persist_ets_config(Boolean, optional) Saves ETS parameter changes to local persistent memory across restarts.start_prog_mode(Boolean, default:false) Starts with KNX physical programming mode enabled for ETS addressing.
3. Array Configuration Tables
Section titled “3. Array Configuration Tables”[[zone]]
Section titled “[[zone]]”Multiple zones can be defined using array of tables.
name(String) Unique name for the room (e.g."Living Room").icon(String, default:"🎵") Icon or emoji used in the WebUI.sink(String, optional) Manual override for the Snapcast audio sink path.airplay_name(String, optional) Override for the AirPlay receiver name.group_volume_mode(String, optional) Zone-specific override for[snapcast].group_volume_mode. Options:"absolute","relative", or"compressed".knx(Table, optional) Explicit group addresses for this zone. Supported keys includeplay,pause,stop,track_next,track_previous,control_status,volume,volume_status,volume_dim,mute,mute_status,mute_toggle, track metadata/status fields, playlist controls, shuffle/repeat controls, and presence controls. Unconfigured group addresses are ignored.presence(Table, optional) Presence-activated playback and auto-off settings.auto_off_delaydefaults to900seconds;default_sourceand schedule entrysourcevalues usenone,radio:<index>, orplaylist:<id>. Schedule entries usefromandtoin 24-hourHH:MMformat, and overlapping or overnight ranges are rejected.
[[client]]
Section titled “[[client]]”Defines output speaker hardware mapped to zones.
name(String) Friendly name for the speaker (e.g."Living Room Left").mac(String) Lowercase MAC address identifying the client device.zone(String) Initial zone mapping. Must match a defined[[zone]].name.icon(String, default:"🎵") Icon or emoji used in the WebUI.max_volume(Integer, default:100) Limits the maximum volume output (0-100) to protect speaker hardware.knx(Table, optional) Explicit group addresses for this client. Supported keys:volume,volume_status,volume_dim,mute,mute_status,mute_toggle,latency,latency_status,zone,zone_status, andconnected_status.
[[radio]]
Section titled “[[radio]]”Defines global internet radio streams.
name(String) Station name.url(String) Streaming source stream URL (supports direct links, M3U/PLS, and HLS).cover(String, optional) URL to a cover art image to display when this station is playing.
4. Environment Variable Overrides
Section titled “4. Environment Variable Overrides”The server applies these environment variables after loading snapdog.toml:
SNAPDOG_HTTP_PORT— Overrides[http].port.SNAPDOG_HTTP_API_KEYS— Comma-separated API keys replacing[http].api_keys.SNAPDOG_SUBSONIC_PASSWORD— Overrides[subsonic].passwordwhen Subsonic is configured.SNAPDOG_MQTT_PASSWORD— Overrides[mqtt].passwordwhen MQTT is configured.SNAPDOG_SNAPCAST_ENCRYPTION_PSK— Overrides[snapcast].encryption_psk.