How to enable Shared Clipboard & Drag-and-Drop features inside VirtualBox with Whonix-LXQt-18.0.8.7 ?

Full Bash script from Filebin URL above:

#!/bin/bash
set -o nounset
set -o pipefail

UNIT_NAME='vbox-wayland-clipboard.service'
UNIT_PATH='/usr/lib/systemd/user/vbox-wayland-clipboard.service'
LAUNCH_PATH='/usr/libexec/vm-config-dist/vbox-wayland-clipboard-autostart'
DESK_PATH='/etc/xdg/autostart/vbox-wayland-clipboard.desktop'

red() { printf '\033[31m%s\033[0m\n' "$*"; }
grn() { printf '\033[32m%s\033[0m\n' "$*"; }
ylw() { printf '\033[33m%s\033[0m\n' "$*"; }

if [ "$(id -u)" -ne 0 ]; then
   red "ERROR: run as root in the 'sysmaint' boot mode:  sudo bash $0"
   exit 1
fi

search_dirs=(/etc/systemd/user /run/systemd/user /usr/lib/systemd/user \
             /usr/local/lib/systemd/user /root/.config/systemd/user)
for h in /home/*; do
   [ -d "$h/.config/systemd/user" ] && search_dirs+=("$h/.config/systemd/user")
done

echo "=== INSTALL ==="

echo "[1/6] clearing masks (/dev/null symlinks) and empty unit files ..."
for d in "${search_dirs[@]}"; do
   f="$d/$UNIT_NAME"
   if [ -L "$f" ] || { [ -e "$f" ] && [ ! -s "$f" ]; }; then
      echo "  removing $f"
      rm -f "$f"
   fi
done
systemctl --global unmask "$UNIT_NAME" 2>/dev/null || true

echo "[2/6] writing $UNIT_PATH ..."
install -d /usr/lib/systemd/user
cat > "$UNIT_PATH" <<'UNIT'
[Unit]
Description=VirtualBox shared clipboard for Wayland (opt-in, default-off)
ConditionVirtualization=oracle
ConditionEnvironment=WAYLAND_DISPLAY
StartLimitIntervalSec=10
StartLimitBurst=3

[Service]
Type=simple
ExecStart=/usr/bin/VBoxClient --foreground --wayland
Restart=on-failure
RestartSec=2s

[Install]
WantedBy=default.target
UNIT

echo "[3/6] writing $LAUNCH_PATH ..."
install -d /usr/libexec/vm-config-dist
cat > "$LAUNCH_PATH" <<'LAUNCH'
#!/bin/bash
set -o nounset
set -o pipefail
PATH=/usr/bin:/bin
unit='vbox-wayland-clipboard.service'
state="$(systemctl --user is-enabled "$unit" 2>/dev/null || true)"
case "$state" in
   enabled|enabled-runtime) ;;
   *) exit 0 ;;
esac
counter=0
while [ "$counter" -lt 50 ]; do
   systemctl --user show-environment 2>/dev/null | grep -q '^WAYLAND_DISPLAY=' && break
   counter="$(( counter + 1 ))"
   sleep 0.2
done
systemctl --user reset-failed "$unit" 2>/dev/null || true
exec systemctl --user start "$unit"
LAUNCH
chmod 755 "$LAUNCH_PATH"

echo "[4/6] writing $DESK_PATH ..."
cat > "$DESK_PATH" <<'DESK'
[Desktop Entry]
Type=Application
Name=VirtualBox shared clipboard for Wayland (opt-in)
Exec=/usr/libexec/vm-config-dist/vbox-wayland-clipboard-autostart
StartupNotify=false
NoDisplay=true
NotShowIn=QUBES;
DESK

echo "[5/6] Guest Additions device (/dev/vboxuser) on every boot ..."
systemctl enable --now virtualbox-guest-utils.service 2>/dev/null \
   || ylw "  virtualbox-guest-utils.service not found; loading module only."
echo vboxguest > /etc/modules-load.d/vboxguest.conf
modprobe vboxguest 2>/dev/null || true

echo "[6/6] enabling for ALL users ..."
systemctl daemon-reload
systemctl --global enable "$UNIT_NAME"

echo
echo "=== CHECKUP ==="
fail=0; warn=0

chk_file() {
   local p="$1" min="$2" sz
   if [ -L "$p" ]; then red "  FAIL  $p is a symlink (masked?)"; fail=$((fail+1)); return; fi
   if [ ! -f "$p" ]; then red "  FAIL  $p missing"; fail=$((fail+1)); return; fi
   sz="$(wc -c < "$p")"
   if [ "$sz" -lt "$min" ]; then red "  FAIL  $p is $sz bytes (empty/too small)"; fail=$((fail+1)); return; fi
   grn "  OK    $p ($sz bytes)"
}
chk_file "$UNIT_PATH"   100
chk_file "$LAUNCH_PATH" 100
chk_file "$DESK_PATH"    50

leftover=0
for d in "${search_dirs[@]}"; do
   f="$d/$UNIT_NAME"
   [ "$f" = "$UNIT_PATH" ] && continue
   if [ -L "$f" ] || { [ -e "$f" ] && [ ! -s "$f" ]; }; then
      red "  FAIL  leftover mask/empty: $f"; leftover=$((leftover+1)); fail=$((fail+1))
   fi
done
[ "$leftover" -eq 0 ] && grn "  OK    no leftover masks / empty unit files"

if [ -x "$LAUNCH_PATH" ]; then grn "  OK    launcher is executable"; else red "  FAIL  launcher not executable"; fail=$((fail+1)); fi

if [ -L "/etc/systemd/user/default.target.wants/$UNIT_NAME" ]; then
   grn "  OK    enabled for all users (default.target.wants symlink present)"
else
   ylw "  WARN  global enable symlink missing"; warn=$((warn+1))
fi

if command -v VBoxClient >/dev/null 2>&1; then
   grn "  OK    VBoxClient present ($(VBoxClient --version 2>/dev/null | head -n1))"
else
   red "  FAIL  /usr/bin/VBoxClient not found (Guest Additions missing)"; fail=$((fail+1))
fi

if lsmod 2>/dev/null | grep -q '^vboxguest'; then grn "  OK    vboxguest module loaded"; else ylw "  WARN  vboxguest module not loaded"; warn=$((warn+1)); fi
if [ -e /dev/vboxuser ]; then grn "  OK    /dev/vboxuser present"; else red "  FAIL  /dev/vboxuser missing (VBoxClient will fail VbglR3InitUser)"; fail=$((fail+1)); fi

echo
if [ "$fail" -eq 0 ]; then grn "RESULT: install OK ($warn warning(s))."; else red "RESULT: $fail problem(s), $warn warning(s) — fix the FAIL lines above."; fi
echo
echo "NEXT:"
echo "  1) On the HOST (normal user, VM powered off):"
echo "       VBoxManage modifyvm \"<vm-name-or-uuid>\" --clipboard-mode bidirectional"
echo "     and launch the VM as your NORMAL user, not root."
echo "  2) Reboot Whonix into the normal 'user' mode."
echo "  3) As 'user' (no sudo) verify:"
echo "       systemctl --user is-enabled $UNIT_NAME    # => enabled  (NOT masked)"
echo "       systemctl --user status    $UNIT_NAME     # => active (running)"

[ "$fail" -eq 0 ] && exit 0 || exit 1
1 Like

I would prefer to try updating virtualbox and the guest additions before trying these scripts. This is because in theory the updated virtualbox should have fixed the issue. But right now, I am stuck (see previous comment).

I have done a test of current Wayland shared clipboard compatibility using a non-Whonix Virtualbox virtual machine.

Virtualbox version- version 7.2.8, from Oracle, for Ubuntu Noble
Host- Zorin OS 18.1, running Wayland with GNOME
Guest- Fedora KDE 44, running Wayland on KDE Plasma.

Apparently, this version of Fedora comes with virtualbox guest additions version 7.2.6 already pre-installed. I was able to mount the virtualbox guest additions ISO, but I did not install them. This is because the installer warned me not to install them if I already have virtualbox guest addtions installed by the distribution. The installer said that I needed to uninstall the preexisting guest additions and then install the guest additions from the ISO. I am not completely sure on exactly how to do this, and I did not want to figure it out, since I could already see that bidirectional clipboard sharing was working on the current version of guest additions.

Conclusion-
Bidirectional clipboard sharing works perfectly between the Wayland host and the Wayland guest.
Additionally, mounting an ISO for the virtualbox guest additions works perfectly. However, I did not go through with installing the guest additions from it, since I could already see that the clipboard sharing was working with the pre-installed guest additions that came as part of the ISO.

Conclusion 2-
The clipboard sharing issue does not appear to be virtualbox-specific any longer. It is now Whonix-specific, unless my test was flawed in some way.

Please let me know if there is any flaw in my test or my conclusions. If you think it would be more appropriate to try a different guest distribution or follow different directions, please provide the directions so that I may conduct a correct test.

To conclude it’s Whonix specific, functionality testing is required on a Debian stable host with a Debian stable VM.

Fortunately, I have a spare laptop lying around. For my next test, I will install debian-lxqt from Debian -- Live install images on that laptop. I will install the latest version of Virtualbox from Oracle. Then I will install whonix-gateway, whonix-workstation and debian-lxqt as three virtual machines on it.

Hi, for unknown reason clipboard works from Vm to host, but not vice versa.

I`ve installed latest script version from filesharin service
both systemctl indicates that everything is working, so no idea whys that
Version 7.2.8 r173730 (Qt6.8.0 on xcb), host is Mint 22.3 cinnamon

Thank you for effort anyway, at least we are moving somewhere