Kde-linux: how to: google-chrome-beta in kapsule container: hardware accelerated and with sound

Getting google-chrome-beta to function in KDE Linux wasn’t easy: I document here the steps to do so if other people are interested.
Maybe someone here knows an easier way?

I have always run google-chrome-beta on my linux computers
but flathub doesn’t serve that (only stable and unstable).

So when I installed KDE Linux last week I was very curious about Kapsule ( Install Software Not Available in Discover - KDE Linux ). Chrome is not a command-line tool but I managed to install it in a Kapsule container not without big thanks to AI Gemini.
If I would have had to search forums manually for this it would have taken months.

Getting instructions from gemini for video hardware accelerated in chrome wasn’t difficult,
but getting sound working in chrome was a big PITA with gemini throwing every possible solution at me and I was getting desperate until it suggested a working solution (after 19 other non working solutions).

Kapsule can create containers from images from https://images.linuxcontainers.org/ but it can also create them from kapsule’s own custom repo: images · master · KDE Linux / Kapsule · GitLab : it has archlinux and kapsule-dev images.
I used kapsule’s archlinux: “Arch Linux optimized for Kapsule”.

In KDE Linux in konsole:

kap create kaps-arch-chrome --image kapsule:archlinux --nvidia-drivers
(nvidia driver injection is disabled by default)

Don’t run “kapsule enter” (or “kap enter”) because that creates a container named container based on the default image archlinux from https://images.linuxcontainers.org/.

kap enter kaps-arch-chrome

inside the container:
vat@kaps-arch-chrome ~ % sudo pacman -Syu --needed base-devel git
the -u flag does a full system upgrade of the container

vat@kaps-arch-chrome ~ % sudo usermod -aG wheel vat

Group changes are not applied instantly to your active terminal session. To activate the new permissions, you must do one of the following:
Log out and log back in to your user session (or restart the container).
Reload your group membership immediately in your current terminal window without logging out by running:
newgrp wheel
You can then verify it worked by typing “groups” or the command “id”.

Allow the user to build packages:
vat@kaps-arch-chrome ~ % sudo visudo
uncomment the line %wheel ALL=(ALL:ALL) ALL

Clone and build the package:
vat@kaps-arch-chrome ~ % git clone ``https://aur.archlinux.org/google-chrome-beta.git
vat@kaps-arch-chrome ~ % cd google-chrome-beta
vat@kaps-arch-chrome ~/google-chrome-beta (git)-[master] % makepkg -is
the home directory of your user in the host system is shared to the container.

Because Chrome is running in a minimal container environment, execute it using the Ozone Wayland native flag to ensure it uses hardware acceleration properly under KDE’s KWin compositor:
vat@kaps-arch-chrome ~ % google-chrome-beta --password-store=basic --enable-features=UseOzonePlatform --ozone-platform=wayland
Chrome requires a secure backend (like KWallet on KDE) to encrypt saved passwords. KWalletManager is being retired in favor of KeepSecret, so I use the Basic Password Store.

How to enable hardware GPU video acceleration for this containerized Chrome browser to reduce high CPU utilization:
To shift resource-heavy media decoding from your CPU to your physical graphics card inside a containerized Chrome instance, you must configure a GPU passthrough on the host engine and install matching VA-API acceleration video drivers inside the Kapsule jail.
Because containers isolate process environments, Chrome cannot see your host’s graphics card by default, dropping back to a high-CPU software emulation loop (llvmpipe).

kap stop kaps-arch-chrome
use the Incus backend driver commands to map your host’s physical GPU device hardware mapping keys straight into your container context:
incus config device add kaps-arch-chrome myfirstgpu gpu

Match the Host’s NVIDIA Driver Version Inside the Container
For NVIDIA hardware acceleration to work, the user-space libraries inside the container must exactly match the kernel driver version running on your host.
Check your host driver version by running this on your host:
nvidia-smi
NVIDIA-SMI 610.43.02

Enter your container as root:
incus exec kaps-arch-chrome -- bash

[root@kaps-arch-chrome ~]# pacman -Syu --print --needed nvidia-utils libva-nvidia-driver libva-utils
shows urls of all packages that it wants to install
the version of nvidia-utils should be the same as you nvidia driver on the host
the version of libva-utils should be the same as the one on the host

