A step-by-step guide to turn a stock Kubuntu 26.04 LTS install into a low-latency audio workstation that can run Windows VST2 / VST3 / CLAP plugins in a native Linux DAW (REAPER, Bitwig, Ardour, etc.) through yabridge.
[!info] Assumptions - Fresh(ish) Kubuntu 26.04 LTS, 64-bit, default PipeWire audio stack. - Your user has
sudorights. - Commands are run in Konsole using bash. - Codename used below:$(lsb_release -sc)resolves automatically, so you don't need to type it.
1. Update the system
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y curl wget gpg software-properties-common lsb-release
Reboot if a new kernel was installed:
sudo reboot
2. Grant realtime privileges to your user
Audio threads need realtime scheduling priority and locked memory.
2.1 Add yourself to the audio group
sudo usermod -aG audio "$USER"
2.2 Set realtime limits for the audio group
sudo tee /etc/security/limits.d/95-audio.conf > /dev/null <<'EOF'
@audio - rtprio 95
@audio - memlock unlimited
@audio - nice -19
EOF
2.3 Make sure RTKit is present (PipeWire uses it for RT threads)
sudo apt install -y rtkit
[!note] Log out and back in (or reboot) for the group and limit changes to take effect.
Verify after logging back in:
groups | grep -w audio
ulimit -r # should print 95
ulimit -l # should print unlimited
3. Kernel: full preemption + threaded IRQs
Ubuntu's generic kernel supports PREEMPT_DYNAMIC, so you can switch it to full preemption at boot time instead of installing a separate low-latency kernel.
3.1 Add kernel parameters to GRUB
sudo cp /etc/default/grub /etc/default/grub.bak
sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 preempt=full threadirqs"/' /etc/default/grub
grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
sudo update-grub
sudo reboot
3.2 Verify after reboot
cat /proc/cmdline | tr ' ' '\n' | grep -E 'preempt|threadirqs'
sudo cat /sys/kernel/debug/sched/preempt # active mode is shown in (brackets), want: (full)
[!tip] Optional – Ubuntu Studio tooling If you prefer a GUI way to manage these tweaks,
sudo apt install ubuntustudio-installerand enable the audio/low-latency options from there. Don't apply both methods at once.
4. CPU & system tuning
4.1 Use the performance power profile
Prevents the CPU from down-clocking mid-buffer (a common cause of xruns).
powerprofilesctl list
powerprofilesctl set performance
To check the actual governor:
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor | sort | uniq -c
4.2 Lower swappiness
echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/99-audio.conf
sudo sysctl --system
4.3 Allow access to high-resolution timers (needed by some JACK/MIDI apps)
sudo tee /etc/udev/rules.d/40-timer-permissions.rules > /dev/null <<'EOF'
KERNEL=="rtc0", GROUP="audio"
KERNEL=="hpet", GROUP="audio"
EOF
sudo udevadm control --reload-rules && sudo udevadm trigger
5. Configure PipeWire for low latency
5.1 Install PipeWire's JACK + ALSA pieces
sudo apt install -y pipewire pipewire-audio pipewire-jack pipewire-alsa \
wireplumber qpwgraph pavucontrol
5.2 Route all JACK applications through PipeWire
This makes DAWs that use JACK talk to PipeWire automatically (no need to prefix pw-jack).
sudo cp /usr/share/doc/pipewire/examples/ld.so.conf.d/pipewire-jack-*.conf /etc/ld.so.conf.d/
sudo ldconfig
5.3 Set the sample rate and buffer size (quantum)
5.3.1 Profile your audio interface first
Before choosing rates, find out what your interface actually supports. List the cards:
cat /proc/asound/cards
aplay -l
For USB interfaces, the kernel exposes the supported formats and rates directly (replace 1 with your card number):
cat /proc/asound/card1/stream0
Look for the Rates: lines, e.g. Rates: 44100, 48000, 88200, 96000, 176400, 192000.
For any interface (USB or PCIe), ask ALSA for the hardware parameters. PipeWire holds the device open, so stop it briefly:
systemctl --user stop pipewire.socket pipewire-pulse.socket pipewire pipewire-pulse wireplumber
aplay -D hw:1,0 --dump-hw-params /dev/zero # playback (Ctrl+C after it prints)
arecord -D hw:1,0 --dump-hw-params /dev/null # capture (Ctrl+C after it prints)
systemctl --user start pipewire.socket pipewire-pulse.socket pipewire pipewire-pulse wireplumber
The RATE: line shows the supported range (e.g. [44100 192000]). The PERIOD_SIZE and BUFFER_SIZE lines show the smallest buffers the hardware accepts, which sets the lower limit for min-quantum.
5.3.2 Write the config using those values
Put only rates your interface reports in allowed-rates. If you add a rate it doesn't support, PipeWire has to resample instead of switching the hardware clock. The example below assumes an interface that goes up to 192 kHz:
mkdir -p ~/.config/pipewire/pipewire.conf.d
tee ~/.config/pipewire/pipewire.conf.d/10-lowlatency.conf > /dev/null <<'EOF'
context.properties = {
default.clock.rate = 48000
default.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 ]
default.clock.quantum = 256
default.clock.min-quantum = 64
default.clock.max-quantum = 2048
}
EOF
default.clock.rateis the rate PipeWire uses when nothing asks for another one. 48 kHz is a good default even if the interface can do 192 kHz: higher rates cost more CPU per second of audio, and many plugins (especially through Wine/yabridge) gain little from them.allowed-rateslets PipeWire switch the hardware to a project's native rate (e.g. a 96 kHz session) instead of resampling. This only works when a single app is using the device.
Latency ≈ quantum / rate:
| Quantum | 48 kHz | 96 kHz | 192 kHz |
|---|---|---|---|
| 64 | 1.3 ms | 0.7 ms | 0.3 ms |
| 128 | 2.7 ms | 1.3 ms | 0.7 ms |
| 256 | 5.3 ms | 2.7 ms | 1.3 ms |
| 1024 | 21.3 ms | 10.7 ms | 5.3 ms |
At higher rates, you need a larger quantum to get the same latency in milliseconds, which is why max-quantum is raised to 2048 above. Start at 256 and go down to 128 or 64 once things are stable. Don't go below the minimum period size --dump-hw-params reported.
Restart PipeWire:
systemctl --user restart pipewire pipewire-pulse wireplumber
5.4 Change the buffer size on the fly (no restart)
pw-metadata -n settings 0 clock.force-quantum 128 # force 128 frames
pw-metadata -n settings 0 clock.force-rate 48000 # force 48 kHz
pw-metadata -n settings 0 clock.force-quantum 0 # back to default
5.5 Monitor xruns and latency
pw-top
Watch the ERR column — it should stay at 0 while playing audio.
6. Check the setup with rtcqs
rtcqs scans the system for common realtime audio misconfigurations.
sudo apt install -y pipx
pipx ensurepath
source ~/.bashrc
pipx install rtcqs
rtcqs
Fix anything it flags as a warning before moving on.
7. Install Wine (Staging)
Yabridge works best with Wine Staging from WineHQ.
7.1 Enable 32-bit architecture
sudo dpkg --add-architecture i386
7.2 Add the WineHQ repository
sudo mkdir -pm755 /etc/apt/keyrings
wget -O - https://dl.winehq.org/wine-builds/winehq.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/winehq-archive.key -
sudo wget -NP /etc/apt/sources.list.d/ \
"https://dl.winehq.org/wine-builds/ubuntu/dists/$(lsb_release -sc)/winehq-$(lsb_release -sc).sources"
sudo apt update
[!warning] If the
wgetof the.sourcesfile returns 404 WineHQ hasn't published packages for 26.04 yet. Either use Ubuntu's own Wine instead:sudo apt install -y wine wine64 wine32:i386…or temporarily point at the previous LTS (
noble) repo by replacing$(lsb_release -sc)withnobleabove.
7.3 Install Wine Staging
sudo apt install -y --install-recommends winehq-staging
wine --version
7.4 (Optional) Pin a known-good Wine version
Newer Wine releases occasionally break plugin GUIs under yabridge. If you hit regressions, list the available versions and pin one:
apt list -a winehq-staging
# replace VERSION with an entry from the list above, e.g. 9.21~noble-1
VERSION="9.21~noble-1"
sudo apt install -y --allow-downgrades \
winehq-staging="$VERSION" wine-staging="$VERSION" \
wine-staging-amd64="$VERSION" wine-staging-i386:i386="$VERSION"
sudo apt-mark hold winehq-staging wine-staging wine-staging-amd64 wine-staging-i386
Undo the hold later with sudo apt-mark unhold winehq-staging wine-staging wine-staging-amd64 wine-staging-i386.
8. Create the Wine prefix and install common libraries
8.1 Install the latest winetricks
The distro version is often outdated, so grab the upstream script:
sudo apt install -y cabextract unzip p7zip-full zenity
mkdir -p ~/.local/bin
wget -O ~/.local/bin/winetricks \
https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
chmod +x ~/.local/bin/winetricks
8.2 Initialize a 64-bit prefix
export WINEPREFIX="$HOME/.wine"
wineboot -u
Click Install if Wine asks for Mono/Gecko.
8.3 Install the runtime libraries most VST plugins need
winetricks -q corefonts # Arial, Times etc. – fixes missing/ugly GUI text
winetricks -q vcrun2022 # Visual C++ 2015-2022 runtime (most modern plugins)
winetricks -q vcrun2019 vcrun2013 vcrun2010 vcrun2008 # older plugins/installers
winetricks -q d3dcompiler_47 # needed by many GPU-rendered GUIs (JUCE/OpenGL/DirectX)
winetricks -q gdiplus # GDI+ drawing for some older GUIs
winetricks -q msxml6 # some installers / licence managers
winetricks fontsmooth=rgb # sub-pixel font smoothing
[!tip] Optional – DXVK Some plugins with DirectX-based GUIs (e.g. certain Native Instructions / Arturia / iZotope versions) render better or only work with DXVK. Others break with it. Install only if you see black/blank plugin windows:
winetricks -q dxvkRemove with
winetricks -q d3d11=builtin d3d10core=builtin dxgi=builtin.
8.4 Wine settings worth checking
winecfg
- Graphics → Screen resolution (DPI): raise to 120–144 on HiDPI screens.
- Graphics: untick Allow the window manager to decorate the windows if plugin windows get KDE title bars.
9. Install yabridge
9.1 Download the latest release
cd /tmp
YABRIDGE_URL=$(curl -s https://api.github.com/repos/robbert-vdh/yabridge/releases/latest \
| grep -oP '"browser_download_url": "\K[^"]*yabridge-[0-9.]+\.tar\.gz')
echo "$YABRIDGE_URL"
wget -O yabridge.tar.gz "$YABRIDGE_URL"
Use the generic
yabridge-X.Y.Z.tar.gz, not the-ubuntu-20.04build — that one is only for old distros.
9.2 Extract it to ~/.local/share
rm -rf ~/.local/share/yabridge
tar -C ~/.local/share -xavf yabridge.tar.gz
9.3 Put yabridge on your PATH
echo 'export PATH="$HOME/.local/share/yabridge:$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
yabridgectl --version
9.4 Optional helper packages
sudo apt install -y libnotify-bin # desktop notifications on yabridge errors
10. Install Windows plugins and sync them with yabridge
10.1 Run the Windows plugin installer through Wine
cd ~/Downloads
wine ./SomePluginSetup.exe # .exe installers
wine msiexec /i ./SomePlugin.msi # .msi installers
Accept the default install paths (VST3 goes to C:\Program Files\Common Files\VST3).
10.2 Tell yabridge where the Windows plugins live
yabridgectl add "$HOME/.wine/drive_c/Program Files/Common Files/VST3"
yabridgectl add "$HOME/.wine/drive_c/Program Files/Common Files/CLAP"
yabridgectl add "$HOME/.wine/drive_c/Program Files/Steinberg/VstPlugins"
yabridgectl add "$HOME/.wine/drive_c/Program Files/VstPlugins"
(Only add folders that actually exist; yabridgectl list shows what's registered.)
10.3 Create the Linux bridge files
yabridgectl sync
yabridgectl status
yabridgectl status should report every plugin as synced, and the Wine + yabridge-host check should pass.
[!important] Re-run
yabridgectl syncevery time you install, update or remove a Windows plugin.
10.4 Point your DAW at the bridged plugins
| Format | Linux path to add in the DAW |
|---|---|
| VST2 | ~/.vst/yabridge |
| VST3 | ~/.vst3/yabridge |
| CLAP | ~/.clap/yabridge |
Most DAWs (REAPER, Bitwig, Ardour) scan ~/.vst3 and ~/.clap by default; VST2 usually needs ~/.vst added manually. Then rescan plugins.
In the DAW's audio settings select JACK (or PipeWire) as the audio system. Thanks to step 5.2 it will connect to PipeWire with your configured buffer size.
11. Troubleshooting
Plugin fails to load / crashes
export YABRIDGE_DEBUG_LEVEL=1
export YABRIDGE_DEBUG_FILE=/tmp/yabridge.log
reaper # or: bitwig-studio, ardour8 ... started from the same terminal
less /tmp/yabridge.log
Stuck Wine processes after a DAW crash
wineserver -k
pkill -f yabridge-host
Re-check realtime setup
rtcqs
pw-top
Per-plugin tweaks
Create yabridge.toml in the plugin folder (e.g. .../Common Files/VST3/yabridge.toml):
tee "$HOME/.wine/drive_c/Program Files/Common Files/VST3/yabridge.toml" > /dev/null <<'EOF'
# Run all plugins in this folder in one shared Wine process (less RAM, inter-plugin comms)
["*"]
group = "all"
# Example: fix a plugin whose GUI has mouse offset issues
["SomePlugin.vst3"]
editor_force_dnd = false
editor_coordinate_hack = true
EOF
yabridgectl sync
Quick checklist
- [ ] User in
audiogroup,ulimit -r= 95 - [ ] Kernel booted with
preempt=full threadirqs - [ ] Power profile = performance
- [ ] PipeWire quantum configured,
pw-topshows no xruns - [ ]
rtcqsclean - [ ] Wine Staging installed, prefix initialised
- [ ] winetricks: corefonts, vcrun2022, d3dcompiler_47, gdiplus
- [ ] yabridge on
PATH, plugin folders added,yabridgectl syncdone - [ ] DAW scanning
~/.vst/yabridge,~/.vst3/yabridge,~/.clap/yabridge
- Log in to post comments