Container with LXC/LXD (5)

Date: 2023/11/15 (initial publish), 2024/02/23 (last update)

Source: en/note-00056.md

Previous Post Top Next Post

TOC

Here is a series of memos of me trying to use LXC/LXD on Debian 12 (bookworm).

YAML to allow IPCs for Wayland + X + sounds

Here is a YAML data example (waylandx.yaml) to add disk device for many IPC sockets supporting Wayland + X + sounds.

config:
  boot.autostart: false
  raw.idmap: both 1000 1000
  security.nesting: "true"
  user.user-data: |
    #cloud-config
    users:
    - name: osamu
      lock_passwd: True
      groups: [adm, audio, cdrom, dialout, dip, floppy, plugdev, sudo, video]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
    write_files:
    - path: /usr/local/bin/mystartup.sh
      permissions: 0755
      content: |
        #!/bin/sh
        uid=$(id -u)
        run_dir=/run/user/$uid
        mkdir -p $run_dir && chmod 700 $run_dir && chown $uid:$uid $run_dir
        mkdir -p $run_dir/pulse && chmod 700 $run_dir && chown $uid:$uid $run_dir
        mkdir -p /tmp/.X11-unix && chmod 700 /tmp/.X11-unix && chown $uid:$uid /tmp/.X11-unix
        for f in \
          wayland-0 wayland-0.lock \
          pipewire-0 pipewire-0.lock \
          pulse/native \
          ; \
        do
          ln -sf /mnt/runuser/$f $run_dir/$f
        done
        ln -sf /mnt/tmp/.X11-unix/X0 /tmp/.X11-unix/X0
    - path: /usr/local/etc/mystartup.service
      content: |
        [Unit]
        After=local-fs.target
        [Service]
        Type=oneshot
        ExecStart=/usr/local/bin/mystartup.sh
        [Install]
        WantedBy=default.target
    runcmd:
    - mkdir -p /home/osamu/.config/systemd/user/default.target.wants
    - ln -s /usr/local/etc/mystartup.service /home/osamu/.config/systemd/user/default.target.wants/mystartup.service
    - ln -s /usr/local/etc/mystartup.service /home/osamu/.config/systemd/user/mystartup.service
    - chown -R osamu:osamu /home/osamu
    - echo 'export WAYLAND_DISPLAY=wayland-0' >> /home/osamu/.profile
    - echo 'export XDG_SESSION_TYPE=wayland'  >> /home/osamu/.profile
    - echo 'export QT_QPA_PLATFORM=wayland'   >> /home/osamu/.profile
    - echo 'export DISPLAY=:0'                >> /home/osamu/.profile
    - echo 'export XAUTHORITY=$(echo /mnt/runuser/.mutter-Xwaylandauth.*)' >> /home/osamu/.profile    
description: Wayland+X+sound LXD profile
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: /
    pool: default
    type: disk
  gpu:
    type: gpu
    gid: 44
  runuser:
    source: /run/user/1000
    path: /mnt/runuser/
    type: disk
  X0:
    source: /tmp/.X11-unix/X0
    path: /mnt/tmp/.X11-unix/X0
    type: disk

NOTE: I don’t know if lock files as above work well or not.

Here, I used information on my host system as below.

 $ echo $XAUTHORITY
/run/user/1000/.mutter-Xwaylandauth.VC1EF2
 $ getent group video
video:x:44:osamu

I am using the primary user name osamu in the container.

Running X GUI application xeyes in container

 $ lxc profile create waylandx
 $ lxc profile edit waylandx < waylandx.yaml
 $ lxc profile ls
+----------+-----------------------------+---------+
|   NAME   |         DESCRIPTION         | USED BY |
+----------+-----------------------------+---------+
| default  | Default LXD profile         | 3       |
+----------+-----------------------------+---------+
| wayland  | Wayland LXD profile         | 1       |
+----------+-----------------------------+---------+
| waylandx | Wayland+X+sound LXD profile | 0       |
+----------+-----------------------------+---------+

Let me create template waylandx0 instance with waylandx profile

 $ lxc init images:debian/12/cloud waylandx0 --profile waylandx

Let me inspect this instance. (We need to expand to see effective configuration settings.)

 $ lxc config waylandx0 -e
