I am almost embarrassed to say that I missed a good night's sleep sifting through erroneous out of date misinformation, missing some subtle distinctions, and winnowing out the chafe.
This all started when I wanted to give Krita a try for editing photographs. It is said it is the next best thing in open source when compared to PhotoShop. When installed on my Debian Linux workstation, all I could get out of it was crashes of one form or another. I'm not really surprised as my workstation has been through various combinations of buster, testing, bullseye, sid and experimental. Some package is out of sync somewhere.
So.. since I know how to run LXC containers, I figured I'd give that a try. That was successful, to a point. I used X2Go for remote console. But when my images are Nikon NEF files at 24Megapixels at 14bits each, file size, computation, and visualization are a bit of challenge (the screen updates being the main challenge). A wide erasure brush was slow, even on my speedy machine.
There are sites which vehemently say that there is no direct way to see the GUI from a container on a workstation host. Sigh. Misinformation. Then there are the five year old sites which show how it is done, but have extra commands, missing commands, or missing options. More sigh.
After much trial and error and trying the same things over again, with minor variations on the theme, in the hopes something might fix itself, it was a long night.
For the record, here is my research on a Debian Bullseye system with LXC '1:3.1.0+really3.0.4-3'
This is where it all starts, LXC Guru Stéphane Graber talking about it six years ago with these four lines in the container configuration file:
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file
Only one of those lines is actually needed for the GUI side, and, for modern installs, the one line causes grief.
On a properly functioning system, here are some diagnostic commands for what things should look like on the host.
host $ ls -alt /tmp/.X11-unix/
total 44
drwxrwxrwt 20 root root 36864 May 23 14:49 ..
drwxrwxrwt 2 root root 4096 May 23 06:24 .
srwxrwxrwx 1 root root 0 May 23 06:24 X0
host $ ls -lhtra /tmp/.X11-unix
total 44K
srwxrwxrwx 1 root root 0 May 23 06:24 X0
drwxrwxrwt 2 root root 4.0K May 23 06:24 .
drwxrwxrwt 20 root root 36K May 23 14:49 ..
host $ xvinfo
X-Video Extension version 2.2
screen #0
Adaptor #0: "GLAMOR Textured Video"
number of ports: 16
port base: 63
operations supported: PutImage
supported visuals:
depth 24, visualID 0x21
number of attributes: 5
"XV_BRIGHTNESS" (range -1000 to 1000)
client settable attribute
client gettable attribute (current value is 0)
"XV_CONTRAST" (range -1000 to 1000)
client settable attribute
client gettable attribute (current value is 0)
"XV_SATURATION" (range -1000 to 1000)
client settable attribute
client gettable attribute (current value is 0)
"XV_HUE" (range -1000 to 1000)
client settable attribute
client gettable attribute (current value is 0)
"XV_COLORSPACE" (range 0 to 1)
client settable attribute
client gettable attribute (current value is 0)
maximum XvImage size: 8192 x 8192
Number of image formats: 2
id: 0x32315659 (YV12)
guid: 59563132-0000-0010-8000-00aa00389b71
bits per pixel: 12
number of planes: 3
type: YUV (planar)
id: 0x30323449 (I420)
guid: 49343230-0000-0010-8000-00aa00389b71
bits per pixel: 12
number of planes: 3
type: YUV (planar)
host $ env |grep -i display=
DISPLAY=:0
host $ stat /tmp/.X11-unix/X0
File: /tmp/.X11-unix/X0
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 10303h/66307d Inode: 128522 Links: 1
Access: (0777/srwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-05-23 06:24:33.183848488 -0600
Modify: 2020-05-23 06:24:33.183848488 -0600
Change: 2020-05-23 06:24:33.183848488 -0600
Birth: -
host $ netstat -lnp |grep -i x11
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
unix 2 [ ACC ] STREAM LISTENING 30371 - /tmp/.X11-unix/X0
unix 2 [ ACC ] STREAM LISTENING 30370 - @/tmp/.X11-unix/X0
The last command, the netstat, shows a primary diagnostic. The line with the @ symbol, based upon commands at
StackExchange,
says:
Xorg listens on both /tmp/.X11-unix/X0 in the filesystem and /tmp/.X11-unix/X0 on the abstract namespace (generally written @/tmp/.X11-unix/X0). From strace, X11 applications seem to now use that abstract namespace by default, which explains why those still work if /tmp/.X11-unix is removed, while ssh doesn't use that abstract namespace.
In additional words, the first line is a regular UNIX domain socket, and the second line is an abstract namespace socket. The distinction is important.
If you put the following line into your container configuration file ...
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir
... you will be rewarded with the following in the container (note the sarcasm due to the missing X0):
host $ ls -lhtra /tmp/.X11-unix
total 4.0K
drwxrwxrwt 2 root root 4.0K May 23 22:14 .
drwxrwxrwt 1 root root 94 May 23 22:15 ..
And depending upon how badly things get messed up, it may actually also disappear from the host as well (it happens when the container is shutdown). Troubleshooting Sequence. And then a display manager or the machine will need to be restarted. The crazy thing is that the directory looses the X0, but the ports are still being listened. So with the X0 missing in the directory, the bind won't work.
host # netstat -lnp |grep -i x11
unix 2 [ ACC ] STREAM LISTENING 30371 1342/Xorg /tmp/.X11-unix/X0
unix 2 [ ACC ] STREAM LISTENING 30370 1342/Xorg @/tmp/.X11-unix/X0
host # ls -lhatr /tmp/.X11-unix
total 44K
drwxrwxrwt 20 root root 36K May 23 14:49 ..
drwxrwxrwt 2 root root 4.0K May 23 16:17 .
The single proper config line is:
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir,ro
The 'ro' prevents systemd from doing strange things in the background on container startup (affects container) and shutdown (affects host).
Additional helpful configuration file items (for a root based start):
lxc.environment = XAUTHORITY=/root/.Xauthority
While at the host prompt, figure out the current X11 Magic-Cookie (which is used for the GUI in the container to talk to the xserver of the host, which changes on each login):
host $ xauth list
mymachine/unix:0 MIT-MAGIC-COOKIE-1 6f5268c58be5a667b9668d822dc336bb
Once the container has been created (lxc-create) and started (lxc-start), it can be attached (lxc-attach), and X11 can be installed (xserver-xorg and xinit are not needed as they are accessed via the UNIX socket):
root@container:/# apt install \
--no-install-recommends \
xserver-xorg-core \
xauth \
x11-apps x11-utils
A new user should be created in the container, but I'll do the following with root as a quick trial:
root@container:/# env |grep DISPLAY
DISPLAY=:0
root@container:/# export XAUTHORITY=/root/.Xauthority
root@container:/# touch ${XAUTHORITY}
root@container:/# xauth add ${DISPLAY} MIT-MAGIC-COOKIE-1 6f5268c58be5a667b9668d822dc336bb
root@container:/# xauth list
container/unix:0 MIT-MAGIC-COOKIE-1 6f5268c58be5a667b9668d822dc336bb
root@container:/# xclock
And a clock should appear in the host's window space!
The end result is that I was able to install Krita in a specific/protected environment, and it functioned at native window speeds, in native/host GUI window space. Now the question is how to apply the GPU to the container without having to resort to LXD syntax.
Further references:
Based upon LXC GPU Passthrough, I should be able to GPU passthrough with my card:
ls -l /dev/dri
total 0
drwxr-xr-x 2 root root 80 May 23 16:28 by-path
crw-rw----+ 1 root video 226, 0 May 23 16:29 card0
crw-rw----+ 1 root render 226, 128 May 23 16:28 renderD128
With placement in to the containers configuration file:
lxc.cgroup.devices.allow = c 226:* rwm
lxc.mount.entry = /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
lxc.mount.entry = /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
From Radeon GPU "Passthrough" with LXC help needed provides a few diagnostic hints:
# lspci|grep -i vga
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Polaris 22 XT [Radeon RX Vega M GH] (rev c0)
# ls -l /dev/dri/by-path/
total 0
lrwxrwxrwx 1 root root 8 May 23 16:29 pci-0000:01:00.0-card -> ../card0
lrwxrwxrwx 1 root root 13 May 23 16:28 pci-0000:01:00.0-render -> ../renderD128
# ls -l /dev/dri
total 0
drwxr-xr-x 2 root root 80 May 23 16:28 by-path
crw-rw----+ 1 root video 226, 0 May 23 16:29 card0
crw-rw----+ 1 root render 226, 128 May 23 16:28 renderD128
To confirm that GL programs work:
apt install mesa-utils
glxgears