How to check version of libva and libva-utils of your host:
vainfo

On an immutable system like KDE Linux, the host system does not actually have a separate libva-nvidia-driver package installed.
The official design architecture of KDE Linux pre-bakes the proprietary NVIDIA user-space files directly into the read-only core system image. Because of this, video decoding tasks are handled natively by the built-in NVIDIA drivers, rather than a standalone community wrapper like libva-nvidia-driver.

now really install it:
[root@kaps-arch-chrome ~]# pacman -Syu --needed nvidia-utils libva-nvidia-driver libva-utils

For AMD GPUs:
pacman -Syu --needed mesa-vdpau libva-mesa-driver libva-utils

[root@kaps-arch-chrome ~]# pacman -Q nvidia-utils libva-nvidia-driver libva-utils
nvidia-utils 610.43.02-2
libva-nvidia-driver 0.0.17-1
libva-utils 2.23.0-1

Verify the setup inside the container: Run vainfo. If configured successfully, it will display a text summary table outlining supported profiles (such as VAEntrypointVideoProcessor).
[root@kaps-arch-chrome ~]# vainfo

exit the container and enter it again with
kap enter kaps-arch-chrome
Chrome enforces strict security sandboxing that often isolates the browser process from newly mapped Unix device nodes (like /dev/dri/renderD128). You must pass a sandbox bypass argument and explicit Linux decoding instructions.
vat@kaps-arch-chrome ~ % google-chrome-beta --password-store=basic --disable-gpu-sandbox --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --ignore-gpu-blocklist --enable-features=UseOzonePlatform --ozone-platform=wayland

Verify Full Hardware Acceleration in chrome://gpu :
Video Decode: Hardware accelerated
Compositing: Hardware accelerated

Critical note: if nvidia-smi inside the container throws an error after installing, it means your host kernel driver is slightly older or newer than what pacman just installed. If that happens, you must download the exact matching .run driver installer from NVIDIA’s website inside the container and run it using the --no-kernel-modules flag.
Or you can use the Arch Linux Archive: find on https://archive.archlinux.org/ in repository extra the version of nvidia-utils and libva you need in your container.

When kde-linux updates its nvidia driver version, i assume i will then have to update the packages nvidia-utils, libva-nvidia-driver and libva-utils of my kapsule container to the same versions?
Yes, you are exactly right. When KDE Linux updates its core system image with a newer NVIDIA driver version, you will need to update the packages inside your Kapsule container to keep them in perfect sync.

If the host driver version updates but the container remains on the old version, nvidia-smi inside the container will throw a “Driver/library version mismatch” error, and Chrome will immediately drop back to high-CPU software rendering (llvmpipe).

If the latest archlinux has a newer version of nvidia than the nvidia of KDE Linux, you can install an intermediate, specific version in your container from the Arch Linux Archive.
I chose to use the Snapshot Mirror Method to freeze my container’s entire universe to a single date: when the whole container is locked to a specific date, the dependencies and the drivers stay frozen together naturally.

vat@kaps-arch-chrome ~ % sudo vi /etc/pacman.d/mirrorlist
#Server = ``https://geo.mirror.pkgbuild.com/$repo/os/$arch
# I commented the line above and added this line below
Server = ``https://archive.archlinux.org/repos/2026/06/27/$repo/os/$arch

When KDE Linux has a new image with a newer version of nvidia, I will check in latest archlinux if their latest version of nvidia is the same version. If the nvidia version of the new KDE Linux image is not the latest version, I will search in the Arch Linux Archive for the date repo that has the nvidia version that I want and the libva version.
Then I will change the mirrorlist of my container to that date repo.

How to sharing audio channels via pipewire from the kapsule container to the host?
Google Chrome on Linux does not natively understand PipeWire raw streams—it expects a standard PulseAudio server link. Because you are inside a lightweight Arch container, you must install the translation wrapper that tells Chrome how to talk to your host’s integrated PipeWire socket.

incus exec kaps-arch-chrome -- pacman -Syu --needed pipewire pipewire-pulse libpipewire
pipewire-pulse: Essential fallback layer. It ensures that standard PulseAudio applications (like Google Chrome) can automatically talk to the PipeWire socket without crashing.
The pipewire-pulse package deploys an automated background daemon loop. It catches standard PulseAudio requests coming from applications like Chrome and converts them instantly into PipeWire-native instructions.

