Georg Krause

coding - music - building stuff

Ardour on NixOS with Wayland


Last year I had to take over the maintenance of about 30 NixOS servers at work. To make it easier for me to handle this and to force me learning more about the distribution, I switched the operating system of my work device to NixOS as well.

After some weeks I loved it so much, I radically migrated all the systems I could to nixos as well. Its just way too great to test some cli tool with the temporary nix shell that just goes away if I don't like the tool. Its way too great to jump into whatever project and have a well defined environment available with the specific tools installed. Its way too great to have all this without the overhead a container introduces...

But back to our topic, since I make some music, I occasionally need Ardour. Its my default digital audio workstation, its great, stable, does not change the interface every month and is linux native.

However, I had some issues using it on NixOS. The interface was freezing whenever I tried to open it. It seemed super random to me. Later I learned it only happens if the cursor is moved at the wrong time. So I could work around the freeze, but it wasn't nice.

After some investigation I learned that wayland is the issue. Ardours interface is implemented in GTK2, which does not and never will support wayland. So the solution is xwayland or similar. I had it installed, but it did not work out of the box. Maybe this is because my .zshrc sets GDK_BACKEND=wayland.

However, NixOS provides a cool workaround for issues like this: A wrapper. We basically mirror the Ardour package using symlinks but replace the binary with a wrapper script that calls the binary after applying some magic:

{
  environment.systemPackages = [
    # Ardour is a GTK2 app with no Wayland backend. Since GDK_BACKEND=wayland
    # is set globally, force x11 (XWayland) here so its GUI reliably shows up.
    (pkgs.symlinkJoin {
      name = "ardour";
      paths = [ pkgs.ardour ];
      nativeBuildInputs = [ pkgs.makeWrapper ];
      postBuild = ''
        wrapProgram $out/bin/ardour9 \
          --set GDK_BACKEND x11 \
      '';
    })
  ];
}

Now I was able to use Ardour with alsa, which is fine. However, I prefer pipewire/jack because I can still use normal desktop audio even if Ardour is running. Ardour can use Pipewire as audio backend if the jack-bridge is running. Thats easy:

{
    services.pipewire.jack.enable = true;
}

This way Ardour can talk to Pipewire as if it was a Jack server. In theory. But because we are running NixOS and Ardour is built against normal jack it wouldn't load pipewires libjack.so unless we tell it to do so. Luckily the wrapper is already set up and I can just add a tiny line of code:

{
  environment.systemPackages = [
    # Ardour is a GTK2 app with no Wayland backend. Since GDK_BACKEND=wayland
    # is set globally, force x11 (XWayland) here so its GUI reliably shows up.
    (pkgs.symlinkJoin {
      name = "ardour";
      paths = [ pkgs.ardour ];
      nativeBuildInputs = [ pkgs.makeWrapper ];
      postBuild = ''
        wrapProgram $out/bin/ardour9 \
          --set GDK_BACKEND x11 \
          --prefix LD_LIBRARY_PATH : ${pkgs.pipewire.jack}/lib
      '';
    })
  ];
}

Now Ardour works well enough for now on NixOS and Sway. I am sure I am going to extend my module over time.