Desktops & the X11 viewer
Podroid includes a built-in VNC viewer that connects to Xvnc running inside the VM on display :0 (port 5900, auto-forwarded). Tap the monitor icon in the terminal's top bar to open it.
Installing a desktop
Alpine ships setup-desktop as part of the alpine-conf package. It is an interactive helper that creates a user and installs a desktop environment of your choice. Run it in the Podroid terminal:
# setup-desktop
Follow the prompts to pick a desktop and create a user account. The script handles the apk add steps for you.
setup-desktop installs lightdm with a greeter and enables it (rc-update add lightdm), and the Xfce and MATE choices also pull in Firefox, so the download is a good deal larger than the minimal example below. In Podroid the display manager is harmless but useless: the guest kernel has no graphics device, so lightdm starts at boot and idles without ever launching an X server, while Xvnc keeps display :0. Run rc-update del lightdm afterwards to keep boot clean, or use the "Complete example" section below for the minimal apk add route instead.
The built-in viewer speaks RFB (VNC), so it connects to an X11 display. It cannot show a Wayland compositor. Use Xfce, LXQt, or MATE - they run on X11 and render correctly. KDE Plasma 6, GNOME, and Sway are Wayland on Alpine and will not appear in the viewer, even after launching them.
Launching a desktop
You do not need a display manager. Xvnc is already the X server on :0, and DISPLAY=:0 is preset in the environment. After installing a desktop, start it directly from the terminal:
# Xfce example
$ startxfce4 &
# LXQt example
$ startlxqt &
# MATE example
$ mate-session &
Xvnc is already the X server on :0, so a display manager such as lightdm is not needed and does nothing useful here: the guest kernel has no graphics device, so it never starts an X server of its own. If one got enabled, for example by setup-desktop, disable it with rc-update del lightdm.
Single GUI apps
You do not need a full desktop to run individual X11 applications. Install any X11 app and launch it directly; DISPLAY=:0 is already exported:
# apk add firefox
$ firefox &
The app will appear in the viewer as soon as it opens a window.
Complete example: Xfce from a fresh VM
Every command in order, starting from a VM you have just booted for the first time. Run these in the Podroid terminal:
# 1. install the desktop (about 400 MB)
# apk add xfce4 xfce4-terminal
# 2. start it; it keeps running in the background
# startxfce4 &
Now tap the monitor icon in the terminal's top bar. The desktop appears in the built-in viewer. There is nothing to configure, no VNC server to install, and no ports to forward: Xvnc is already running as the X server and Podroid already forwards it to the viewer.
Connecting from another computer
The built-in viewer is the intended way to use the desktop, and it needs no setup. Reaching that same desktop from a PC takes one extra step, because of a deliberate safety decision.
The X session inside the VM runs with no password (-SecurityTypes None). To stop that from becoming an open desktop for everyone on your network, Podroid forwards port 5900 to 127.0.0.1 on the phone only, so nothing outside the phone can dial it. Host ports 5900 and 4713 are reserved for this reason, and adding your own forwarding rule on them is refused with "Port 5900 is reserved for the in-app desktop".
The recommended way in is an SSH tunnel, which carries the desktop over the SSH connection you already have. Enable SSH in Podroid's settings first, then run this on your computer:
# replace with the phone's address shown on the Status screen
$ ssh -p 9922 -L 5900:127.0.0.1:5900 root@<phone-ip>
Leave that connection open, then point any VNC client at localhost:5900. The desktop is encrypted in transit, needs no extra forwarding rule, and works from whichever network the phone and PC share.
A phone on mobile data that is also sharing its connection has more than one address at once, and only one of them reaches your PC. The Status screen lists every address the phone can be reached on. Use the one on the same network as the computer you are connecting from.
If you would rather expose VNC directly instead of tunnelling, add a port forward from a host port other than 5900 (for example 5901) to guest port 5900, then connect to phone-address:5901. Be aware of what that means: the session has no password, so anyone on that network can open your desktop. Only do this on a network you trust.
Connecting with RDP instead
An SSH tunnel assumes the other computer has an SSH client. Older Windows machines often do not, while every one of them has a Remote Desktop client built in. Alpine has xrdp in its repositories, so the guest can speak RDP as well. Nothing needs to be installed on the Windows side.
This is not shipped in the VM image, and it does not replace the built-in viewer, which keeps working exactly as before. It is a few commands inside the guest.
# inside the VM, over SSH or the in-app terminal
# apk add xrdp openssl
# plus a desktop for the session to start, if you have not installed one
# already. openbox and xterm are the smallest pair that works.
# apk add openbox xterm
# xrdp needs a TLS certificate. Without one it falls back to legacy RDP
# security, which current Windows and FreeRDP clients refuse to complete.
# cd /etc/xrdp
# openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout key.pem -out cert.pem -subj "/CN=podroid"
# chmod 600 key.pem
# xrdp offers its Xorg backend first and Alpine ships no xorgxrdp, so a
# login would fail with "X server could not be started". Pin it to Xvnc.
# sed -i 's/^autorun=$/autorun=Xvnc/' /etc/xrdp/xrdp.ini
# tell the session what to start. On Alpine, xrdp runs the system xinitrc,
# which reads ~/.xinitrc; it never looks at ~/.xsession. Start the window
# manager FIRST and let it launch the terminal: a program started before
# openbox is up can end up permanently invisible, which reads as a black
# or empty desktop.
# echo 'exec openbox-session' > /root/.xinitrc
# mkdir -p /root/.config/openbox
# echo 'xterm &' > /root/.config/openbox/autostart
# both services are required: xrdp speaks the protocol, sesman logs you in
# rc-service xrdp-sesman start
# rc-service xrdp start
# rc-update add xrdp-sesman
# rc-update add xrdp
Then add a port forward in Settings → Port forwards from host port 3389 to VM port 3389, and connect from the PC to phone-address:3389 with the guest's own credentials: user root, password podroid unless you changed it. Be patient on the first login: on the QEMU backend the session can take a minute or more to start, and until openbox is up the screen is plain black with only a mouse cursor. The dark gray desktop appearing means the session is ready; the terminal from the autostart follows, and the right-click menu works from that point on.
The guest sets DISPLAY for you so that programs started from the terminal appear on the in-app desktop, and xrdp reads the same profile before starting your session. Older images set it unconditionally, which sends an RDP session's windows to the phone's screen and leaves the remote desktop black. Check with grep DISPLAY /etc/profile.d/podroid-x11.sh: if it reads export DISPLAY=:0 rather than : "${DISPLAY:=:0}", run sed -i 's/^export DISPLAY=:0$/: "${DISPLAY:=:0}"; export DISPLAY/' /etc/profile.d/podroid-x11.sh once.
Port forwards bind every interface, so an RDP listener is reachable by anyone on the same network. Unlike the VNC path above, this one does ask for a password, which is worth having. It is also the guest's well-known default password, which is not. Run passwd in the guest first.
The session you get this way is its own desktop, separate from the one the in-app viewer shows, and it survives a disconnect: reconnecting drops you back into the same windows. That is usually what you want from a PC. If you would rather see the same screen as the phone, add this section to /etc/xrdp/xrdp.ini and set autorun=podroid instead of autorun=Xvnc, which points RDP at the running X session rather than starting a new one:
[podroid]
name=Podroid desktop
lib=libvnc.so
ip=127.0.0.1
port=5900
username=na
password=na
Two things trip people up here. First, xrdp.ini is read by the xrdp daemon itself, so the change is not live until you run rc-service xrdp restart; restarting only xrdp-sesman does nothing for it. Second, this mirrors whatever the phone's own session is currently showing: if the in-app desktop has nothing running, the mirror is an empty black screen. Open the in-app desktop (or start something on it) and the mirror shows the same picture.
That variant inherits the in-app session's lack of a password, so it hands the desktop to anyone who can reach port 3389. Use it over an SSH tunnel, or on a network you control, and prefer the authenticated login above otherwise.
Viewer settings reference
Tap the tune/gear icon in the X11 viewer's top bar to open viewer settings.
Resolution
Controls what resolution Xvnc presents to the desktop. Uses the RFB ExtendedDesktopSize extension to resize live without restarting the VM.
- Match viewport - the desktop tracks your screen size exactly, resizing whenever the viewer resizes. Pixel-perfect on most devices.
- Preset - fixed resolutions: 720p, 900p, 1080p, or 1440p. Pick a lower preset for smoother rendering on heavy desktops over a high-DPI display.
- Custom - enter any width and height in pixels.
Touch input
- Direct - tap to click at the point you touch; drag to drag; long-press activates drag-lock. Intuitive for touch-first use.
- Trackpad - relative pointer: your finger position moves the cursor rather than placing it. Sensitivity is adjustable (0.5x to 3.0x) with optional pointer acceleration.
In both modes: two-finger tap sends a right-click; two-finger drag scrolls.
External input
A connected hardware keyboard passes through fully, including Ctrl, Alt, Shift, and composed shortcuts (e.g. Ctrl+L in a browser). An external mouse's scroll wheel scrolls, and all three buttons map to their X11 equivalents.
Other settings
| Setting | Notes |
|---|---|
| Fullscreen | Hides the system UI. Back exits fullscreen. |
| Rotation lock | Auto, Landscape, or Portrait. Auto follows the device sensor. |
| Extra-keys bar | Show or hide the keyboard shortcut bar below the viewer. |
| Server DPI | 96 to 192. Tells Xvnc what DPI to report to apps. Takes effect on the next VM start. |
| Audio | PulseAudio streams PCM from the VM to the app over port 4713. Toggle to enable or disable. |
With an external mouse, right-click currently exits fullscreen instead of reaching the desktop. Android maps the mouse's right button to the Back action. Two-finger touch right-click works correctly as a workaround. A fix is planned.
The viewer currently uses uncompressed Raw encoding (ZRLE was disabled after it desynced on complex content). On a high-DPI phone, selecting the 720p or 900p preset reduces the amount of screen data transferred each frame and noticeably improves smoothness on heavy desktops. See the Performance page for general tuning advice.
Podroid is free software (GPL). Docs for v1.2.8. Found something inaccurate? Open an issue.