Vnc_container for desktop working examples?

Looking for a working example using vnc_container from Batch Connect VNC Container Options that starts a desktop session. The desktop (xfce) is also in the same container.

I’m running OOD v4.0.3.

I have a rocky 9.6 container based off the def listed at the previous link.

Bootstrap: docker
From: rockylinux/rockylinux:9.6.20250531

%labels
  ABOUTME rockylinux/rockylinux:9.6.20250531

%environment
  LANGUAGE="en_US.UTF-8"
  LC_ALL="en_US.UTF-8"
  LANG="en_US.UTF-8"
  export PATH=.:/opt/apps/local/bin:/opt/TurboVNC/bin/:${PATH}
  export LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH}

%runscript
  exec /bin/bash "$@"

%post
    yum -y upgrade

    # OOD
    dnf install -y wget
    dnf install -y epel-release
    dnf groupinstall -y xfce
    dnf install -y python3-pip xorg-x11-xauth
    pip3 install ts
    dnf install -y https://yum.osc.edu/ondemand/latest/compute/el9Server/x86_64/python3-websockify-0.11.0-1.el9.noarch.rpm
    cd /etc/yum.repos.d && wget https://raw.githubusercontent.com/TurboVNC/repo/main/TurboVNC.repo && dnf install -y turbovnc
    dnf clean all
    rm -rf /var/cache/dnf/*

The batch connect template is:

    vnc_container:
      container_path:   "/path/to/rocky9/rockylinux-9.3.sif"
      container_module: "apptainer/1.4.0"
      container_command: "apptainer"
      websockify_cmd: "/usr/bin/websockify"

Using default submit.yml.erb, submit.sh.erb, and xfce.sh from OSC/bc_desktop where I really just add module load apptainer/1.4.0.

The portion of the output.log that seems relevant is Failed to get connection to system bus,

Launching desktop 'xfce'...
Failed to init libxfconf: Could not connect: No such file or directory.
Failed to init libxfconf: Could not connect: No such file or directory.
_IceTransmkdir: Owner of /tmp/.ICE-unix should be set to root
/usr/bin/iceauth:  creating new authority file /state/partition1/job-62176499/ICEauthority
WebSocket server settings:
  - Listen on :16521
  - No SSL/TLS support (no cert file)
  - Backgrounding (daemon)
Scanning VNC log file for user authentications...
Generating connection YAML file...

(xfwm4:102): xfwm4-WARNING **: 17:41:13.389: Unsupported GL renderer (llvmpipe (LLVM 19.1.7, 256 bits)).

** (agent:197): CRITICAL **: 17:41:13.801: Failed to get connection to system bus: Could not connect: No such file or directory
libclock-Message: 17:41:13.835: could not get proxy for org.freedesktop.login1

I attempted to tweak this script.sh Xfce4 Desktop app using container_vnc - #5 by brandonbiggs to meet my needs here:

#!/usr/bin/env bash

# Clean the environment
module purge
module load apptainer/1.4.0

# Set working directory to home directory
cd "${HOME}"

export APPTAINERENV_DISPLAY=$DISPLAY

#
# Launch Xfce Window Manager and Panel
#
export SEND_256_COLORS_TO_REMOTE=1
export APPTAINERENV_SEND_256_COLORS_TO_REMOTE="$SEND_256_COLORS_TO_REMOTE"

export XDG_CONFIG_HOME="<%= session.staged_root.join("config") %>"
export APPTAINERENV_XDG_CONFIG_HOME="$XDG_CONFIG_HOME"

export XDG_DATA_HOME="<%= session.staged_root.join("share") %>"
export APPTAINERENV_XDG_DATA_HOME="$XDG_DATA_HOME"

export XDG_CACHE_HOME="/tmp/xdg"
export APPTAINERENV_XDG_CACHE_HOME="$XDG_CACHE_HOME"

export $(apptainer exec instance://$INSTANCE_NAME dbus-launch 2>/dev/null)
export APPTAINERENV_DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS
export APPTAINERENV_DBUS_SESSION_BUS_PID=$DBUS_SESSION_BUS_PID

module restore
set -x
apptainer exec instance://$INSTANCE_NAME xfwm4 --compositor=off --sm-client-disable &
apptainer exec instance://$INSTANCE_NAME xsetroot -solid "#D3D3D3"
apptainer exec instance://$INSTANCE_NAME xfsettingsd --sm-client-disable --daemon
apptainer exec instance://$INSTANCE_NAME xfce4-panel --sm-client-disable &

# Remove any preconfigured monitors
if [[ -f "${HOME}/.config/monitors.xml" ]]; then
  mv "${HOME}/.config/monitors.xml" "${HOME}/.config/monitors.xml.bak"
fi

# Disable startup services
apptainer exec instance://$INSTANCE_NAME xfconf-query -c xfce4-session -p /startup/ssh-agent/enabled -n -t bool -s false
apptainer exec instance://$INSTANCE_NAME xfconf-query -c xfce4-session -p /startup/gpg-agent/enabled -n -t bool -s false

# Disable useless services on autostart
AUTOSTART="${HOME}/.config/autostart"
rm -fr "${AUTOSTART}"    # clean up previous autostarts
mkdir -p "${AUTOSTART}"
for service in "pulseaudio" "rhsm-icon" "spice-vdagent" "tracker-extract" "tracker-miner-apps" "tracker-miner-user-guides" "xfce4-power-manager" "xfce-polkit"; do
  echo -e "[Desktop Entry]\nHidden=true" > "${AUTOSTART}/${service}.desktop"
done

# Run Xfce4 Terminal as login shell (sets proper TERM)
TERM_CONFIG="${HOME}/.config/xfce4/terminal/terminalrc"
if [[ ! -e "${TERM_CONFIG}" ]]; then
  mkdir -p "$(dirname "${TERM_CONFIG}")"
  sed 's/^ \{4\}//' > "${TERM_CONFIG}" << EOL
    [Configuration]
    CommandLoginShell=TRUE
EOL
else
  sed -i \
    '/^CommandLoginShell=/{h;s/=.*/=TRUE/};${x;/^$/{s//CommandLoginShell=TRUE/;H};x}' \
    "${TERM_CONFIG}"
fi

set +x
#
# Start
#

export APPTAINERENV_PATH=$PATH
export APPTAINERENV_LD_LIBRARY_PATH=$LD_LIBRARY_PATH

sleep 5

apptainer exec "instance://$INSTANCE_NAME" xfce4-session

Now the error I receive is couldn't create cgroup manager.

+ apptainer exec instance://314ae0d2-7cb1-4636-b140-44ed7aea51d9 xsetroot -solid '#D3D3D3'
+ apptainer exec instance://314ae0d2-7cb1-4636-b140-44ed7aea51d9 xfwm4 --compositor=off --sm-client-disable
FATAL:   While setting image/instance: couldn't create cgroup manager: while creating cgroup manager: Process org.freedesktop.systemd1 exited with status 1
FATAL:   While setting image/instance: couldn't create cgroup manager: while creating cgroup manager: Process org.freedesktop.systemd1 exited with status 1

I’ve searched github looking for a public repo that uses vnc_container without luck. Anyone get it working?

We did eventually get it working. Here’s my app and other things that might be helpful. You may not need all of this. If there is something specific I missed, let me know. FWIW we moved away containerized desktops and put them back in our images. Many people didn’t like it not being the “native” experience.

My script.sh.erb

#!/usr/bin/env bash

# Change working directory to user's home directory
cd "${HOME}"

# Ensure that the user's configured login shell is used
export SHELL="$(getent passwd $USER | cut -d: -f7)"

# Start up desktop
echo "Launching desktop '<%= context.desktop %>'..."

<% if context.cluster == "specific_cluster" %>
module load apptainer
apptainer exec ${MOUNTS} "instance://${INSTANCE_NAME}" "<%= session.staged_root.join("desktops", "#{context.desktop}.sh") %>"

<% else %>
source "<%= session.staged_root.join("desktops", "#{context.desktop}.sh") %>"

<% end %>
echo "Desktop '<%= context.desktop %>' ended with $? status..."

We only have one desktop environment, xfce, so xfce.sh:

# Remove any preconfigured monitors
if [[ -f "${HOME}/.config/monitors.xml" ]]; then
  mv "${HOME}/.config/monitors.xml" "${HOME}/.config/monitors.xml.bak"
fi

# Copy over default panel if doesn't exist, otherwise it will prompt the user
PANEL_CONFIG="${HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml"
if [[ ! -e "${PANEL_CONFIG}" ]]; then
  mkdir -p "$(dirname "${PANEL_CONFIG}")"
  cp "/etc/xdg/xfce4/panel/default.xml" "${PANEL_CONFIG}"
fi

# Disable startup services
xfconf-query -c xfce4-session -p /startup/ssh-agent/enabled -n -t bool -s false
xfconf-query -c xfce4-session -p /startup/gpg-agent/enabled -n -t bool -s false

# Disable useless services on autostart
AUTOSTART="${HOME}/.config/autostart"
rm -fr "${AUTOSTART}"    # clean up previous autostarts
mkdir -p "${AUTOSTART}"
for service in "pulseaudio" "rhsm-icon" "spice-vdagent" "tracker-extract" "tracker-miner-apps" "tracker-miner-user-guides" "xfce4-power-manager" "xfce-polkit"; do
  echo -e "[Desktop Entry]\nHidden=true" > "${AUTOSTART}/${service}.desktop"
done

# Run Xfce4 Terminal as login shell (sets proper TERM)
TERM_CONFIG="${HOME}/.config/xfce4/terminal/terminalrc"
if [[ ! -e "${TERM_CONFIG}" ]]; then
  mkdir -p "$(dirname "${TERM_CONFIG}")"
  sed 's/^ \{4\}//' > "${TERM_CONFIG}" << EOL
    [Configuration]
    CommandLoginShell=TRUE
EOL
else
  sed -i \
    '/^CommandLoginShell=/{h;s/=.*/=TRUE/};${x;/^$/{s//CommandLoginShell=TRUE/;H};x}' \
    "${TERM_CONFIG}"
fi

# launch dbus first through eval because it can conflict with a conda environment
# see https://github.com/OSC/ondemand/issues/700
# Get the current hostname
current_hostname=$(hostname)

# Regular expression to match hostname pattern for system with containers
hostname_pattern="^(r[1-9]*n[1-9]*)$"

if [[ ! $current_hostname =~ $hostname_pattern ]]; then
    eval $(dbus-launch --sh-syntax)
fi

# Start up xfce desktop (block until user logs out of desktop)
module purge
xfce4-session

My cluster.d file for the containers:

---
v2:
  metadata:
    title: "cluster name"
    url: "some url"
    hidden: false
  login:
    host: "login.example.com"
  job:
    adapter: "slurm"
    host: "slurm-host"
    conf: "/etc/slurm/server.conf"
  batch_connect:
    basic:
      script_wrapper: |
        module purge
        %s
    vnc_container:
      header: "#!/bin/bash"
      container_path: "/full/path/to/desktop.sif"
      container_bindpath: "/projects,/scratch,/apps,/etc/slurm/slurm.conf,/lib64/libpsm2.so.2"
      container_module: "apptainer"
      container_command: "apptainer"
      container_start_args: []
      websockify_cmd: '/usr/bin/websockify'

Here’s my apptainer def file:

Bootstrap: docker
From: rockylinux/rockylinux:8

%environment
  PATH=/opt/TurboVNC/bin:$PATH
  LANGUAGE="en_US.UTF-8"
  LC_ALL="en_US.UTF-8"
  LANG="en_US.UTF-8"

%post
    dnf install -y epel-release
    dnf groupinstall -y xfce
    dnf install -y python3-pip xorg-x11-xauth
    pip3 install ts
    dnf install -y https://yum.osc.edu/ondemand/latest/compute/el8Server/x86_64/python3-websockify-0.10.0-1.el8.noarch.rpm
    dnf install -y https://yum.osc.edu/ondemand/latest/compute/el8Server/x86_64/turbovnc-2.2.5-1.el8.x86_64.rpm
    dnf clean all
    dnf remove -y xfce4-screensaver
    chown root:root /opt/TurboVNC/etc/turbovncserver-security.conf
    rm -rf /var/cache/dnf/*

Thank you, but unfortunately it didn’t work for me. Same errors referencing cgroups.

I’ve found that you need to mount /var into apptainer to get desktops working.

Since you don’t have any bindpath defined, maybe it’s not part of your default bindpath?

It’s not in my bindpath, only a subset of /var is mounted. I updated the code to mount all of /var and still errors of

Failed to init libxfconf: Could not connect: No such file or directory.

or

FATAL:   While setting image/instance: couldn't create cgroup manager: while creating cgroup manager: Process org.freedesktop.systemd1 exited with status 1

I’ll start clean again as I’ve made a lot fo changes trying to debug.

Thank you!

libxfconf is from /usr so maybe you need that mount too?