Installing Chromium in Ubuntu container fails - /dev/pts: Permission denied

I have an LXC container (managed with Incus) that I’m using for JS development (node, npm, angular, etc.). I want to install Chromium (or Chrome) into this container and run it in headless-mode for web application testing.

Since I’m running Ubuntu inside the container, I’ve tried to install apt package chromium-browser, which merely pulls in the chromium snap. I’ve also tried to install the snap directly. Either way, I ultimately get the same error message. Here’s the alternative commands that I’ve tried, and the resulting message:

$ sudo snap install chromium
[...]
$ sudo apt install chromium-browser
[...]
- Run configure hook of "chromium" snap if present (run hook "configure": cannot perform operation: mount -t devpts --make-slave --make-private -o acl,relatime,kernmount,iversion,active,nous
er,0xffffffff00000000 devpts /dev/pts: Permission denied)

Someone else brought up this similar topic about 4 years ago: Installing Chromium in container fails - sudo snap install chromium. But the root cause (lzo compression) seemed quite different back then.

Searching the web for the error message doesn’t bring up anything useful, so I thought I’d fist ask here. I might also try over at snapcraft, and find out what the chromium snap is trying to do with /dev/pts here.

That said, the chromium snap works like a charm when I run it directly on my laptop (i.e. my Incus host) or in an Incus-managed VM - both also running Ubuntu 24.10 (oracular). In contrast, I’ve tried installing the chromium snap in several other Incus-managed LXC containers, and I ran into the same error for all of them. So could it have to do with the way that LXC manages /dev/pts?

Here’s some technical details about my host and the container:

$ incus version 
Client version: 6.0.1
Server version: 6.0.1

$ incus config show container-js-dev
architecture: x86_64
config:
  boot.autostart: "true"
  cloud-init.user-data: |
    [**** omitted ****]
  image.architecture: amd64
  image.description: Ubuntu oracular amd64 (20241124_07:42)
  image.os: Ubuntu
  image.release: oracular
  image.serial: "20241124_07:42"
  image.type: squashfs
  image.variant: cloud
  limits.cpu: "2"
  limits.memory: 2GiB
  raw.idmap: both 40001 40001
  volatile.base_image: 64b3c49eae9b7874467871efbbe6541fbf9a8801925a0ec15f1370794ec16011
  volatile.bridge-nic.host_name: vethec4ba243
  volatile.bridge-nic.hwaddr: 00:16:3e:06:c8:3b
  volatile.bridge-nic.name: eth0
  volatile.cloud-init.instance-id: 83fbbb47-b286-4426-b934-2feba2505f83
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":40001},{"Isuid":true,"Isgid":true,"Hostid":40001,"Nsid":40001,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":1040002,"Nsid":40002,"Maprange":999959998},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":40001},{"Isuid":false,"Isgid":true,"Hostid":1040002,"Nsid":40002,"Maprange":999959998}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":40001},{"Isuid":true,"Isgid":true,"Hostid":40001,"Nsid":40001,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":1040002,"Nsid":40002,"Maprange":999959998},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":40001},{"Isuid":false,"Isgid":true,"Hostid":1040002,"Nsid":40002,"Maprange":999959998}]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
  volatile.last_state.ready: "false"
  volatile.uuid: 1d75ac8e-4830-4012-8d8e-851962c72df7
  volatile.uuid.generation: 1d75ac8e-4830-4012-8d8e-851962c72df7
devices:
  bridge-nic:
    ipv4.address: 192.168.66.34
    network: incusbr0
    type: nic
  disk-0:
    path: /mnt/meeque/dev/web/xss-demo-app
    shift: "false"
    source: /home/michael/Programmierung/web/xss-demo-app
    type: disk
ephemeral: false
profiles:
- default
stateful: false
description: ""

$ incus project show user-40001
config:
  features.images: "true"
  features.networks: "false"
  features.networks.zones: "true"
  features.profiles: "true"
  features.storage.buckets: "true"
  features.storage.volumes: "false"
  restricted: "true"
  restricted.containers.nesting: block
  restricted.devices.disk: allow
  restricted.devices.disk.paths: /home/michael/,/tmp/.X11-unix/
  restricted.devices.gpu: allow
  restricted.devices.nic: allow
  restricted.devices.proxy: allow
  restricted.idmap.gid: "40001"
  restricted.idmap.uid: "40001"
  restricted.networks.access: incusbr0,incusbr-40001
  user.mq_config_hash: 3997d7e1f0e0f314feec84c2dccdec9c48c42b57
description: ""
name: user-40001
used_by:
- [**** omitted ****]
- /1.0/instances/container-js-dev?project=user-40001
- [**** omitted ****]
- /1.0/profiles/default?project=user-40001

Fyi, 40001 (not 1000) is my uid/gid (for user michael), both on the host and inside the container.

Here’s additional info from inside the container:

$ ls -la /dev/pts/
total 0
drwxr-xr-x 2 root    root      0 Jan 20 21:23 .
drwxr-xr-x 8 root    root    500 Jan 20 21:23 ..
crw--w---- 1 root    tty  136, 0 Jan 20 21:23 0
crw--w---- 1 michael tty  136, 2 Jan 26 22:01 2
crw-rw-rw- 1 root    root   5, 2 Jan 26 22:01 ptmx

$ mount | grep /dev/pts
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=1000005,mode=620,ptmxmode=666,max=1024)

Does not look suspicious to me. Any idea how to fix this or investigate further?

I know, I should try with latest Incus version instead, but I’d need some time to set that up. I can also try a different approach to install Chromium/Chrome in the container… but I’d still like to know why I’m running into this error?

You don’t need the latest, but the LTS branch is currently on 6.0.3. I suggest you start with that, in case this is an issue that’s already been found and fixed.

1 Like