From 0384ce9b90d0391e9b9b84ced81f5446929781e9 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:37:17 +0200 Subject: [PATCH 01/15] Update Dockerfile --- Dockerfile | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/Dockerfile b/Dockerfile index 902e2ef..a3f0eaf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ # syntax=docker/dockerfile:1 FROM scratch AS runner -COPY --from=qemux/qemu:7.46 / / +COPY --from=qemux/qemu:7.47 / / ARG VERSION_ARG="0.0" + ARG DEBCONF_NOWARNINGS="yes" ARG DEBIAN_FRONTEND="noninteractive" ARG DEBCONF_NONINTERACTIVE_SEEN="true" @@ -23,38 +24,9 @@ EOF COPY --chmod=755 ./src /run/ -RUN <<'EOF' - set -eu - - sed -i \ - 's@if ! enabled "$GPU" || isAmdCpu || \[\[ "$ARCH" != "amd64" \]\]; then@if ! enabled "$GPU" || [[ "$ARCH" != "amd64" ]]; then@' \ - /run/display.sh - - sed -i \ - 's| -device usb-tablet||' \ - /run/config.sh - - sed -i \ - 's@USB_OPTS="-device $USB"@& \&\& { [[ "${TABLET:-Y}" =~ ^[Yy] ]] \&\& USB_OPTS+=" -device usb-tablet" || USB_OPTS+=" -device usb-mouse"; }@' \ - /run/config.sh - - grep -q 'usb-mouse' /run/config.sh || { - echo "patch failed: TABLET conditional not injected into config.sh" >&2 - exit 1 - } - - ! grep -q 'isAmdCpu' /run/display.sh || { - echo "patch failed: AMD GPU gate not removed from display.sh" >&2 - exit 1 - } - - bash -n /run/display.sh /run/config.sh -EOF - VOLUME /storage EXPOSE 5900 8006 -ENV GPU="Y" ENV RAM_SIZE="4G" ENV CPU_CORES="2" ENV DISK_SIZE="64G" From b626c4f5c1958a317b49db1a614b21b4680b20fc Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:41:06 +0200 Subject: [PATCH 02/15] Update entry.sh --- src/entry.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/entry.sh b/src/entry.sh index 42390e0..f42cb12 100644 --- a/src/entry.sh +++ b/src/entry.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -Eeuo pipefail +: "${PLATFORM:="x64"}" : "${APP:="ChromeOS Flex"}" : "${SUPPORT:="https://github.com/dockur/chromeos"}" @@ -8,10 +9,11 @@ set -Eeuo pipefail : "${LOSSY:="N"}" : "${SHUTDOWN:="Y"}" : "${TIMEOUT:="105"}" -: "${PLATFORM:="x64"}" +: "${RAM_MINIMUM:="2G"}" : "${BOOT_MODE:="uefi"}" : "${RAM_MINIMUM:="2G"}" : "${DISK_MINIMUM:="16G"}" +: "${MOUSE:="usb-tablet"}" cd /run From 13cdb18ff6833656096fe2a77d1cf3a87db0cc14 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:47:24 +0200 Subject: [PATCH 03/15] Update define.sh --- src/define.sh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/define.sh b/src/define.sh index cc7fb66..3a9012c 100755 --- a/src/define.sh +++ b/src/define.sh @@ -3,7 +3,7 @@ set -Eeuo pipefail : "${LOSSY:="N"}" : "${TABLET:="Y"}" -: "${FORCE_HOST_CURSOR:="Y"}" +: "${FORCE_HOST_CURSOR:="N"}" BOOT_DESC=" $APP (${VERSION,,})" @@ -60,24 +60,28 @@ LOSSY_OPT="" [[ "${LOSSY^^}" =~ ^Y ]] && LOSSY_OPT=",lossy=on" export LOSSY_OPT -# Show the browser's cursor over the noVNC canvas — ChromeOS hides its own cursor in touchscreen mode (which we are, since usb-tablet sends absolute coords). +# Show the browser's cursor over the noVNC canvas — ChromeOS hides its own cursor +# in touchscreen mode (which we are, since usb-tablet sends absolute coords). CSS_MARKER='/* chromeos-flex */' CSS_RULE='#noVNC_container, #noVNC_container * { cursor: default !important; }' BASE_CSS='/usr/share/novnc/app/styles/base.css' if [ -f "$BASE_CSS" ]; then + sed -i "\|$CSS_MARKER|,+1d" "$BASE_CSS" 2>/dev/null || true - if [[ "${FORCE_HOST_CURSOR^^}" =~ ^[Yy] ]]; then + + if enabled "${TABLET:-Y}" || enabled "${FORCE_HOST_CURSOR:-N}"; then printf '\n%s\n%s\n' "$CSS_MARKER" "$CSS_RULE" >> "$BASE_CSS" fi + fi -if [[ "${TABLET^^}" =~ ^Y ]] && [ -x /run/mouse_fix.sh ]; then +if enabled "${TABLET:-Y}" && [ -x /run/mouse_fix.sh ]; then nohup /run/mouse_fix.sh >/dev/null 2>&1 & disown fi -if [[ "${KEEP_AWAKE:-N}" =~ ^[Yy] ]] && [ -x /run/keep_awake.sh ]; then +if enabled "${KEEP_AWAKE:-N}" && [ -x /run/keep_awake.sh ]; then nohup /run/keep_awake.sh >/dev/null 2>&1 & disown fi From 5253f8c783e5cd9bc0066c0b05d654c2ffd87244 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:48:12 +0200 Subject: [PATCH 04/15] Update define.sh --- src/define.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/define.sh b/src/define.sh index 3a9012c..78c61d1 100755 --- a/src/define.sh +++ b/src/define.sh @@ -56,10 +56,6 @@ if [ -n "$GPU" ]; then info "Hardware rendering on $gpu_name render node $RENDERNODE." fi -LOSSY_OPT="" -[[ "${LOSSY^^}" =~ ^Y ]] && LOSSY_OPT=",lossy=on" -export LOSSY_OPT - # Show the browser's cursor over the noVNC canvas — ChromeOS hides its own cursor # in touchscreen mode (which we are, since usb-tablet sends absolute coords). CSS_MARKER='/* chromeos-flex */' From 72b1154a8436f89c451dacc41cb03db08675ba61 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:53:51 +0200 Subject: [PATCH 05/15] Update readme.md --- readme.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index 1c76ba0..9c9af93 100644 --- a/readme.md +++ b/readme.md @@ -239,17 +239,6 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern Or with the CLI: add `--gpus all -e NVIDIA_DRIVER_CAPABILITIES=all`. The render node is auto-detected by vendor, so no card-specific configuration is needed. If both an Nvidia and an Intel/AMD GPU are present, the Nvidia card is preferred once its EGL libraries are available; force the choice either way with `GPU: "nvidia"` / `GPU: "intel"`, or pin a node with `RENDERNODE`. -### How does the cursor work? - - ChromeOS Flex sees the input device as a touchscreen and doesn't render a cursor. noVNC has an optional "Show dot when no cursor" setting, but the dot is small and easy to miss. By default the container overrides this with a CSS rule so the browser's normal cursor shows through: - - ```yaml - environment: - FORCE_HOST_CURSOR: "Y" - ``` - - Set it to `"N"` to disable the override. - ### How do I right-click? ChromeOS treats the input device as a touchscreen, so right-click events are ignored. To open a context menu, **left-click and hold for about half a second**. The touch UI interprets a long-press as a context-menu gesture. @@ -261,7 +250,6 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern ```yaml environment: TABLET: "N" - FORCE_HOST_CURSOR: "N" ``` This swaps the tablet for a `usb-mouse`, so ChromeOS shows its own cursor and right-click works. The trade-off is pointer tracking: ChromeOS scales the relative movements noVNC sends, so the cursor drifts away from the real pointer position over distance and clicks land off-target. This mode suits a direct VNC client more than the browser viewer; for noVNC, the default tablet mode is recommended. @@ -369,6 +357,10 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern - /dev/bus/usb ``` +### Are these all available options? + + No. For a complete overview of all supported settings, see the [environment variables](https://github.com/qemus/qemu/docs/environment.md) page. + ### How do I verify that KVM is available? First, make sure your platform and container runtime meet the [requirements](#requirements-️) listed above. From d784a3d95dfd62944c892b5f7ef7ce7a02b14375 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:55:27 +0200 Subject: [PATCH 06/15] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 9c9af93..051e7bd 100644 --- a/readme.md +++ b/readme.md @@ -359,7 +359,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern ### Are these all available options? - No. For a complete overview of all supported settings, see the [environment variables](https://github.com/qemus/qemu/docs/environment.md) page. + No. For a complete overview of all supported settings, see the [environment variables](https://github.com/qemus/qemu/blob/master/docs/environment.md) page. ### How do I verify that KVM is available? From e95d30062e5d6f88d36cb196ab33731402bc5ad3 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:56:17 +0200 Subject: [PATCH 07/15] Update define.sh --- src/define.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/define.sh b/src/define.sh index 78c61d1..70427eb 100755 --- a/src/define.sh +++ b/src/define.sh @@ -75,6 +75,8 @@ fi if enabled "${TABLET:-Y}" && [ -x /run/mouse_fix.sh ]; then nohup /run/mouse_fix.sh >/dev/null 2>&1 & disown +else + MOUSE="usb-mouse" fi if enabled "${KEEP_AWAKE:-N}" && [ -x /run/keep_awake.sh ]; then From 7f7d2bae74c0f4d7909a23172de0a1aa7fddfd38 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:58:06 +0200 Subject: [PATCH 08/15] Update entry.sh --- src/entry.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/entry.sh b/src/entry.sh index f42cb12..498ec16 100644 --- a/src/entry.sh +++ b/src/entry.sh @@ -5,6 +5,7 @@ set -Eeuo pipefail : "${APP:="ChromeOS Flex"}" : "${SUPPORT:="https://github.com/dockur/chromeos"}" +: "${GPU:="Y"}" : "${AUDIO:="N"}" : "${LOSSY:="N"}" : "${SHUTDOWN:="Y"}" From 27283f9d878a7969bd2a671e2cf6859c188d9eea Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 03:59:57 +0200 Subject: [PATCH 09/15] Update define.sh --- src/define.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/define.sh b/src/define.sh index 70427eb..723409a 100755 --- a/src/define.sh +++ b/src/define.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash set -Eeuo pipefail -: "${LOSSY:="N"}" : "${TABLET:="Y"}" +: "${KEEP_AWAKE:="N"}" : "${FORCE_HOST_CURSOR:="N"}" BOOT_DESC=" $APP (${VERSION,,})" @@ -66,20 +66,20 @@ if [ -f "$BASE_CSS" ]; then sed -i "\|$CSS_MARKER|,+1d" "$BASE_CSS" 2>/dev/null || true - if enabled "${TABLET:-Y}" || enabled "${FORCE_HOST_CURSOR:-N}"; then + if enabled "$TABLET" || enabled "$FORCE_HOST_CURSOR"; then printf '\n%s\n%s\n' "$CSS_MARKER" "$CSS_RULE" >> "$BASE_CSS" fi fi -if enabled "${TABLET:-Y}" && [ -x /run/mouse_fix.sh ]; then +if enabled "$TABLET" && [ -x /run/mouse_fix.sh ]; then nohup /run/mouse_fix.sh >/dev/null 2>&1 & disown else MOUSE="usb-mouse" fi -if enabled "${KEEP_AWAKE:-N}" && [ -x /run/keep_awake.sh ]; then +if enabled "$KEEP_AWAKE" && [ -x /run/keep_awake.sh ]; then nohup /run/keep_awake.sh >/dev/null 2>&1 & disown fi From 2d363c15d274fb99c75a3bf060405244034aef40 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:28:02 +0200 Subject: [PATCH 10/15] Update define.sh --- src/define.sh | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) diff --git a/src/define.sh b/src/define.sh index 723409a..cd07fdb 100755 --- a/src/define.sh +++ b/src/define.sh @@ -7,55 +7,6 @@ set -Eeuo pipefail BOOT_DESC=" $APP (${VERSION,,})" -gpu="${GPU:-}" -gpu_vendor="" - -case "${gpu,,}" in - ""|n|no|0|false|off) GPU="" ;; - y|yes|1|true|on|auto) GPU="Y" ;; - intel) GPU="Y"; gpu_vendor="0x8086" ;; - amd) GPU="Y"; gpu_vendor="0x1002" ;; - nvidia) GPU="Y"; gpu_vendor="0x10de" ;; - *) info "Unknown GPU value \"$gpu\"; treating it as auto."; GPU="Y" ;; -esac - -if [ -n "$GPU" ] && [ -z "${RENDERNODE:-}" ]; then - compgen -G "/usr/lib/*/libEGL_nvidia.so.0" >/dev/null && nvidia_egl=1 || nvidia_egl= - for node in /dev/dri/renderD*; do - { exec 3<"$node"; } 2>/dev/null || continue - exec 3<&- - dev="/sys/class/drm/${node##*/}/device" - vid=$(cat "$dev/vendor" 2>/dev/null) - if [ -n "$gpu_vendor" ] && [ "$vid" != "$gpu_vendor" ]; then - continue - fi - if [ "$vid" != "0x10de" ]; then - : "${RENDERNODE:=$node}" - elif [ -z "$nvidia_egl" ]; then - info "Nvidia GPU at $node has no graphics capability; run the container with \"--gpus all -e NVIDIA_DRIVER_CAPABILITIES=all\"." - elif ! compgen -G "$dev/drm/card*" >/dev/null; then - info "Nvidia GPU at $node needs nvidia-drm modeset=1 on the host; add \"options nvidia_drm modeset=1\" and reboot." - else - RENDERNODE="$node"; break - fi - done -fi - -if [ -n "$GPU" ] && { [ -z "${RENDERNODE:-}" ] || [ ! -c "${RENDERNODE:-/dev/null}" ]; }; then - info "No usable ${gpu_vendor:+$gpu }GPU render node found; falling back to software rendering." - GPU="" -fi - -if [ -n "$GPU" ]; then - case "$(cat "/sys/class/drm/${RENDERNODE##*/}/device/vendor" 2>/dev/null)" in - 0x8086) gpu_name="Intel" ;; - 0x1002) gpu_name="AMD" ;; - 0x10de) gpu_name="Nvidia" ;; - *) gpu_name="GPU" ;; - esac - info "Hardware rendering on $gpu_name render node $RENDERNODE." -fi - # Show the browser's cursor over the noVNC canvas — ChromeOS hides its own cursor # in touchscreen mode (which we are, since usb-tablet sends absolute coords). CSS_MARKER='/* chromeos-flex */' From d4cf7195adb16f8208a94c79d74409c62db3676e Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:29:12 +0200 Subject: [PATCH 11/15] Update define.sh --- src/define.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/define.sh b/src/define.sh index cd07fdb..d371c63 100755 --- a/src/define.sh +++ b/src/define.sh @@ -5,8 +5,6 @@ set -Eeuo pipefail : "${KEEP_AWAKE:="N"}" : "${FORCE_HOST_CURSOR:="N"}" -BOOT_DESC=" $APP (${VERSION,,})" - # Show the browser's cursor over the noVNC canvas — ChromeOS hides its own cursor # in touchscreen mode (which we are, since usb-tablet sends absolute coords). CSS_MARKER='/* chromeos-flex */' From f41d26eaf413846689809e677c3f7bdeecb1309f Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:37:00 +0200 Subject: [PATCH 12/15] Update readme.md --- readme.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index 051e7bd..9fe3aab 100644 --- a/readme.md +++ b/readme.md @@ -38,23 +38,16 @@ services: container_name: chromeos environment: VERSION: "stable" - GPU: "Y" - FORCE_HOST_CURSOR: "Y" - KEEP_AWAKE: "N" devices: + - /dev/dri - /dev/kvm - /dev/net/tun - device_cgroup_rules: - - "c 226:* rwm" cap_add: - NET_ADMIN ports: - 8006:8006 - - 5900:5900/tcp - - 5900:5900/udp volumes: - ./chromeos:/storage - - /dev/dri:/dev/dri:rw restart: always stop_grace_period: 2m ``` @@ -62,7 +55,7 @@ services: ##### Docker CLI: ```bash -docker run -it --rm --name chromeos -e "VERSION=stable" -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --device-cgroup-rule="c 226:* rwm" --cap-add NET_ADMIN -v "${PWD:-.}/chromeos:/storage" -v /dev/dri:/dev/dri --stop-timeout 120 docker.io/dockurr/chromeos +docker run -it --rm --name chromeos -e "VERSION=stable" -p 8006:8006 --device=/dev/dri --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/chromeos:/storage" --stop-timeout 120 docker.io/dockurr/chromeos ``` ##### Kubernetes: @@ -85,9 +78,6 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern > [!NOTE] > Docker Desktop on Linux, macOS, and Windows 10 does not currently provide KVM access to containers and is therefore not supported. -> [!IMPORTANT] -> For best performance, run on a host with a GPU and `/dev/dri/` exposed. GPU acceleration uses the QEMU egl-headless path: Intel and AMD render nodes go through the open-source Mesa driver, Nvidia through its proprietary driver (see the FAQ). Without a usable GPU it falls back to software rendering, which works but is slow. - ## FAQ 💬 ### How do I use it? From 84a45f3b36d1b2293baa3d2a3b9ff5f16da6e867 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:45:59 +0200 Subject: [PATCH 13/15] Update readme.md --- readme.md | 106 ++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/readme.md b/readme.md index 9fe3aab..3d0980d 100644 --- a/readme.md +++ b/readme.md @@ -169,66 +169,6 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern CPU_CORES: "4" ``` -### How do I password-protect the viewer? - - By default the viewer on port 8006 is open to anyone who can reach it. Set `PROTECT` to require a login (HTTP basic auth). The default credentials are `Docker` / `admin`, so override them with `USERNAME` and `PASSWORD`: - - ```yaml - environment: - PROTECT: "Y" - USERNAME: "admin" - PASSWORD: "your-password" - ``` - -### How do I let the host reclaim unused memory? - - By default the VM holds the full `RAM_SIZE` for its entire lifetime. Set `BALLOONING` to enable dynamic memory ballooning, which lets the host reclaim guest RAM that isn't in use: - - ```yaml - environment: - BALLOONING: "Y" - ``` - - The target can be tuned with `BALLOONING_MIN_MEM` (default `33%`) and `BALLOONING_RAM_THRESHOLD` (default `80.0`). - -### How does GPU acceleration work? - - The container expects the host's `/dev/dri/` to be bind-mounted in. At startup, the entrypoint scans for a usable render node and hands it to QEMU as the VirGL backend (`-display egl-headless,rendernode=...` + `virtio-vga-gl`). Both the `volumes: - /dev/dri:/dev/dri:rw` mount and the `device_cgroup_rules: - "c 226:* rwm"` rule in the example compose are required for this. Intel and AMD render nodes work out of the box; for Nvidia see below. If no usable render node is found, the container falls back to software rendering. - - The `GPU` setting accepts: - - | Value | Effect | - |-------|--------| - | `Y` / `auto` | Auto-detect (default); prefers a ready Nvidia node, otherwise Intel/AMD | - | `N` | Off — software rendering (3–15 fps) | - | `intel` / `amd` / `nvidia` | Force a specific vendor, useful on multi-GPU hosts | - - For finer control, set `RENDERNODE` to a specific node (e.g. `/dev/dri/renderD128`). On a miss the container logs exactly what was found and what to fix, then falls back to software rendering. - -### How do I use an Nvidia GPU? - - Nvidia cards render through the same egl-headless path, with two extra requirements: - - - The host must load `nvidia-drm` with `modeset=1` (add `options nvidia_drm modeset=1` to a file in `/etc/modprobe.d/`, run `update-initramfs -u`, then reboot). Without it the card is invisible to the GBM/EGL backend the container uses. - - Run the container with the Nvidia runtime and the `graphics` capability so the driver's EGL libraries are injected: - - ```yaml - services: - chromeos: - image: dockurr/chromeos - runtime: nvidia - environment: - GPU: "Y" - NVIDIA_VISIBLE_DEVICES: "all" - NVIDIA_DRIVER_CAPABILITIES: "all" - device_cgroup_rules: - - "c 226:* rwm" - volumes: - - /dev/dri:/dev/dri:rw - ``` - - Or with the CLI: add `--gpus all -e NVIDIA_DRIVER_CAPABILITIES=all`. The render node is auto-detected by vendor, so no card-specific configuration is needed. If both an Nvidia and an Intel/AMD GPU are present, the Nvidia card is preferred once its EGL libraries are available; force the choice either way with `GPU: "nvidia"` / `GPU: "intel"`, or pin a node with `RENDERNODE`. - ### How do I right-click? ChromeOS treats the input device as a touchscreen, so right-click events are ignored. To open a context menu, **left-click and hold for about half a second**. The touch UI interprets a long-press as a context-menu gesture. @@ -277,6 +217,41 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern Trade-off: slight blurring on photos and gradients (invisible on UI text). Most useful when accessing the container over WAN or on bandwidth-constrained networks. +### How do I password-protect the noVNC viewer? + + By default the viewer on port 8006 is open to anyone who can reach it. Set `PROTECT` to require a login: + + ```yaml + environment: + PROTECT: "Y" + USERNAME: "admin" + PASSWORD: "password" + ``` + +### How do I enable GPU acceleration? + + To enable hardware-accelerated graphics using an Intel or AMD GPU, add the following device to your compose file: + + ```yaml + devices: + - /dev/dri + ``` + + For NVIDIA GPUs, the `NVIDIA Container Toolkit` must be installed on the host and the GPU must be exposed to the container: + + ```yaml + environment: + NVIDIA_DRIVER_CAPABILITIES: "graphics" + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: + - gpu + ``` + ### How do I enable developer mode? Add `DEV_MODE: "Y"` to your compose file: @@ -347,6 +322,17 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/chromeos/master/kubern - /dev/bus/usb ``` +### How do I let the host reclaim unused memory? + + By default the VM holds the full `RAM_SIZE` for its entire lifetime. Set `BALLOONING` to enable dynamic memory ballooning, which lets the host reclaim guest RAM that isn't in use: + + ```yaml + environment: + BALLOONING: "Y" + ``` + + The target can be tuned with `BALLOONING_MIN_MEM` (default `33%`) and `BALLOONING_RAM_THRESHOLD` (default `80.0`). + ### Are these all available options? No. For a complete overview of all supported settings, see the [environment variables](https://github.com/qemus/qemu/blob/master/docs/environment.md) page. From dc65bcd85c96758a821231d9ea7e971af1007b5e Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:48:32 +0200 Subject: [PATCH 14/15] Update compose.yml --- compose.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/compose.yml b/compose.yml index 714ae44..14bf120 100644 --- a/compose.yml +++ b/compose.yml @@ -4,22 +4,15 @@ services: container_name: chromeos environment: VERSION: "stable" - GPU: "Y" - FORCE_HOST_CURSOR: "Y" - KEEP_AWAKE: "N" devices: + - /dev/dri - /dev/kvm - /dev/net/tun - device_cgroup_rules: - - "c 226:* rwm" cap_add: - NET_ADMIN ports: - 8006:8006 - - 5900:5900/tcp - - 5900:5900/udp volumes: - ./chromeos:/storage - - /dev/dri:/dev/dri:rw restart: always stop_grace_period: 2m From 4c89ef045a03a4792d40815c172de34198263c28 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 18 Aug 2026 05:48:54 +0200 Subject: [PATCH 15/15] Update codespaces.yml --- .devcontainer/codespaces.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.devcontainer/codespaces.yml b/.devcontainer/codespaces.yml index ea2480b..14bf120 100644 --- a/.devcontainer/codespaces.yml +++ b/.devcontainer/codespaces.yml @@ -4,17 +4,10 @@ services: container_name: chromeos environment: VERSION: "stable" - GPU: "N" - FORCE_HOST_CURSOR: "Y" - KEEP_AWAKE: "N" - RAM_SIZE: "half" - DISK_SIZE: "max" - CPU_CORES: "max" devices: + - /dev/dri - /dev/kvm - /dev/net/tun - device_cgroup_rules: - - "c 226:* rwm" cap_add: - NET_ADMIN ports: