Waydroid template

Original forum link
https://forum.qubes-os.org/t/23356
Original poster
apparatus
Created at
2024-01-01 07:51:54
Last wiki edit
2024-08-23 07:08:27
Revisions
33 revisions
Posts count
201
Likes count
57
Tags
template

This guide is for creating Waydroid template that can be used to create AppVMs based on it. The Android image is installed in template and applications and their configuration will be installed in AppVMs. This guide is for setting up minimal Waydroid template. You may want to install additional packages like GUI terminal, file manager, passwordless root etc.

Create Waydroid template qube

Install debian-12-minimal template using "Qubes Template Manager" tool if you don't have it already.

Update debian-12-minimal template using "Qubes Update" tool.

Clone debian-12-minimal and name it d12m-waydroid.

Add Waydroid App menu shortcut to the newly created qubes by default

To add the Waydroid App menu shortcut to the newly created qubes you need to set default-menu-items feature for Waydroid template. Open dom0 terminal and run this command to set the default App menu items for qubes based on this template:

qvm-features d12m-waydroid default-menu-items "Waydroid-Sway.desktop debian-xterm.desktop"

Configure Waydroid template

Start d12m-waydroid and open its root terminal using this command in dom0 terminal:

qvm-run -u root d12m-waydroid xterm &

All the commands in this guide must be run in d12m-waydroid qube root terminal if not stated otherwise.

To configure the Waydroid template you can use the easy way if you don't need to fine-tune your template or the advanced way if you want to fine-tune it.

Easy way to configure Waydroid template for Qubes OS 4.2 with in-VM kernel, audio support and Thunar installed.

Run this command in dom0 terminal to add support for in-VM kernel in PVH qubes:

sudo qubes-dom0-update grub2-xen-pvh
````
Run this command in `d12m-waydroid` root terminal to install the in-VM kernel support in template:
apt install -y linux-image-amd64 linux-headers-amd64 grub2 qubes-kernel-vm-support
Shutdown `d12m-waydroid` template.
Run this command in dom0 terminal to configure the Waydroid qube to use in-VM kernel:
qvm-prefs d12m-waydroid kernel pvgrub2-pvh
Start `d12m-waydroid` and open its root terminal using this command in dom0 terminal:
qvm-run -u root d12m-waydroid xterm &
Run these commands in `d12m-waydroid` root terminal:
apt install -y ca-certificates extrepo https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 extrepo enable waydroid apt update apt install -y sway qubes-core-agent-networking waydroid pipewire-qubes curl unzip build-essential libx11-dev libxtst-dev xclip wl-clipboard pip python3-venv x11-utils thunar qubes-core-agent-thunar mkdir -p /etc/systemd/system/waydroid-container.service.d cat << 'EOF' | tee /etc/systemd/system/waydroid-container.service.d/override.conf >/dev/null [Unit] ConditionPathExists=!/run/qubes/this-is-templatevm EOF curl --proxy http://127.0.0.1:8082/ --tlsv1.2 --proto =https --max-time 180 https://codeload.github.com/cdown/clipnotify/zip/refs/heads/master -o clipnotify-master.zip unzip -j clipnotify-master.zip -d clipnotify cd clipnotify mkdir -p /opt/bin sed -i "s|/usr/local|/opt|g" Makefile make make install echo 'export PATH="/opt/bin:$PATH"' >> /etc/profile.d/opt-bin.sh echo "exec /opt/bin/x11-wl-clip.sh" > /etc/sway/config.d/99-x11-wl-clip.conf mkdir -p /opt/bin cat << 'EOF' | tee /opt/bin/x11-wl-clip.sh >/dev/null

!/bin/bash

