Skip to main content
Connections makes the desktop’s local Aiola server reachable from a paired phone or another Mac without exposing a reusable account token in the connection code. For setup steps, use Connect Mobile.

Architecture

Desktop local server

The desktop server binds to loopback until Central Settings → Connections → Allow LAN connections is enabled. It tries the mode’s preferred port and may select another available port, so clients must use the displayed/generated endpoint rather than hard-code a port.

LAN binding

Enabling Allow LAN connections restarts the local server with host 0.0.0.0; disabling it uses 127.0.0.1. Private IPv4 interfaces appear as Wi-Fi, Ethernet, or Local network endpoints with URLs shaped as follows:
LAN endpoints work on the same network and are marked Not encrypted in the app. The API is available only in the desktop app; an externally managed server must instead set AIOLA_SERVER_HOST and AIOLA_ALLOW_LAN in its service configuration and restart that service.

Tailscale

When a Tailscale IPv4 address exists, it is preferred over LAN and labeled Works from anywhere. Encrypted. A MagicDNS endpoint can follow it when a tailnet address and DNS name are available. The QR includes one address per reachability class, so the Tailscale hostname is omitted when the Tailscale IP already represents the same path.

Pairing bootstrap

Opening Central Settings → Connections → Devices → Add requests a bootstrap and renders a QR code. The implementation does not ask the user to type an address.
The bootstrap expires after 120 seconds. While the dialog remains open, the desktop refreshes it 10 seconds before expiry, with a minimum refresh delay of 5 seconds. Generate a new code replaces it on demand.

Device credentials

deviceId is optional during exchange and is capped at 200 characters when supplied. Re-pairing the same device ID replaces its previous credential. Raw bootstrap secrets, device credentials, and WebSocket tickets are returned only to callers; the server persists SHA-256 hashes and compares presented secrets with timing-safe equality. The credential store is written with file mode 0600. Responses that contain credentials set Cache-Control: no-store and Pragma: no-cache.

WebSocket tickets

A paired client presents its device credential in x-aiola-device-credential to mint a ticket. The ticket expires after 60 seconds and is single-use. The WebSocket upgrade supplies it as the ticket query parameter; consuming it binds the live connection to the paired device ID.

Failover

Version-3 clients walk baseUrls in the desktop-supplied order. They therefore try Tailscale before LAN when both exist, without asking the user to choose an address. The legacy baseUrl deliberately prefers LAN so a version-2 phone without Tailscale can pair on the same Wi-Fi.

Presence and status

The Devices list refreshes every 10 seconds and also refreshes when the window gains focus or becomes visible. Each paired row can show: Presence updates are persisted at most once per 60 seconds during normal activity.

Revocation

Choose Revoke access on a paired device and confirm Revoke access. Revocation invalidates its credential and already minted tickets, then immediately closes live connections for that device. The device can connect again only by pairing with a new QR code.

Platform notes

The desktop UI implements both macOS and Windows. On Windows, allow Aiola on private networks when Windows Firewall prompts; otherwise phones on the same Wi-Fi cannot connect. The paired client platform metadata supports iOS, Android, Web, Desktop, and Unknown.

Security considerations