If you want legacy ALSA clients and modern Pulse/PipeWire clients to play through the same audio server — for example inside WSL2 or a minimal Linux environment — these commands form a compact recipe. Below I’ll walk through what each line does and why it’s useful.
apt install -y alsa-utils pulseaudio-utils pipewire-bin libasound2-pluginsInstalls:
alsa-utils— ALSA command-line tools (aplay, etc.)pulseaudio-utils— PulseAudio clients (paplay,pactl, ...)pipewire-bin— PipeWire server + clients (pw-play,pw-cli, ...)libasound2-plugins— ALSA plugins, including the Pulse plugin that lets ALSA talk to Pulse/PipeWire.
paplay /usr/share/sounds/alsa/Noise.wavpaplay is a PulseAudio client. If Pulse (or PipeWire’s Pulse emulation) is reachable, this should play the test sound. If it fails, we proceed to bridge ALSA → Pulse.
Append this to ~/.asoundrc:
pcm.!default {
type pulse
fallback "sysdefault"
hint {
show on
description "PulseAudio Sound Server"
}
}
ctl.!default {
type pulse
fallback "sysdefault"
}
This tells ALSA clients that the default PCM and control devices are the PulseAudio plugin. Effect: apps that only know ALSA (e.g., aplay, old programs) will be routed into Pulse (or PipeWire’s Pulse compatibility layer) when available. The fallback "sysdefault" ensures ALSA still works if Pulse is not present.
aplay /usr/share/sounds/alsa/Noise.wavaplay is an ALSA client; with the .asoundrc above it should route through Pulse/PipeWire and produce the same noise.
Create an override for the PipeWire user unit(s):
systemctl --user edit pipewire
# then add:
[Unit]
ConditionUser=
systemctl --user edit pipewire-pulse.service
# then add:
[Unit]
ConditionUser=ConditionUser= clears the ConditionUser check from the unit (the override file produced by systemctl --user edit disables that particular condition). Some container-ish or WSL environments make the ConditionUser test fail (for example, if the user detection logic or expectations differ), which prevents pipewire or `pipewire-pulse
service from starting. Clearing it allows the unit to proceed under those environments. This is a targeted override — it doesn’t edit the packaged unit file, it adds an override fragment in your user configuration.
Then reload the unit files:
systemctl --user daemon-reloadwsl --shutdown
# then start your WSL instance again and run:
pw-play /usr/share/sounds/alsa/Noise.wavpw-play is a PipeWire-native player. In WSLg or other PipeWire-enabled setups it talks directly to PipeWire. wsl --shutdown forces the whole WSL VM to restart so the changed unit overrides and server restarts take effect.
- The
.asoundrcapproach is per-user and safe to revert by editing/removing the file. systemctl --user editcreates overrides under~/.config/systemd/user/— easy to inspect or remove later.- Clearing
ConditionUseris useful in environments where systemd’s unit conditions incorrectly block starting. It’s a conservative override but be mindful: unit conditions exist for reasons; only remove them when you understand the environment (WSL, containers, or nonstandard login daemons are common cases). - If sound still fails, check user logs:
journalctl --user -xeand query servers:pactl info(Pulse) orpw-cli info/pw-dump(PipeWire). Those commands show whether the server is running and which sinks/sources are available. - Use
pactl list short sinks(orpw-cliequivalent) to verify the active sink and volume.
- Install ALSA/Pulse/PipeWire tools and plugin.
- Test Pulse client (
paplay). - Route ALSA → Pulse via
~/.asoundrc. - Test ALSA client (
aplay). - If systemd user units are blocked by
ConditionUser, add an override to clear that condition and reload. - Restart WSL and test PipeWire directly with
pw-play.
You now have a small, practical pipeline so legacy ALSA apps, PulseAudio clients, and PipeWire-native tools can all coexist and play sound through the same server. Happy tinkering — the audio stack is oddly cooperative once you bribe it with the right config.