Remote teleop is sensitive to latency. Tailscale usually connects the two devices directly. When it can’t, it sends traffic through a relay, which adds latency. You get the best results on connections with a low round-trip time.
Sideload Tailscale on the Quest
The Quest runs Horizon OS, which is based on Android, so you can install Tailscale’s Android app from its APK file.1
Enable Developer Mode on the Quest
- Open the Meta Quest app on your phone, with your headset connected.
- Go to Menu → Devices, select your headset, then Headset Settings → Developer Mode, and turn it on. You may need to create a free Meta “organization” first, which takes a minute.
- Restart the headset.
2
Download the Tailscale APK
Download the Android APK from Tailscale’s package server at pkgs.tailscale.com/stable/#android onto your computer.
3
Sideload it with SideQuest
The easiest tool is SideQuest:
- Install SideQuest on your computer from sidequestvr.com.
- Connect the Quest to your computer with a USB-C cable.
- Put the headset on and accept the Allow USB debugging? prompt. Check Always allow from this computer.
- In SideQuest, press Install APK from folder and select the Tailscale APK.
adb install tailscale.apk.4
Launch and log in
Tailscale doesn’t appear in your normal app grid. Find it under Unknown Sources in your Quest app library (the folder icon with a ”?”). Open it, sign in to your tailnet, and approve the VPN connection prompt.
A sideloaded Tailscale doesn’t update itself. Sideload a newer APK from time to time.
Connect the robot’s computer to the same tailnet
On the robot’s computer, install Tailscale and start it (see Tailscale’s Linux install docs):100.x.y.z IP or its MagicDNS name. Run tailscale ip -4, or check the Tailscale admin console.
Drive the robot
With both devices on the tailnet, use teleoperation as usual, with the Tailscale address instead of the local one:1
Start teleop on the robot's computer
Start it from the control panel or with
axol teleop, as for local teleop.2
Check that Tailscale is connected in the headset
Open the Tailscale app on the Quest and check that the VPN is on.
3
Enter the Tailscale address in the VR app
Open the VR app at axol.almond.bot on the headset. In the Connect field, enter the robot computer’s Tailscale IP or MagicDNS name instead of its local IP. Press Connect, then Start.
4
Authorize the certificate
As with local teleop, accept the self-signed certificate once. Tap Authorize certificate when prompted, or open
https://<tailscale-address>:8000 in the headset browser and continue past the warning. See Authorize the TLS certificate.Drive from outside your tailnet (Funnel + TURN)
The steps above assume the operator can join your tailnet. To let someone drive without installing Tailscale, publish the robot on the internet with Tailscale Funnel. You need two pieces: Funnel carries the control connection, and a TURN server carries the camera video.1. Publish the control connection with Funnel
Funnel publishes only on ports 443, 8443 and 10000, and it handles TLS itself. Point it at the VR server’s HTTPS port and tell it to skip the self-signed certificate check:https://<your-machine>.tailXXXX.ts.net/ on port 443. Check it with tailscale serve status.
If your Tailscale version doesn’t accept this command, use these two instead:
2. Add a TURN server for camera video
Camera video travels as a separate stream that doesn’t go through Funnel. When the headset and the robot are on different networks, they need a public TURN server to relay the video. Use a hosted TURN provider, or run coturn on a machine with a public IP. The repo includes a coturn setup for Fly.io indeploy/turn/. Fly supports the UDP traffic TURN needs, which most hosting services don’t. Follow deploy/turn/README.md to launch your own server with a few flyctl commands.
Then set these variables on the robot’s computer before you start teleop:
AXOL_TURN_URL is a comma-separated list of turn:, turns: or stun: URLs. Without these variables, an operator outside your tailnet can still drive the arms through Funnel, but sees no camera video. On a local network or a tailnet, leave them unset.
3. Connect from the headset
In the VR app’s Connect field, enter the Funnel address as anhttps:// URL, or add :443. Otherwise the app uses the local default port, 8000.
Next steps
Teleoperation
The full teleop flow and controller layout.
VR Interface
The WebXR app, camera views, and connection details.