architecture: x86_64
config:
  boot.autostart: "false"
  image.architecture: amd64
  image.description: Debian bookworm amd64 (20231124_05:24)
  image.os: Debian
  image.release: bookworm
  image.serial: "20231124_05:24"
  image.type: squashfs
  image.variant: cloud
  raw.idmap: both 1000 1000
  security.nesting: "true"
  user.user-data: |
    #cloud-config
    users:
    - name: osamu
      lock_passwd: True
      groups: [adm, audio, cdrom, dialout, dip, floppy, plugdev, sudo, video]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
    write_files:
    - path: /usr/local/bin/mystartup.sh
      permissions: 0755
      content: |
        #!/bin/sh
        uid=$(id -u)
        run_dir=/run/user/$uid
        mkdir -p $run_dir/pulse && chmod -R 700 $run_dir && chown -R $uid:$uid $run_dir
        mkdir -p /tmp/.X11-unix && chmod 700 /tmp/.X11-unix && chown $uid:$uid /tmp/.X11-unix
        ln -sf /mnt/runuser/wayland-0 $run_dir/wayland-0
        ln -sf /mnt/runuser/pipewire-0 $run_dir/pipewire-0
        #ln -sf /mnt/runuser/.mutter-Xwaylandauth.VC1EF2 $run_dir/.mutter-Xwaylandauth.VC1EF2
        ln -sf /mnt/runuser/pulse/native $run_dir/pulse/native
        ln -sf /mnt/tmp/.X11-unix/X0 /tmp/.X11-unix/X0
    - path: /usr/local/etc/mystartup.service
      content: |
        [Unit]
        After=local-fs.target
        [Service]
        Type=oneshot
        ExecStart=/usr/local/bin/mystartup.sh
        [Install]
        WantedBy=default.target
    runcmd:
    - mkdir -p /home/osamu/.config/systemd/user/default.target.wants
    - ln -s /usr/local/etc/mystartup.service /home/osamu/.config/systemd/user/default.target.wants/mystartup.service
    - ln -s /usr/local/etc/mystartup.service /home/osamu/.config/systemd/user/mystartup.service
    - chown -R osamu:osamu /home/osamu
    - echo 'export WAYLAND_DISPLAY=wayland-0' >> /home/osamu/.profile
    - echo 'export XDG_SESSION_TYPE=wayland'  >> /home/osamu/.profile
    - echo 'export QT_QPA_PLATFORM=wayland'   >> /home/osamu/.profile
    - echo 'export DISPLAY=:0'                >> /home/osamu/.profile
    - echo 'export XAUTHORITY=$(echo /mnt/runuser/.mutter-Xwaylandauth.*)' >> /home/osamu/.profile
  volatile.base_image: 03e51acc22a673de40cf411923bebc3215bea394cf828cafabb6b61925fd722f
  volatile.cloud-init.instance-id: 0370e577-15a0-4eed-a6b8-04932fa98f84
  volatile.eth0.host_name: veth2db8d385
  volatile.eth0.hwaddr: 00:16:3e:6e:bf:b7
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":232073,"Nsid":1001,"Maprange":9999000},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":232073,"Nsid":1001,"Maprange":9999000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":232073,"Nsid":1001,"Maprange":9999000},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":232073,"Nsid":1001,"Maprange":9999000}]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 9071439f-ceaa-4350-8137-7537b2991d50
devices:
  X0:
    path: /mnt/tmp/.X11-unix/X0
    source: /tmp/.X11-unix/X0
    type: disk
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  gpu:
    gid: "44"
    type: gpu
  root:
    path: /
    pool: default
    type: disk
  runuser:
    path: /mnt/runuser/
    source: /run/user/1000
    type: disk
ephemeral: false
profiles:
- waylandx
stateful: false

Let’s start with a fresh waylandx instance.

 $ lxc delete waylandx -f || lxc copy wayland0 waylandx
 $ lxc start waylandx
 $ lxc exec waylandx -- apt install x11-apps
 ...
 $ lxc exec waylandx -- sudo -u osamu -i xeyes

Now xeyes works.

Running mesa-utils GUI application in container

Let’s start with a fresh waylandx instance.

 $ lxc delete waylandx -f || lxc copy wayland0 waylandx
 $ lxc start waylandx
 $ lxc exec waylandx -- apt install mesa-utils
 ...
 $ lxc exec waylandx -- sudo -u osamu -i glxgears
