Posted on

Waypipe Guide

Waypipe forwards Wayland applications over SSH. Run apps on a remote Linux or Mac machine and display them on your device running Wawona.


Platform Overview

PlatformSSH TransportBuffer PathStatus
macOSOpenSSH (process spawn)IOSurface → MetalWorking
iOSlibssh2 (in-process)IOSurface → MetalWorking
AndroidDropbear SSH (fork/exec)SHM → VulkanWorking

Quick Start

macOS (Command Line)

With Wawona running:

export XDG_RUNTIME_DIR="/tmp/wawona-$(id -u)"
export WAYLAND_DISPLAY="wayland-0"

nix run .#waypipe -- ssh user@remote-host weston-terminal

iOS / Android (In-App)

  1. Open WawonaSettingsWaypipe (or SSH)
  2. SSH Host: IP address or hostname of the remote machine
  3. SSH User: Your username on the remote
  4. SSH Password: Your login password (or configure Public Key auth)
  5. Remote Command: The app to run, e.g., nix run ~/Wawona#weston-terminal
  6. Tap Start Waypipe

Prepare a Remote Mac

bash scripts/prepare_mac_remote.sh

This checks that Remote Login (SSH) is enabled, Python 3 is installed, and Waypipe is available.


Remote Command Examples

CommandDescription
nix run ~/Wawona#weston-terminalWeston Terminal (Wawona repo on remote)
weston-terminalWeston Terminal (if installed)
footFoot terminal
nix run ~/Wawona#westonFull Weston compositor
gearyGeary email client
gnome-calculatorGNOME Calculator

How It Works

macOS

Waypipe runs as a local process that connects to Wawona's Wayland socket, then spawns an SSH connection to the remote host. The remote waypipe server captures Wayland protocol data and forwards it through the SSH tunnel.

Buffer sharing uses IOSurface for zero-copy Metal rendering.

iOS — libssh2 + Streamlocal

iOS can't spawn processes, so Wawona uses libssh2 in-process with streamlocal-forward@openssh.com:

iOS App                        SSH                          Remote
──────────────────────────────────────────────────────────────────
1. connect_ssh2()
   ├── TCP connect + handshake + auth
   ├── streamlocal-forward  ──────►  sshd creates
   │   (path=/tmp/wp-XXX.sock)       /tmp/wp-XXX.sock
   │
   ├── exec channel:  ──────────►  waypipe --socket
   │   waypipe server -- <app>       /tmp/wp-XXX.sock
   │                                 server -- <app>
   │
   └── bridge thread: pumps data
       forwarded channel ↔ local socket

Remote requirements: Stock waypipe + OpenSSH ≥ 6.7. No socat, nc, or patched tools needed.

Android — Dropbear SSH

Android bundles Dropbear SSH (lightweight SSH client) as a static ARM64 executable:

  1. SSH binaries packaged as libssh_bin.so / libsshpass_bin.so in the APK
  2. Android extracts them at install time
  3. Waypipe Rust backend exposes waypipe_main() for JNI
  4. SSH bridge thread: fork()exec(dbclient) with SSHPASS env

Compression

OptionSpeedRatioUse Case
noneFastest1:1Local network
lz4 (default)FastGoodGeneral use
zstdSlowerBetterSlow connections

Configure in Settings → Waypipe → Compression.


Troubleshooting

IssueFix
"streamlocal-forward failed"Check AllowStreamLocalForwarding in sshd_config (default: yes)
"Timed out waiting for channel"Verify waypipe is installed and in PATH on remote
"Missing Wayland socket"Start a Wayland compositor on the remote first
Remote command not foundUse full path: nix run ~/Wawona#weston-terminal
Black screen after connectCheck that the remote app supports Wayland