This is an update to an earlier post. Thanks to contributions on this thread and related bugfix.

The Qubes operating system aims to be reasonably secure through isolation.

One example of isolation: one virtual machine (“Qube”) runs the windowing environment, while other VMs run applications, which are displayed in that environment. This separation from the X11 environment means that an application, like skype or bluejeans, cannot share the screen. This is by design, and highlights the security that makes me a fan of Qubes.

In this post, I’ll walk through a technique that makes it possible to show applications in a screensharing application, within Qubes. The idea is to run an additional X11 display. The screensharing application will run there, as will all windows that you want to show in the screenshare. (Applications appearing in the primary display will remain hidden, as we want.)

Prepare the Template VM

I made a clone of Qubes’ fedora-28 template called f28-media (because I’ve installed codecs and applications to display various media formats). Install the VNC software there…

[user@f28-media ~]$ sudo dnf install tigervnc tigervnc-server

Prepare the AppVM

Next, configure an AppVM based on the template (f28-media in this example). Let’s say the AppVM is called screenshare.

Screenshare VM Window Manager

The screenshare VM needs a window manager for the VNC environment. I decided to try dwm from suckless. It has a reputation for being lightweight, which I’m more than OK with, for this purpose.

First install dependencies. Note this can be done on the screenshare VM (as opposed to the template VM). We won’t need these again after compiling dwm.

[user@screenshare ~]$ sudo dnf install libX11-devel libXft-devel libXinerama-devel

Next, compile and install dwm. It will be installed in /usr/local, which lives in screenshare app VM, not the template.

[user@screenshare ~]$ git clone https://git.suckless.org/dwm
[user@screenshare ~]$ cd dwm
[user@screenshare dwm]$ make
[user@screenshare dwm]$ sudo make install

vncserver Configuration

Edit ~/.vnc/config to make vncserver easier to start on the command line:

securitytypes=none

Also edit ~/.vnc/xstartup. Here’s what I ended up with:

#!/bin/sh

# Use `xhost +` to allow Qubes app VMs to access this vnc session.
xhost +

# The following from the dwm README.
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
do
    sleep 1
done &
exec dwm

This file needs execute permission!

[user@screenshare ~]$ chmod +x ~/.vnc/xstartup

Then run the VNC server and viewer…

[user@screenshare ~]$ vncserver
[user@screenshare ~]$ vncviewer :1

(If you prefer to enable vncserver as a service that starts automatically, the ArchWiki comes through with a detailed HOWTO for TigerVnc.)

Test AppVm configuration

[user@screenshare ~]$ DISPLAY=:1 xterm

At this point, on the screenshare appVM, you can launch whatever you use for meetings and screensharing. Remember to use DISPLAY=:1 for that application, and any application you want to show in the session.

(I find bluejeans indicates it is sharing the screen, but it doesn’t succeed. Google meet works, and I haven’t tested others yet.)

(Optional) Show Apps Running in Other AppVMs

What if you want to include in your screensharing session an application that runs in another VM? For example, an appVM without a network connection. Or, one that doesn’t have Bluejeans proprietary RPM installed.

To allow this, we can use Qubes’ powerful qrexec feature. To do so, we need to modify the dom0 VM, the screenshare VM, and the appVM running the application, which for this example I’ll call devel

On dom0, Create my-screenshare RPC

Allow the devel appVM to reach the screenshare appVM, specifically for screensharing, by creating /etc/qubes-rpc/policy/my-screenshare:

devel screenshare allow

Expose X11 Display on screenshare

On screenshare, create file /usr/local/etc/qubes-rpc/my-screenshare, with the following:

socat STDIO UNIX-CLIENT:/tmp/.X11-unix/X1

This exposes the screen share display :1, to qrexec, via a socket that X11 creates.

Pseudo-display on devel

On the appVM, run:

[devel ~]$ sudo socat TCP-LISTEN:6001,reuseaddr,fork EXEC:"qrexec-client-vm screenshare my-screenshare

Now, on devel when we use DISPLAY=:1, it will attempt to use port :6001. And socat, through Qubes qrexec, will forward packets to the socket on screenshare.

Test That It Works

On devel:

[devel ~]$ DISPLAY=:1 xterm

You should see a devel terminal in the vncclient. This will be included in any screensharing done from screenshare. Other applications can be shown in the same way.