Use cases
What Podroid is genuinely good for, what it does with caveats, and what to avoid - with honest notes on TCG performance throughout.
Self-hosting via containers
Rootless Podman, Docker and LXC are all ready the moment the VM boots: Podman needs no daemon, and the Docker and LXC services are enabled in the default runlevel, so they start automatically. You can run any ARM64 container image from Docker Hub or GHCR.
Port forwarding rules (see Networking & ports) expose guest ports on the phone's real IP. Use a host port above 1024 for anything you expose, because an unprivileged Android app cannot bind host ports below 1024.
If you have never run a container before, start with this. It serves one page and proves the whole chain works, from the container to your phone's browser:
# 1. write a page for it to serve
$ mkdir -p ~/site && echo '<h1>Hello from Podroid</h1>' > ~/site/index.html
# 2. run nginx, serving that folder on guest port 80
$ podman run -d --name hello \
-p 8080:80 \
-v ~/site:/usr/share/nginx/html:ro \
docker.io/library/nginx:alpine
# 3. check it from inside the VM
$ wget -qO- http://localhost:8080
To open it from the phone's browser or another device, add a port forward for host port 8080 in Settings, then visit http://<phone-address>:8080. The Status screen lists the phone's addresses; use the one on the same network as the device you are browsing from.
The same pattern scales to real services:
# Pi-hole (DNS + ad-blocking)
$ podman run -d --name pihole \
-p 8080:80 -p 5353:53/tcp \
-e TZ=Europe/London \
docker.io/pihole/pihole:latest
# Gitea (self-hosted Git)
$ podman run -d --name gitea \
-p 3000:3000 -p 2222:22 \
-v gitea-data:/data \
docker.io/gitea/gitea:latest-linux-arm64
# Vaultwarden (Bitwarden-compatible password server)
$ podman run -d --name vaultwarden \
-p 8888:80 \
-v vaultwarden-data:/data \
docker.io/vaultwarden/server:latest
# code-server (VS Code in the browser)
$ podman run -d --name code-server \
-p 8443:8443 \
-v "$HOME/.config:/home/coder/.config" \
-v "$PWD:/home/coder/project" \
ghcr.io/coder/code-server:latest \
--bind-addr 0.0.0.0:8443 /home/coder/project
Services backed by a JVM - Gitea's built-in runner, Jenkins, Gradle builds inside code-server, and anything running on Java or Kotlin - are noticeably slow on the QEMU TCG backend. JVM startup alone can take 10-30 seconds. If you rely on these services heavily, enabling the AVF backend on a Pixel device makes a large practical difference.
Backing up containers
The Backup screen (the home screen's Backup button, or Settings) builds shell commands for exporting a container, saving an image, listing existing backups, or backing up everything at once. It doesn't run anything itself - it builds the command and you copy it into the terminal.
# The screen builds a command like this one, which you paste into the terminal
$ podman export pihole -o /mnt/downloads/Podroid/backups/pihole.tar
It uses a podroid-backup helper when one is present in the guest, and falls back to plain podman save / podman export otherwise. Backups are written inside the guest to /mnt/downloads/Podroid/backups. With Downloads folder sharing enabled, that path appears on the phone under Download/Podroid/backups; with sharing off, backups stay inside the VM at /var/backups/podroid.
Checking VM and phone status
The Status screen (the home screen's Status button, or the monitor icon in the header) gives a single view of both sides of the system: phone RAM, storage, CPU cores, and load average (when readable) alongside the VM's status, uptime, active backend (QEMU or AVF), and the phone's IP. The backend shown is the one actually running: when a forced AVF selection falls back to QEMU, Status says so explicitly ("AVF unavailable, running QEMU").
It also shows a VM CPU-load graph, available on the QEMU backend only - on AVF the screen shows a note that the graph is QEMU-only - plus the VM's allocated RAM, CPU cores, disk-image usage, and bandwidth limit.
Local Linux development environment
The Alpine guest is a full persistent Linux system. Install your toolchain once and it survives every reboot on the ext4 overlay.
# Install a development toolchain
$ apk add git nodejs npm python3 py3-pip go gcc musl-dev make
# SSH in from a laptop on the same Wi-Fi
$ ssh root@<phone-ip> -p 9922
Once SSH is working, VS Code Remote-SSH and JetBrains Gateway both connect without any plugin beyond their standard remote-development extension. The phone acts exactly like any remote Linux server from the laptop's point of view.
Persistence is handled by the overlayfs stack: all writes go to the ext4 storage.img. Packages you install with apk add, files you create, services you enable with rc-update add - all survive reboots and app updates.
Text editing, shell scripting, Git operations, and short Python scripts are comfortable on TCG - these workloads spend most time on IO and memory, where the emulation overhead is low. Long compilations (LLVM, Linux kernel, large Rust projects) will be painfully slow; for those, prefer cross-compiling on the laptop and copying binaries over SSH.
GUI Linux apps
The in-app X11 viewer connects to an Xvnc display in the guest. Install a desktop environment or individual X11 apps and they appear directly in the viewer with touch, external keyboard and mouse, and audio forwarding.
# Install XFCE and common accessories
$ apk add xfce4 xfce4-terminal mousepad ristretto xfce4-taskmanager
# Install Firefox (ARM64 build)
$ apk add firefox
# Install GIMP
$ apk add gimp
See Desktops & X11 viewer for how to start and configure the Xvnc session. Note that only X11 desktop sessions render correctly; Wayland sessions (GNOME on Wayland, Plasma Wayland, sway) do not render in the viewer - see Limitations.
Learning Linux and containers
Podroid gives you a real Linux kernel with cgroup v2, network namespaces, overlayfs, netfilter/nftables, and OpenRC - all on hardware you already own. Nothing is simulated or mocked; the same kernel features that production servers use are present and explorable.
# Inspect the cgroup v2 hierarchy
$ mount | grep cgroup
$ ls /sys/fs/cgroup/
# Run a container and inspect its namespaces
$ podman run --rm -it alpine sh
$ ls -la /proc/1/ns/
# Examine the overlayfs mount used by Podman's graph driver
$ podman info | grep graphDriver
$ mount | grep overlay
# Explore OpenRC service management
$ rc-status
$ rc-update add sshd default
$ rc-service sshd start
# Inspect nftables rules added by Podman for port forwarding
$ nft list ruleset
Because this is a real VM, experiments that would break a shared server are safe here - a factory reset restores a clean Alpine image in under a minute. You can deliberately crash the kernel, fill the disk, or misconfigure networking and recover immediately.
Lightweight CLI tools and scripts
Running cron jobs, personal bots, data processing scripts, or static site generators is one of the most practical uses on TCG. These workloads are typically IO-bound or short-lived, so the 5-20x CPU penalty of TCG emulation is barely noticeable compared to the time spent waiting on network or disk.
# Install common CLI tooling
$ apk add curl jq rsync htop tmux vim ffmpeg yt-dlp
# Run a Python script on a schedule
$ echo "*/15 * * * * python3 /root/sync.py" | crontab -
$ rc-update add crond default && rc-service crond start
What works poorly
- Wayland desktops - GNOME Wayland, Plasma Wayland, sway, and Hyprland do not render in the X11 viewer. Use XFCE or another X11 session instead.
- Heavy compilation on TCG - building LLVM, the Linux kernel, or large Rust crates inside the VM is feasible but very slow (hours, not minutes). Cross-compile on a real machine and copy the result over SSH.
- x86 Docker images - pulling an
linux/amd64image runs it under double emulation (QEMU TCG emulating ARM64 guest, which then runs QEMU user-mode emulating x86). Expect 50-100x slowdown. Always preferlinux/arm64images. - A full desktop environment at 512 MB RAM - XFCE with a browser open will page heavily into ZRAM swap at 512 MB. Set RAM to 1 GB or more in Settings if you plan to run a desktop regularly.
If TCG is too slow for your workload, the most impactful step is switching to the AVF backend on a Pixel 8 or later - it provides near-native CPU speed. Bumping RAM above 1 GB also helps containers and desktops avoid swap pressure. The Performance & why it's slow page covers every tuning option in detail. For hard limits such as Wayland, see Limitations & troubleshooting.
Podroid is free software (GPL). Docs for v1.2.8. Found something inaccurate? Open an issue.