x11_wl='while DISPLAY=":0" clipnotify -s clipboard; do xclip -d ":0" -selection clipboard -o | wl-copy; done' wl_x11='wl-paste -nw xclip -d ":0" -selection clipboard' eval "${x11_wl}" &>/dev/null & eval "${wl_x11}" &>/dev/null pstree -A -p $$ | grep -Eow "[0-9]+" | xargs kill &>/dev/null EOF chmod +x /opt/bin/x11-wl-clip.sh python3 -m venv /opt/venv/pyclip source /opt/venv/pyclip/bin/activate pip install --proxy http://127.0.0.1:8082 pyclip deactivate echo 'export PATH="$PATH:/opt/venv/pyclip/bin"' >> /etc/profile.d/python-venv.sh echo 'export PYTHONPATH="$PYTHONPATH:/opt/venv/pyclip/lib/python3.11/site-packages"' >> /etc/profile.d/python-venv.sh cat << 'EOF' | tee /etc/systemd/system/waydroid-firewall.service >/dev/null [Unit] ConditionPathExists=!/run/qubes/this-is-templatevm PartOf=waydroid-container.service After=waydroid-container.service BindsTo=waydroid-container.service Requires=qubes-iptables.service After=qubes-iptables.service BindsTo=qubes-iptables.service [Service] Type=oneshot ExecStart=/usr/bin/bash -c "if (nft create chain ip qubes waydroid-input) &>/dev/null; then nft add rule ip qubes custom-input jump waydroid-input; fi" ExecStart=/usr/bin/bash -c "if (nft create chain ip qubes waydroid-forward) &>/dev/null; then nft add rule ip qubes custom-forward jump waydroid-forward; fi" ExecStart=/usr/sbin/nft add rule ip qubes waydroid-input iifname "waydroid0" meta l4proto {tcp, udp} th dport { 53, 67 } accept ExecStart=/usr/sbin/nft add rule ip qubes waydroid-forward iifname "waydroid0" oifgroup 1 accept ExecStart=/usr/sbin/nft add rule ip qubes waydroid-forward oifname "waydroid0" iifgroup 1 accept ExecStop=/usr/sbin/nft flush chain ip qubes waydroid-input ExecStop=/usr/sbin/nft flush chain ip qubes waydroid-forward RemainAfterExit=yes [Install] WantedBy=waydroid-container.service EOF systemctl daemon-reload systemctl enable waydroid-firewall.service echo "default_border none" > /etc/sway/config.d/94-disable-window-titlebar.conf perl -0777 -i -pe 's/(^\hbar\s|\v\hbar\s)({(?:(?>[^{}]+)|(?-1))*})//g' /etc/sway/config cat << 'EOF' | tee /opt/bin/sway-waydroid.sh >/dev/null

!/bin/bash

sway &>/dev/null & WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid first-launch &>/dev/null & for i in $(seq 1 3); do if xwininfo -name "wlroots - X11-1" &>/dev/null; then break fi sleep 1 done while xwininfo -name "wlroots - X11-1" &>/dev/null; do sleep 2 done WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid session stop &>/dev/null pstree -A -p $$ | grep -Eow "[0-9]+" | xargs kill &>/dev/null EOF chmod +x /opt/bin/sway-waydroid.sh cat << 'EOF' | tee /usr/share/applications/Waydroid-Sway.desktop >/dev/null [Desktop Entry] Type=Application Name=Waydroid-Sway Exec=/opt/bin/sway-waydroid.sh Icon=waydroid Categories=X-WayDroid-App; X-Purism-FormFactor=Workstation;Mobile; EOF cat << 'EOF' | tee /opt/bin/waydroid-install-apk >/dev/null

!/bin/sh

WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid app install $1 EOF chmod +x /opt/bin/waydroid-install-apk cat << 'EOF' | tee /opt/bin/waydroid-upgrade >/dev/null

!/bin/sh

https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid upgrade EOF chmod +x /opt/bin/waydroid-upgrade

Run this command to initialize Waydroid, Itll download VANILLA Android image:
https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init
Or this command for Waydroid image with GApps support:
https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init -s GAPPS
Run this command in dom0 terminal to sync the Waydroid template appmenu entries:
qvm-sync-appmenus d12m-waydroid
///

---

/// details | Advanced way to configure Waydroid template for fine-tuning.
# Install required packages for Waydroid

