# 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).

| Platform | Status | Service manager | TLS | Firewall |
|---|---|---|---|---|
| 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:

```bash
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`](FORK.md) for the full walkthrough, ports and secrets.

---

## Android / Termux — mode A (proot Debian, recommended)

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.

```bash
# 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:

```bash
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:

```bash
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
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`):

```bash
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
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:

```bash
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
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`](TERMUX-CHECKLIST.md)** — it has the exact commands, the pass criteria and
a troubleshooting table.

### What native Termux gives up

| Capability | Server | Termux native | Why |
|---|---|---|---|
| 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

- `node.json.url` **must** be `https://…`. With `WX11_TLS_MODE=none` the instance works locally
  but peers will refuse the URL — by design, the SSRF guard requires https.
- Use tunnel mode (Cloudflare) for reachability behind CGNAT. The tunnel hostname is your
  public origin; nothing else needs to be exposed.
- Peer health is one HMAC handshake every 15 minutes (~1 KB); searches are only sent when a
  visitor searches. Mobile data cost is negligible.
- A phone that sleeps will be marked `degraded` after 3 failed handshakes and recover on the
  next successful one — that is expected behaviour, not a bug.

---

## Verifying a platform

```bash
# 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
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.
