vdesktop
Vdesktop runs any RPi operating system inside any RPi operating system. (like a VM)
See it in action:
This script is excellent in these situations:
- Customizing a new Raspbian image: installing packages, configuring raspi-config, installing Chrome Extensions, changing wallpaper, etc.
- Migrating to a clean install of Raspbian and want to compare the appearance of both OS'es at once.
- Run a fresh version of an OS to make a video or to test software compatibility.
- Running something you might want to undo (such as compiling) and don't want your main OS modified.
- "Switch" OSes without ever shutting down or swapping SD cards.
- Running Raspbian Stretch on a Pi 4. Note: Vdesktop has been reported unstable running on Ubuntu.
To download:
git clone https://github.com/Botspot/vdesktop
To run:
sudo ~/vdesktop/vdesktop
Supported operating systems:
Vdesktop has been tested to successfully run:
- TwisterOS
- Kali Linux (armhf)
- Raspberry Pi OS Buster or below (armhf or arm64)
Unsupported operating systems:
Vdesktop does not appear to run:
- Gentoo ARM - it can boot and reach a shell, but the desktop session doesn't work.
- Ubuntu and Pop!_OS - boot procedure never finishes due to this strange bug
- Other operating systems that don't share the same RPiOS kernel, like FydeOS, Android, Windows, etc.
- Raspberry Pi OS Bullseye - the
mutter
window manager is not compatible with Xephyr and the desktop encounters various other strange errors.
After running once, vdesktop will create a file in /usr/bin. So from now on you can simply run vdesktop
. (with no sudo)
Usage:
Boot a .img file: vdesktop /home/pi/2020-08-20-raspios-buster-armhf.img
Boot a usb drive: vdesktop /dev/sda
Boot a directory: vdesktop /home/pi/raspbian-stretch/
A second word specifies the boot mode: cli
, or gui
. If none
specified, gui mode is assumed.
Variable & env file usage:
This new version of vdesktop allows many options to be customized.
For example, you can prevent vdesktop from logging in automatically to the guest.
VDESKTOP_AUTO_LOGIN=no vdesktop /dev/sdc
In the above example, the VDESKTOP_AUTO_LOGIN
value will not be preserved for the next command you run in the terminal. If you want such a behavior, do something like this:
export VDESKTOP_AUTO_LOGIN=no
vdesktop /dev/sdc
To change a setting permanently, go edit the settings.env
file.
BOOT_MODE=gui
UMOUNT_ON_EXIT=yes
USERNAME=pi
PASSWORD=raspberry
MOUNTPOINT=/media/pi/vdesktop
ENABLE_ROOTMOUNT=yes
#ENABLE_VIRGL=no
#LOCAL_BINARIES=yes
NSPAWN_FLAGS=''
#AUTO_LOGIN=yes
Did you notice anything different? None of these variables are prefixed with VDESKTOP_
. Why not? Well, this allows there to be two variable sets, one of which overrides the other.
If the env file contains BOOT_MODE=cli
, but on the terminal you set VDESKTOP_BOOT_MODE=gui
, which one should vdesktop
obey? Turns out the "VDESKTOP_
"-prefixed variable will take priority.
Variable explanation:
BOOT_MODE
- Allowed values:
gui
andcli
- Default value:
gui
- If
gui
, vdesktop will attempt to launch a graphical desktop session for the booted device.
- Allowed values:
UMOUNT_ON_EXIT
- Allowed values:
yes
andno
- Default value:
yes
- When the booted device exits, should vdesktop automatically unmount the device and exit?
- Allowed values:
USERNAME
- Allowed values: anything
- Default value:
pi
- Specifies the username vdesktop will attempt to login with.
PASSWORD
- Allowed values: anything
- Default value:
raspberry
- Specifies the password vdesktop will attempt to login with.
AUTO_LOGIN
- Allowed values:
yes
andno
- Default value:
yes
- If set to
no
, vdesktop will not attempt to login to the guest. - Note: If set to
yes
and the user/pass combination is incorrect, you can login manually afterwards. So there are few cases when you would have to set this tono
.
- Allowed values:
MOUNTPOINT
- Allowed values: Any empty directory.
- Default value:
/media/pi/vdesktop
- Location where vdesktop will mount the device.
- Note: If value is set to a nonexistent directory, vdesktop will create it.
ENABLE_ROOTMOUNT
- Allowed values:
yes
andno
- Default value:
yes
- Enables/disables the mounting of files from the
~/vdesktop/rootmount
into the device. - Note: This is like a bind-mount into the device. You can add scripts, folders - anything you want into the device - and when vdesktop exits, all those files/folders will be unmounted.
- Allowed values:
ENABLE_VIRGL
- Allowed values:
yes
andno
- Default value: depends. If
BOOT_MODE
is set togui
, then this default value isyes
. IfBOOT_MODE
is set tocli
, then this default value isno
. - Enables/disables the virtual GPU for the device.
- Note: Enabling this allows much smoother graphics for some applications, but for other applications, it can cause X server issues.
- Allowed values:
LOCAL_BINARIES
- Allowed values:
yes
andno
- Default value:
yes
- Enables/disables using the
~/vdesktop/systemd-nspawn-32
orsystemd-nspawn-64
binaries. If set tono
, vdesktop will use the version ofsystemd-nspawn
that exists on your main system. - Note: vdesktop uses this later version of
systemd-nspawn
to fix several CPU bugs. Using an outdatedsystemd-nspawn
was the cause for all the Firefox crashes and Chromium "Aw, Snap!"s
- Allowed values:
NSPAWN_FLAGS
- Allowed values: anything
- Default value: nothing
- Easily add your own flags to
systemd-nspawn
, either to change some behavior or to add a bind-mount.
How does it work?
Vdesktop uses a systemd-nspawn
container to 'boot' its devices with. This is very similar to a chroot
.
Systemd-nspawn is much faster than other methods because it doesn't use any emulation. Why would you need emulation anyway, when you want a Pi to run its own OS?
Try out systemd-nspawn yourself:
sudo systemd-nspawn -bD /media/pi/USB-DRIVE
(Where /media/pi/USB-DRIVE is the path to an externally connected usb device with Raspberry Pi OS flashed to it.)
With that command, you'll see the SD card boot up. After manually logging in yourself, you can change settings, run updates, etc, as long as it can be done in the command-line.
What about an image file?
This is harder to do, since it involves mounting the img first, but here you go:
sudo -i
LOOP="$(losetup -fP --show /path/to/your-raspbian.img)"
mount -o rw "${LOOP}p2" /media/pi/vdesktop
mount -o rw "${LOOP}p1" /media/pi/vdesktop/boot
systemd-nspawn -bD /media/pi/vdesktop
umount -fl /media/pi/vdesktop/boot
umount -fl /media/pi/vdesktop
losetup -d "$LOOP"
What if you want graphics?
This is even harder. Launch Xephyr from a host's terminal, then connect to it from within the guest.
From a terminal running on the host system:
Xephyr :1
A black window will appear. Assuming you've already ran the necessary systemd-nspawn
command and logged in as user pi, to make the container/guest system connect to the Xephyr window, run this in the guest's console:
export DISPLAY=:1
/usr/bin/startlxde-pi
If the graphics look bad, you will have to restart certain services. From within the guest's console:
eval "pcmanfm --desktop --profile LXDE-pi; sleep 20; pcmanfm --desktop --profile LXDE-pi" &
lxpanelctl restart
sleep 10
lxpanelctl restart
What if you want everything to work automatically, without requiring any user interaction?
This is too long to post here. After all, it takes the entire vdesktop script to do this. Here's what it does:
expect
logs in automatically to the console. It types inpi
andraspberry
so you don't have to.- After logging in,
/etc/profile
is run. Vdesktop mounts a custom version of/etc/profile
to autostart an X session from the inside. It creates a signal file:/xready
, to let vdesktop know the gui is ready to be loaded. Xephyr
launches when that that file is created, (this is the VNC-style window), to allow the container's X session to connect to it.- Once Xephyr opens and the desktop loads,
clipboardsync
runs, to let you copy & paste text back and forth. - When you exit the container, and all of the above has to be safely dismantled and shutdown. Complex? You bet.
- On top of all that,
vdesktop
ensures dependencies are installed, detects filesystem errors in the .img and asks permission to repair them, and performs a host of little bug fixes to make it Just Workโข.
Directory Tree:
vdesktop/
The main vdesktop folder. Located at /home/pi by default.clipboardsync
Short script keeps the guest's and host's clipboards in sync, like VNC.COPYING
Stores the GNU General Public license v3 forvdesktop
.nspawn
The systemd-nspawn command. This was broken out ofvdesktop
to allow many bind-mounts.profile
This is temporarily mounted to the selected device to start the desktop session. (If enabled via Settings)README.md
You're reading this right now.settings.env
This is the ENV file to store permanent setting changes.systemd-nspawn-32
32-bitsystemd-nspawn
binary.systemd-nspawn-64
64-bitsystemd-nspawn
binary.vdesktop
The main scriptvdesktop-runner
Short script that's put in /usr/local/bin. You can now runvdesktop
in a terminal, instead ofsudo /home/pi/vdesktop/vdesktop
.version
Lets Vdesktop keep track of what version it is to see when an update is available.rootmount/
Files contained in this directory are mounted to the guest's filesystem before boot, and unmounted after boot.src/
This directory holdslibsystemd-shared-246.so
, necessary for thesystemd-nspawn
binaries to work.
To do:
- Write up a more comprehensive set of instructions, and add come CLI flags.
- autologin to the guest, so the user doesn't have to do it manually.
- auto-detect default desktop session profile to correctly boot pi-top OS and Raspbian that doesn't have raspberrypi-ui-mods installed.
- Sync sound between host and guest, while avoiding pulseaudio.
- Sync clipboards between host and guest.
- display text at guest's default size instead of autoscaling to Xephyr's aspect ratio.
- display guest's default mouse pointer instead of the fallback Adwaita.