DEV Community

viraj-sh
viraj-sh

Posted on Fully Autonomous

Running pywebview on NixOS with a single shell.nix

How to run pywebview (Qt backend) on NixOS.

Why

pywebview's Qt backend uses prebuilt wheels (PyQt6 + QtWebEngine). On NixOS they can't find the shared libraries they expect, so the libraries have to be exposed through LD_LIBRARY_PATH.

The shell.nix below includes everything QtWebEngine/Chromium needs, so it works on a fresh NixOS install with nothing else installed.

shell.nix

{ pkgs ? import <nixpkgs> { } }:

let
  runtimeLibs = with pkgs; [
    # Base
    stdenv.cc.cc.lib
    zlib
    zstd
    brotli

    # GL / graphics
    libGL
    libglvnd # libEGL
    libgbm
    libdrm
    vulkan-loader

    # Wayland / input
    wayland
    libxkbcommon

    # X11
    libx11
    libxext
    libxrandr
    libxcomposite
    libxdamage
    libxfixes
    libxrender
    libxi
    libxcursor
    libxtst
    libxkbfile
    libxshmfence

    # xcb
    libxcb
    libxcb-util
    libxcb-cursor
    libxcb-wm
    libxcb-image
    libxcb-keysyms
    libxcb-render-util

    # GTK stack / fonts
    glib
    gtk3
    gdk-pixbuf
    pango
    cairo
    atk
    at-spi2-atk
    harfbuzz
    fontconfig
    freetype

    # QtWebEngine / Chromium
    dbus
    expat
    nss
    nspr
    cups
    alsa-lib
    libpulseaudio
    krb5
    icu
    libpng
    libjpeg
    libwebp
    libxml2
    libxslt
    lcms2
    libopus
    libevent
    minizip
    snappy
  ];
in
pkgs.mkShell {
  packages = [ pkgs.uv ];

  LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath runtimeLibs;

  # --pure sets this to a nonexistent file, which breaks httpx
  SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";

  QTWEBENGINE_DISABLE_SANDBOX = "1";
  PYWEBVIEW_GUI = "qt";
}
Enter fullscreen mode Exit fullscreen mode

What the non-obvious bits do:

  • LD_LIBRARY_PATH: makes the libs above visible to the pip wheels
  • SSL_CERT_FILE: only needed with nix-shell --pure, otherwise httpx breaks
  • QTWEBENGINE_DISABLE_SANDBOX: the Chromium sandbox doesn't work here, so it's disabled
  • PYWEBVIEW_GUI=qt: forces the Qt backend

Usage

nix-shell
uv init
uv add "pywebview[qt]"
uv run main.py
Enter fullscreen mode Exit fullscreen mode

main.py

import webview

webview.create_window("Hello", "https://example.com")
webview.start()
Enter fullscreen mode Exit fullscreen mode

Top comments (0)