Running synchronized to the vertical refresh.  The framerate should be
approximately the same as the monitor refresh rate.
301 frames in 5.0 seconds = 60.105 FPS
296 frames in 5.0 seconds = 59.122 FPS
299 frames in 5.0 seconds = 59.661 FPS
296 frames in 5.0 seconds = 59.025 FPS
X connection to :0 broken (explicit kill or server shutdown).
 $ lxc exec waylandx -- sudo -u osamu -i glxheads
glxheads: exercise multiple GLX connections (any key = exit)
Usage:
  glxheads xdisplayname ...
Example:
  glxheads :0 mars:0 venus:1
Name: :0
  Display:     0x555b946171b0
  Window:      0x1600002
  Context:     0x555b94633370
  GL_VERSION:  4.6 (Compatibility Profile) Mesa 22.3.6
  GL_VENDOR:   AMD
  GL_RENDERER: AMD Radeon Graphics (renoir, LLVM 15.0.6, DRM 3.54, 6.5.0-0.deb12.1-amd64)
 $ lxc exec waylandx4 -- sudo -u osamu -i es2gears_wayland
EGLUT: failed to initialize native display
 $ lxc exec waylandx -- sudo -u osamu -i es2gears_x11
EGL_VERSION = 1.5
vertex shader info:
fragment shader info:
info:
302 frames in 5.0 seconds = 60.159 FPS
X connection to :0 broken (explicit kill or server shutdown).
 $ lxc exec waylandx -- sudo -u osamu -i es2tri
EGL_VERSION = 1.5
EGL_VENDOR = Mesa Project
EGL_EXTENSIONS = EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync EGL_CHROMIUM_sync_control EGL_ANGLE_sync_control_rate EGL_EXT_buffer_age EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_EXT_protected_surface EGL_EXT_swap_buffers_with_damage EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs EGL_KHR_context_flush_control EGL_KHR_create_context EGL_KHR_create_context_no_error EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_KHR_no_config_context EGL_KHR_reusable_sync EGL_KHR_surfaceless_context EGL_KHR_swap_buffers_with_damage EGL_EXT_pixel_format_float EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_drm_image EGL_MESA_image_dma_buf_export EGL_MESA_query_driver EGL_NOK_texture_from_pixmap EGL_WL_bind_wayland_display
EGL_CLIENT_APIS = OpenGL OpenGL_ES
Uniform modelviewProjection at 0
Attrib pos at 0
Attrib color at 1
X connection to :0 broken (explicit kill or server shutdown).

Now GL/EGL/ES2 programs work. (except es2gears_wayland)

Running Wayland GUI application firefox in container

Let’s start with a fresh waylandx instance.

 $ lxc delete waylandx -f || lxc copy wayland0 waylandx
 $ lxc start waylandx
 $ lxc exec waylandx -- apt install firefox-esr
 ...
 $ lxc exec waylandx -- sudo -u osamu -i firefox
Gtk-Message: 06:01:42.367: Failed to load module "canberra-gtk-module"
Gtk-Message: 06:01:42.369: Failed to load module "canberra-gtk-module"
[GFX1-]: glxtest: libpci missing
[GFX1-]: glxtest: libEGL missing
 $ lxc exec waylandx -- apt install libpci3 libegl1 libcanberra-gtk3-0
 ...
 $ lxc exec waylandx -- sudo -u osamu -i firefox
ATTENTION: default value of option mesa_glthread overridden by environment.
ATTENTION: default value of option mesa_glthread overridden by environment.

Works even without some library but by installing them reduces warnings. Browser works well with sound capability.

Running X GUI application chromium in container

Let’s start with a fresh waylandx instance.

 $ lxc delete waylandx -f || lxc copy wayland0 waylandx
 $ lxc start waylandx
 $ lxc exec waylandx -- apt install chromium
 ...
 $ lxc exec waylandx -- sudo -u osamu -i chromium
Gtk-Message: 06:15:48.971: Failed to load module "canberra-gtk-module"
Gtk-Message: 06:15:48.975: Failed to load module "canberra-gtk-module"
[4167:4167:1125/061549.053769:ERROR:policy_logger.cc(157)] :components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc(163) Cloud management controller initialization aborted as CBCM is not enabled.
 $ lxc exec waylandx -- apt install libcanberra-gtk3-0
 ...
 $ lxc exec waylandx -- sudo -u osamu -i chromium
[4442:4442:1125/064117.418688:ERROR:policy_logger.cc(157)] :components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc(163) Cloud management controller initialization aborted as CBCM is not enabled.

Works even without some library but by installing them reduces warnings. Browser works well with sound capability.

Previous Post Top Next Post