Audio from Linux apps in an OrbStack VM routes over TCP to PulseAudio on macOS, which outputs via CoreAudio.
Linux app → PulseAudio client → TCP:4713 → PulseAudio server (macOS) → CoreAudio → speakers
brew install pulseaudioCreate ~/.config/pulse/daemon.conf:
# Don't exit when idle — keep running for OrbStack VM connections
exit-idle-time = -1
Create ~/.config/pulse/default.pa:
# Include the system default configuration
.include /opt/homebrew/etc/pulse/default.pa
# Allow TCP connections from OrbStack VMs (anonymous auth for local use)
load-module module-native-protocol-tcp auth-anonymous=1 listen=0.0.0.0 port=4713
load-module module-native-protocol-tcp auth-anonymous=1 listen=:: port=4713
The module is loaded twice — once for IPv4 (0.0.0.0) and once for IPv6 (::) — because OrbStack resolves host.orb.internal to an IPv6 address.
brew services start pulseaudioThis auto-starts PulseAudio on login. To manually restart:
brew services restart pulseaudiopactl info # should show server info
lsof -nP -iTCP:4713 # should show LISTEN on both IPv4 and IPv6sudo apt install pulseaudio-utils libpulse0echo "PULSE_SERVER=tcp:host.orb.internal:4713" | sudo tee -a /etc/environmentThis takes effect on next login. For the current shell:
export PULSE_SERVER=tcp:host.orb.internal:4713pactl info # should show Server Name: pulseaudio, Default Sink: 1__2# Play white noise for 1 second
paplay --raw /dev/urandom &
sleep 1
kill %1OrbStack sets SSH_CONNECTION in the environment, which causes peon to assume audio should not be played locally. Override this with:
peon ssh-audio localauth-anonymous=1 means any process that can reach port 4713 can play audio. This is fine for a local OrbStack setup but not suitable for shared networks. For stricter auth, use cookie-based authentication instead (copy ~/.config/pulse/cookie to the Linux VM and remove auth-anonymous=1).