Waydroid needs Wayland so we will install `sway` Wayland compositor for it:
apt install -y sway
We also need the `qubes-core-agent-networking` package to enable networking in minimal qube:
apt install -y qubes-core-agent-networking
# Install Waydroid

Run these commands to install Waydroid:
apt install -y ca-certificates extrepo https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 extrepo enable waydroid apt update apt install -y waydroid apt install -y --no-install-recommends pipewire-pulse
The `pulseaudio` or `pipewire-pulse` package is required for Waydroid to work.
The installation is using `extrepo` package instead of downloading the shell script from waydro.id and running it.
This was suggested here:
 https://github.com/QubesOS/qubes-issues/issues/2233#issuecomment-2028278710
The link to the default installation process for reference:
 https://docs.waydro.id/usage/install-on-desktops#ubuntu-debian-and-derivatives

<details>
<summary>Original installation instructions if you prefer them:</summary>
apt install -y curl ca-certificates curl --proxy http://127.0.0.1:8082/ --tlsv1.2 --proto =https --max-time 180 https://repo.waydro.id | https_proxy=http://127.0.0.1:8082 bash apt install -y waydroid
</details>


Configure for Waydroid container not to start in TemplateVMs:
mkdir -p /etc/systemd/system/waydroid-container.service.d cat << 'EOF' | tee /etc/systemd/system/waydroid-container.service.d/override.conf >/dev/null [Unit] ConditionPathExists=!/run/qubes/this-is-templatevm EOF
# Initialize Waydroid

Run this command to initialize Waydroid, It'll download VANILLA Android image:
https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init
Or this command for Waydroid image with GApps support:
https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init -s GAPPS
# Install Waydroid clipboard support

## Configure automatic transfer of clipboard content between X11 and Wayland

We need to build and install clipnotify tool from sources to use it for receiving the X11 clipboard change events. You can build it in some other qube based on the same template and copy the built binaries to the `d12m-waydroid` qube and install them there to keep the `d12m-waydroid` template minimal or you can build it in the `d12m-waydroid` qube itself but you'll need to install additional packages for building.
This example is for the second option.

You can download the clipnotify sources in the Waydroid template directly or in some other qube and transfer them to the Waydroid template.
To download the sources directly in Waydroid template you'll need to install the additional packages unzip/git.
Since unzip/git probably won't be used ever again in the Waydroid qube you may want to keep the Waydroid template minimal then you can download the sources in some other qube and transfer them to the Waydroid template.

