Platforms — where WebX11 runs, and what each one gives up

One tree, one installer, three platform abstractions: a platform adapter (packages, paths, firewall, TLS), a service manager (systemd or the built-in supervisor) and render modes (bind address, ports, TLS).

Debian 12 supported — this host systemd certbot (letsencrypt) ufw + fail2ban
Ubuntu 22.04 / 24.04 supported — same adapter systemd certbot ufw + fail2ban
Termux → proot Debian supported, recommended on Android supervisor tunnel or none none (bind 127.0.0.1)
Termux native experimental — needs on-device acceptance supervisor tunnel or none none
Alpine / OpenRC deferred — busybox + OpenRC differences, no demand yet supervisor tunnel none
macOS / launchd deferred — dev-only, no server story supervisor none none

“Deferred” means the adapter contract already supports it (≈60 lines each) but nobody ships it. “Experimental” means the code paths exist and are simulated-tested, but no real device has passed deploy/test-termux.sh yet.


Servers (Debian / Ubuntu)

Unchanged from the server guide:

git clone --depth 1 https://git.webx11.duckdns.org/webx11.git /opt/webx11-src
cd /opt/webx11-src && cp deploy/wx11.conf deploy/wx11.conf.local   # edit domain/user/email
sudo deploy/install.sh --conf deploy/wx11.conf.local --source /opt/webx11-src --tls --admin you@example.com
sudo deploy/verify.sh --conf deploy/wx11.conf.local

See FORK.md for the full walkthrough, ports and secrets.


You need: Termux (F-Droid or GitHub build, not the stale Play Store one), ~3 GB free, a domain or DuckDNS name, and a tunnel for HTTPS.

# 1. On the phone, inside Termux
pkg update -y && pkg install -y proot-distro git curl termux-api
bash <(curl -fsSL https://webx11.duckdns.org/deploy/termux-bootstrap.sh)

Or from a clone:

git clone --depth 1 https://git.webx11.duckdns.org/webx11.git ~/webx11
bash ~/webx11/deploy/termux-bootstrap.sh          # creates the Debian userland

Inside the Debian login, edit deploy/wx11.conf.local and install:

WX11_DOMAIN="myphone.example.org"
WX11_USER="root"                 # proot has a single user; root is expected
WX11_ROOT="/root/webx11"         # or any path inside the proot filesystem
WX11_DATA="/root/.local/share/webx11"
WX11_STATE="/root/.local/share/webx11/federation"
WX11_LOG_DIR="/root/.local/share/webx11/log"
WX11_PLATFORM="debian"           # yes: inside proot this IS Debian
WX11_SERVICE_MANAGER="supervisor"  # proot has no systemd
WX11_BIND_ADDR="127.0.0.1"
WX11_HTTP_PORT="8080"
WX11_TLS_MODE="tunnel"
WX11_TUNNEL_ID="<uuid from `cloudflared tunnel create`>"
WX11_ENABLE_UBAN="0"             # optional: heavy for a phone
bash deploy/install.sh --conf deploy/wx11.conf.local --source /root/webx11-src --platform debian
bash deploy/verify.sh --conf deploy/wx11.conf.local

Then the tunnel (HTTPS terminates at Cloudflare, nginx stays on 127.0.0.1:8080):

cloudflared tunnel login
cloudflared tunnel create webx11        # prints the UUID → WX11_TUNNEL_ID
cloudflared tunnel route dns webx11 myphone.example.org
cloudflared tunnel --config /root/.local/share/webx11/cloudflared/config.yml run

Keep it alive: termux-wake-lock in the Termux session, and disable battery optimisation for Termux in Android settings (Settings → Apps → Termux → Battery → Unrestricted).


Android / Termux — mode B (native, experimental)

No proot. Everything lives in $PREFIX and $HOME, nginx and Python come from pkg, services run under the supervisor.

bash deploy/termux-bootstrap.sh --native
git clone --depth 1 https://git.webx11.duckdns.org/webx11.git ~/webx11-src
cd ~/webx11-src
cp deploy/wx11.conf deploy/wx11.conf.local

Minimal native config:

WX11_DOMAIN="myphone.example.org"
WX11_USER="$(whoami)"            # the Termux app user
WX11_ROOT="$HOME/webx11"
WX11_DATA="$HOME/.local/share/webx11"
WX11_STATE="$HOME/.local/share/webx11/federation"
WX11_LOG_DIR="$HOME/.local/share/webx11/log"
WX11_PLATFORM="termux"
WX11_SERVICE_MANAGER="supervisor"
WX11_BIND_ADDR="127.0.0.1"
WX11_HTTP_PORT="8080"
WX11_HTTPS_PORT="8443"           # unused in tunnel/none mode
WX11_TLS_MODE="none"             # or tunnel
WX11_PREFIX="$PREFIX"
WX11_PHP="0"                     # strips the 7 php-fpm locations
WX11_ETC_DIR="$PREFIX/etc/webx11"
WX11_UBAN_DIR="$HOME/.local/share/webx11/uban"
WX11_MONITOR_DIR="$PREFIX/bin/webx11-monitor"
WX11_ENABLE_UBAN="0"
bash deploy/install.sh --conf deploy/wx11.conf.local --source "$HOME/webx11-src" --platform termux
bash deploy/lib/svc.sh --conf deploy/wx11.conf.local start
bash deploy/test-termux.sh        # acceptance gate — must print TERMUX ACCEPTANCE PASSED

Before claiming support, run the one-page device runbook: TERMUX-CHECKLIST.md — it has the exact commands, the pass criteria and a troubleshooting table.

What native Termux gives up

Privileged ports (80/443) yes no Android apps cannot bind < 1024
certbot yes no needs privileged ports + nginx plugin
fail2ban yes no no iptables without root
ufw yes no same
php-fpm yes no 7 fastcgi_pass blocks stripped (WX11_PHP=0)
systemd yes no replaced by the supervisor
logrotate yes no supervisor rotates at 5 MB
cron /etc/cron.d no supervisor runs the same 6-job schedule
bcrypt apt package maybe pkg install python-bcrypt, else auth is unavailable
Always-on yes fragile Doze kills processes without a wake lock

Android survival checklist

  1. termux-wake-lock before svc.sh start; termux-wake-unlock after svc.sh stop.
  2. Battery optimisation Unrestricted for Termux.
  3. After a reboot, services do not come back by themselves. Either use the Termux:Boot add-on with ~/.termux/boot/webx11.sh (#!/data/data/com.termux/files/usr/bin/sh → termux-wake-lock; ~/webx11/deploy/lib/svc.sh --conf ~/webx11/deploy/wx11.conf start), or start it by hand.
  4. Watch ~/.local/share/webx11/log/supervisor.log — every respawn is logged with a status.

Federation on a phone


Verifying a platform

# server
sudo deploy/verify.sh --conf deploy/wx11.conf.local

# anything without systemd (honest FAIL where the manager is absent)
bash deploy/verify.sh --conf deploy/wx11.conf.local --platform termux

# Android acceptance (the only proof that counts for native Termux)
bash deploy/test-termux.sh       # see TERMUX-CHECKLIST.md for the full runbook

verify.sh never fakes a check: on a platform without fail2ban/ufw it prints SKIP with the reason instead of failing, and the service block follows the configured service manager.

Test harnesses (run on a Linux host, no phone needed)

bash deploy/tests/supervisor-test.sh   # real respawn, cron matching, log rotation
bash deploy/tests/termux-sim.sh        # asserts the Termux adapter never calls root-only tools

They prove the platform-agnostic mechanics. They do not prove Android — only deploy/test-termux.sh on a device does that.