vat@kaps-arch-chrome ~ % env PULSE_SERVER=unix:$XDG_RUNTIME_DIR/pulse/native google-chrome-beta --password-store=basic --disable-gpu-sandbox --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --ignore-gpu-blocklist --enable-features=UseOzonePlatform --ozone-platform=wayland

sound should now play from youtube videoclips from chrome.

vi ~/.local/share/applications/kapsule-chrome-beta.desktop :
[Desktop Entry]
Version=1.0
Type=Application
Name=Google Chrome Beta (Kapsule)
Comment=Launch Chrome securely inside an Arch Linux container
Exec=kapsule enter kaps-arch-chrome -- env PULSE_SERVER=unix:$XDG_RUNTIME_DIR/pulse/native google-chrome-beta --password
-store=basic --disable-gpu-sandbox --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --ignore-gpu-blocklist --enable
-features=UseOzonePlatform --ozone-platform=wayland %u
Icon=/home/vat/google-chrome-beta/pkg/google-chrome-beta/usr/share/icons/hicolor/48x48/apps/google-chrome-beta.png
Terminal=false
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
StartupWMClass=google-chrome-beta

chmod +x ~/.local/share/applications/kapsule-chrome-beta.desktop

Force KDE Plasma to Refresh the Cache
KDE Plasma caches application launcher entries. If the icon doesn’t update immediately, force a system database refresh using the terminal:

kbuildsycoca6

Once the cache updates, open your application launcher menu. Your Google Chrome Beta launcher will immediately read the targeted icon graphic

If you want to drag files from dolphin to Google Drive in Chrome: copy the files in the shared home directory.

Also whenever I want the latest version of google-chrome-beta,
I will move in my home folder the folder google-chrome-beta to google-chrome-beta-150.0.7871.46 and make a new package in the container and install it.

Also some Core Architecture Insights from Gemini:

  • Privileged Sockets Boundary: Privileged containers share the host’s namespaces. Using an Incus proxy device with bind=container or bind=instance on a live host socket causes a device or resource busy conflict because Incus attempts to overwrite the host’s active file descriptor. Standard directory bind mounts (disk type) must be used instead.
  • Systemd Over-mounting: Arch Linux container base images use systemd, which mounts a fresh, empty volatile tmpfs RAM disk over /run/ and /tmp/ at boot time. Any directory created or mounted there prior to boot gets entirely wiped out or buried.
  • XDG_RUNTIME_DIR & Kapsule: Kapsule automatically maps the user’s graphical and runtime paths (including a working audio bridge) under $XDG_RUNTIME_DIR during interactive logins (kapsule enter). Running direct bash -c string flags straight from the host breaks this environment initialization cycle.
  • Chrome Audio Protocols: Chrome on Linux completely lacks raw PipeWire stream routing capabilities. It relies heavily on PulseAudio. Without the pipewire-pulse translation package inside the container, Chrome ignores the mapped sockets, falls back to a broken ALSA driver channel loop, and goes completely silent.

I know this isn’t really relevant to your eventual solution, but what about bash -ic ? That should source the same profile files that are sourced for an interactive shell.

Or bash -ilc to reflect what happens on an interactive login shell.

you have to take it up with Gemini which let me run all those commands that I barely understood.

e.g.
kapsule enter kaps-arch-chrome --bash -c "PULSE_SERVER=unix:/mnt/pulse/native google-chrome-beta --password-store=basic --disable-gpu-sandbox --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --ignore-gpu-blocklist --enable-features=UseOzonePlatform --ozone-platform=wayland"
did not make chrome appear.

and Gemini answered with:
The reason running kapsule enter with a bash -c string fails to launch Chrome is that Kapsule’s internal graphic rendering links only activate during an interactive TTY session.

As shown in the official Kapsule system design specifications, when you execute a raw command string through kapsule enter, it completely bypasses the interactive login lifecycle scripts. This leaves your visual window display manager (Wayland/XDG_RUNTIME_DIR) uninitialized inside that specific process branch, so Chrome cannot build its window and fails immediately.

Since you proved that entering the container interactively first via kapsule enter allows Chrome to initialize its window, we just need to fix why the sound isn’t passing through when launched that way.