#### Option 1: Download the sources directly in Waydroid template
Download and extract the clipnotify sources in Waydroid template:
apt install -y curl unzip curl --proxy http://127.0.0.1:8082/ --tlsv1.2 --proto =https --max-time 180 https://codeload.github.com/cdown/clipnotify/zip/refs/heads/master -o clipnotify-master.zip unzip -j clipnotify-master.zip -d clipnotify
or using git:
apt install -y git git config --global http.proxy http://127.0.0.1:8082 git clone https://github.com/cdown/clipnotify.git git config --global http.proxy ""
#### Option 2: Download the sources in some other qube and transfer them to Waydroid template
Download and extract the clipnotify sources in some qube with network access:
curl https://codeload.github.com/cdown/clipnotify/zip/refs/heads/master -o clipnotify-master.zip unzip -j clipnotify-master.zip -d clipnotify
or using git:
git clone https://github.com/cdown/clipnotify.git
Transfer the clipnotify directory to `d12m-waydroid` qube:
qvm-copy clipnotify
---
After getting the sources in `d12m-waydroid` qube, move to the clipnotify sources directory in `d12m-waydroid` qube:
If you followed `Option 1: Download the sources directly in Waydroid template`:
cd clipnotify
If you followed `Option 2: Download the sources in some other qube and transfer them to Waydroid template`:
mv /home/user/QubesIncoming/*/clipnotify/ /home/user/ cd /home/user/clipnotify
---
Once you're in the sources directory, build and install clipnotify:
apt install -y build-essential libx11-dev libxtst-dev mkdir -p /opt/bin sed -i "s|/usr/local|/opt|g" Makefile make make install echo 'export PATH="/opt/bin:$PATH"' >> /etc/profile.d/opt-bin.sh
Install X11 and Wayland clipboard cli tools:
apt install -y xclip wl-clipboard
Configure sway to run script that will automatically transfer of clipboard content between X11 and Wayland on sway start:
echo "exec /opt/bin/x11-wl-clip.sh" > /etc/sway/config.d/99-x11-wl-clip.conf mkdir -p /opt/bin cat << 'EOF' | tee /opt/bin/x11-wl-clip.sh >/dev/null

!/bin/bash

x11_wl='while DISPLAY=":0" clipnotify -s clipboard; do xclip -d ":0" -selection clipboard -o | wl-copy; done' wl_x11='wl-paste -nw xclip -d ":0" -selection clipboard' eval "${x11_wl}" &>/dev/null & eval "${wl_x11}" &>/dev/null pstree -A -p $$ | grep -Eow "[0-9]+" | xargs kill &>/dev/null EOF chmod +x /opt/bin/x11-wl-clip.sh

## Install `pyclip` required by Waydroid
apt install -y xclip wl-clipboard pip python3-venv python3 -m venv /opt/venv/pyclip source /opt/venv/pyclip/bin/activate pip install --proxy http://127.0.0.1:8082 pyclip deactivate echo 'export PATH="$PATH:/opt/venv/pyclip/bin"' >> /etc/profile.d/python-venv.sh echo 'export PYTHONPATH="$PYTHONPATH:/opt/venv/pyclip/lib/python3.11/site-packages"' >> /etc/profile.d/python-venv.sh
Links for reference:
 https://docs.waydro.id/debugging/troubleshooting#failed-to-start-clipboard-manager-service
 https://github.com/waydroid/waydroid/issues/981#issuecomment-1778969058

# Configure firewall for Waydroid

For Qubes OS 4.2:
cat << 'EOF' | tee /etc/systemd/system/waydroid-firewall.service >/dev/null [Unit] ConditionPathExists=!/run/qubes/this-is-templatevm PartOf=waydroid-container.service After=waydroid-container.service BindsTo=waydroid-container.service Requires=qubes-iptables.service After=qubes-iptables.service BindsTo=qubes-iptables.service [Service] Type=oneshot ExecStart=/usr/bin/bash -c "if (nft create chain ip qubes waydroid-input) &>/dev/null; then nft add rule ip qubes custom-input jump waydroid-input; fi" ExecStart=/usr/bin/bash -c "if (nft create chain ip qubes waydroid-forward) &>/dev/null; then nft add rule ip qubes custom-forward jump waydroid-forward; fi" ExecStart=/usr/sbin/nft add rule ip qubes waydroid-input iifname "waydroid0" meta l4proto {tcp, udp} th dport { 53, 67 } accept ExecStart=/usr/sbin/nft add rule ip qubes waydroid-forward iifname "waydroid0" oifgroup 1 accept ExecStart=/usr/sbin/nft add rule ip qubes waydroid-forward oifname "waydroid0" iifgroup 1 accept ExecStop=/usr/sbin/nft flush chain ip qubes waydroid-input ExecStop=/usr/sbin/nft flush chain ip qubes waydroid-forward RemainAfterExit=yes [Install] WantedBy=waydroid-container.service EOF systemctl daemon-reload systemctl enable waydroid-firewall.service
For Qubes OS 4.1:
cat << 'EOF' | tee /etc/systemd/system/waydroid-firewall.service >/dev/null [Unit] ConditionPathExists=!/run/qubes/this-is-templatevm PartOf=waydroid-container.service After=waydroid-container.service BindsTo=waydroid-container.service Requires=qubes-iptables.service After=qubes-iptables.service BindsTo=qubes-iptables.service [Service] Type=oneshot ExecStart=/usr/sbin/iptables -I INPUT -i waydroid0 -p tcp -m multiport --dports 53,67 -j ACCEPT ExecStart=/usr/sbin/iptables -I INPUT -i waydroid0 -p udp -m multiport --dports 53,67 -j ACCEPT ExecStart=/usr/sbin/iptables -I FORWARD 2 -o eth0 -i waydroid0 -j ACCEPT ExecStart=/usr/sbin/iptables -I FORWARD 2 -i eth0 -o waydroid0 -j ACCEPT ExecStop=/usr/sbin/iptables -D INPUT -i waydroid0 -p tcp -m multiport --dports 53,67 -j ACCEPT ExecStop=/usr/sbin/iptables -D INPUT -i waydroid0 -p udp -m multiport --dports 53,67 -j ACCEPT ExecStop=/usr/sbin/iptables -D FORWARD -o eth0 -i waydroid0 -j ACCEPT ExecStop=/usr/sbin/iptables -D FORWARD -i eth0 -o waydroid0 -j ACCEPT RemainAfterExit=yes [Install] WantedBy=waydroid-container.service EOF systemctl daemon-reload systemctl enable waydroid-firewall.service
# Disable sway window title bar and status bar

This will make Waydroid run in fullscreen.

Disable sway window title bar:
echo "default_border none" > /etc/sway/config.d/94-disable-window-titlebar.conf
To disable sway status bar you need to edit the default sway config `/etc/sway/config` and remove or comment out the entire bar section.
Run this command to remove the `bar{}` block from the sway config:
perl -0777 -i -pe 's/(^\hbar\s|\v\hbar\s)({(?:(?>[^{}]+)|(?-1))*})//g' /etc/sway/config
Or do it manually:
nano /etc/sway/config
Find and remove/comment out the entire `bar{}` section e.g.:

Status Bar:

Read man 5 sway-bar for more information about this section.

bar { position top

# When the status_command prints a new line to stdout, swaybar updates.
# The default just shows the current date and time.
status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done

colors {
    statusline #ffffff
    background #323232
    inactive_workspace #32323200 #32323200 #5c5c5c
}

} ```

Create .desktop file to start Waydroid in sway using qube app menu

When you start sway it'll open the X11 window with sway but when you close this window it won't cause sway to exit. To not leave the sway with Waydroid running in background when you close the window we need to track this window and when it's closed we need to kill the sway and Waydroid processes. For this we need to install xwininfo tool: apt install -y x11-utils Create script to start the sway and Waydroid: ``` cat << 'EOF' | tee /opt/bin/sway-waydroid.sh >/dev/null

!/bin/bash

sway &>/dev/null & WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid first-launch &>/dev/null & for i in $(seq 1 3); do if xwininfo -name "wlroots - X11-1" &>/dev/null; then break fi sleep 1 done while xwininfo -name "wlroots - X11-1" &>/dev/null; do sleep 2 done WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid session stop &>/dev/null pstree -A -p $$ | grep -Eow "[0-9]+" | xargs kill &>/dev/null EOF chmod +x /opt/bin/sway-waydroid.sh Create the .desktop file to start Waydroid in sway using qube app menu: cat << 'EOF' | tee /usr/share/applications/Waydroid-Sway.desktop >/dev/null [Desktop Entry] Type=Application Name=Waydroid-Sway Exec=/opt/bin/sway-waydroid.sh Icon=waydroid Categories=X-WayDroid-App; X-Purism-FormFactor=Workstation;Mobile; EOF Run this command in dom0 terminal to sync the Waydroid template appmenu entries: qvm-sync-appmenus d12m-waydroid ```

Create script to install apk from the terminal

``` cat << 'EOF' | tee /opt/bin/waydroid-install-apk >/dev/null

!/bin/sh

WAYLAND_DISPLAY="wayland-1" XDG_SESSION_TYPE="wayland" DISPLAY=":1" waydroid app install $1 EOF chmod +x /opt/bin/waydroid-install-apk ```

Create script to upgrade Waydroid image in template from the terminal

``` cat << 'EOF' | tee /opt/bin/waydroid-upgrade >/dev/null

!/bin/sh

https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid upgrade EOF chmod +x /opt/bin/waydroid-upgrade ```

File manager in Waydroid qube

If you want to use the file manager in Waydroid qube then you need to install these packages in Waydroid qube template: apt install -y thunar qubes-core-agent-thunar

Enable sound for the Waydroid qube

To get the sound working in the Waydroid qube, for Qubes OS 4.2 you need to install pipewire-qubes package in Waydroid qube template: apt install -y pipewire-qubes In case you don't want for some Waydroid qubes to have sound (e.g. for protection against profiling threat and tracking or increasing attack surface) you can clone the d12m-waydroid template without sound to d12m-waydroid-sound template and install the sound package in d12m-waydroid-sound template. Then you can choose whatever the Waydroid qube should have the sound or not by setting the suitable template for it. ///



At this point the template is configured and ready to be used.

You can create a new app qube based on the d12m-waydroid and start the Waydroid-Sway app in this qube from Qubes OS menu to start the Waydroid inside this qube.

Additional information

Upgrade Waydroid image

To upgrade Waydroid image in the future you'll need to manually run this command in Waydroid template d12m-waydroid: waydroid-upgrade See above on how to create waydroid-upgrade command if it doesn't exist.

Install application in Waydroid

In a DisposableVM: * download an application apk (for example F-Droid from https://f-droid.org/) * qvm-copy it to your Waydroid AppVM or DisposableVM In your Waydroid AppVM or DisposableVM: * Run waydroid-install-apk (see above) with the path to the apk file e.g.: waydroid-install-apk /home/user/QubesIncoming/disp1629/F-Droid.apk

Change keyboard layout in Waydroid

Settings -> Languages & input -> Physical keyboard -> wayland_keyboard Add layouts. Change keyboard layout with Ctrl+Space.

Transfer files to/from Waydroid

The Waydroid internal storage is located in this path: /home/user/.local/share/waydroid/data/media/0/ You can copy files to/from there. Or you can set up shared folders like this: https://docs.waydro.id/faq/setting-up-a-shared-folder Or you can try to configure it like this: https://github.com/waydroid/waydroid/discussions/1107

Info about your system that apps in Waydroid will know

Apps installed in Waydroid will be able to see your CPU and system kernel. Since qubes use kernel provided by dom0 by default then apps in Waydroid can know that you're running Waydroid in Qubes OS (e.g. 6.7.3-1.qubes.fc37.x86_64). NOTE that if you've used the easy way to configure the Waydroid template then it's already configured to use the in-VM kernel. Use the following command if you've used the advanced way. To hide this you can use in-VM kernel instead: https://www.qubes-os.org/doc/managing-vm-kernels/#using-kernel-installed-in-the-vm Run this command in dom0 terminal to add support for in-VM kernel in PVH qubes: sudo qubes-dom0-update grub2-xen-pvh ```` Run this command in `d12m-waydroid` root terminal to install the in-VM kernel support in template: apt install -y linux-image-amd64 linux-headers-amd64 grub2 qubes-kernel-vm-support Shutdown `d12m-waydroid` template. Run this command in dom0 terminal to configure the Waydroid qube to use in-VM kernel: qvm-prefs d12m-waydroid kernel pvgrub2-pvh You'll need to reinitialize the Waydroid in template after switching the kernel. Start the Waydroid template with new kernel and run this command in its root terminal for VANILLA Android image: https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init -f Or this command for Waydroid image with GApps support: https_proxy=http://127.0.0.1:8082 http_proxy=http://127.0.0.1:8082 waydroid init -f -s GAPPS ```

Troubleshootings

1. From Application menu, choose AppVM / Waydroid-Sway, BUT nothing displayed.

Solution: Application menu, choose AppVM / xterm, in the displayed xterm, manually launch waydroid with this command to see the debug output: sed "s|&>/dev/null||g" /opt/bin/sway-waydroid.sh | source /dev/stdin

2. How to exit the AppVM ?

Solution: From dom0 Qubes Domain traybar, for the AppVM, choose Shutdown.