Install¶
This guide installs the tl-starnav aircraft software on your ModalAI VOXL2 flight computer — from a sealed box to an aircraft that is on your private network, configured for your setup, and brought to a flight-ready release by the mandatory pre-first-flight update.
The aircraft runs the tl-starnav web app in your browser, served over standard
HTTPS (https://, port 443).
Setting up your ground control station (GCS) is a separate guide
tl-starnav also has a ground control station (GCS) — the application you bind the aircraft to and fly from. GCS setup has its own dedicated guide (a native Windows GCS application with single-installer setup and account-based sign-in is on the roadmap; this page will link to it when it ships). This guide covers the aircraft side; where a step needs the GCS (binding, verification), it points you to the GCS guide.
What you need¶
- Your tl-starnav aircraft unit — the ModalAI VOXL2 flight computer shipped with your order.
- A Starlink dish with an active subscription, to be connected to the aircraft.
- An ArduPilot-based autopilot (Cube Orange+, Pixhawk 6X, or similar) connected to the aircraft over MAVLink.
- A laptop or tablet with a browser to drive the aircraft web app.
- A USB cable (or LAN access) to open a shell on the VOXL2 for the one-time install.
- A Tailscale or Headscale account for the private network that links the aircraft and your GCS. (A free Tailscale account is sufficient.)
- Your welcome materials — they carry your setup command and your GCS address, not download credentials. The software itself downloads over a verified, signed channel anonymously: there are no keys, tokens, or account passwords to paste.
- Internet access for the aircraft during setup.
One-time provisioning needs internet; flight does not
Software download, the private-network sign-in, and binding all happen once, with internet. After that the aircraft↔GCS command link runs over Starlink and your private network — there is no cloud dependency in flight.
1. Connect the aircraft hardware¶
- Connect the Starlink dish to the aircraft's WAN. Mount the dish with a clear view of the sky (no obstructions above ~25° elevation); it auto-orients, so no manual aiming is needed.
- Connect the autopilot to the aircraft's LAN for the MAVLink link.
- Power the aircraft and confirm it reaches the internet through Starlink.
The VOXL2 acts as the aircraft's full LAN router — it serves DHCP, is the gateway for devices connected to its LAN, and routes their traffic out through Starlink. You can adjust this later from the Settings tab (LAN card); the defaults work out of the box.
2. Provision the aircraft¶
The tl-starnav aircraft software installs on the VOXL2 with one command. It
pulls the aircraft software down automatically over a verified, signed,
anonymous download — there are no keys to paste on the aircraft — runs
the whole stack inside one managed container, and brings the web app up over
standard HTTPS (https://, port 443).
a. Open a root shell on the VOXL2. For a fresh aircraft use USB — the network paths aren't reachable until the aircraft's LAN is configured (next section).
- Install the Android platform-tools (which provide
adb) on your computer if you don't have them — macOS:brew install android-platform-tools; Windows/Linux: download Google's SDK Platform-Tools. -
Connect the VOXL2 by USB and confirm it is attached:
If it shows
unauthorized, accept the USB-debugging prompt on the VOXL2. 3. Open a shell — you land asroot:
(Once the aircraft is on a network you can reach — after you configure its LAN,
or after it joins your private network — you can also use
ssh root@<aircraft-ip>. The stock ModalAI root password is oelinux123; change
it for production.)
b. Confirm the aircraft has internet (through its Starlink WAN, or any uplink during setup):
curl -sfI -A tl-starnav-updater/1.0 https://dl.tyrlaboratories.com/first-install/install.sh >/dev/null && echo "internet OK"
c. Run the install command (on the VOXL2, in that root shell):
curl -fsSL -A tl-starnav-updater/1.0 -o /tmp/install.sh \
https://dl.tyrlaboratories.com/first-install/install.sh \
&& sh /tmp/install.sh
You are root via adb shell, so no sudo is needed. The -A user-agent flag
is required — the download endpoint's bot protection refuses unnamed/library
clients.
That one command downloads the installer, which then fetches the signed
aircraft image and host components from dl.tyrlaboratories.com anonymously,
verifies them, installs the thin host layer, and starts the managed container.
First install takes a few minutes (it downloads a ~180 MB image), and it is
idempotent — safe to re-run if it is interrupted.
Your welcome materials carry the same command + your GCS address
The exact command above is also printed in your welcome materials, alongside your GCS address — neither carries any download key or password (the software downloads over a signed, anonymous channel).
d. Open the aircraft web app¶
You do not have to configure the aircraft's network — or guess which Ethernet port is which — to open the web app. Use whichever method below is easiest. The first needs nothing but the USB cable you already used to install, so it always works on a fresh unit.
adb forwards a port from your laptop straight to the aircraft over the
same USB cable you used for the install. Run this on your laptop (not
in the device shell):
Then open https://localhost:8443 in your browser. That reaches the
aircraft's web app directly — no LAN, no Wi-Fi, no Ethernet-port selection.
If you opened the install shell with adb shell, you already have everything
you need; run the adb forward from that same laptop. (To stop forwarding
later: adb forward --remove tcp:8443.)
The aircraft serves the web app on every network interface at port 443, including its WAN/uplink address. From the device shell, read that address:
Then, from a computer on the same network as that interface, open
https://<AIRCRAFT-IP> (port 443). This is the handy path on a bench where
your laptop and the aircraft share a switch or LAN.
Once you have selected the aircraft's LAN interface (in Configure, or via
the shell recovery in the tip below), the app is also reachable at
https://192.168.2.1. On a fresh unit no LAN port is assigned yet, so
this address may not load over Ethernet until you pick the LAN interface — that
is expected on first boot, not a failed install, and the two methods above
do not depend on it.
The aircraft serves standard HTTPS; a plain http://… request redirects to
HTTPS automatically. The first visit shows a one-time self-signed-certificate
warning that you accept per machine (covered in the next section). The
certificate is issued for localhost and 127.0.0.1, so the USB method
opens with only the issuer warning; the WAN-address method additionally shows
a name-mismatch you click through the same way.
Putting the aircraft on its own LAN (optional, for later)
The VOXL2 has two interchangeable USB Ethernet ports and cannot always tell
which one you wired to your laptop (LAN) versus to Starlink (WAN). On a fresh
aircraft no port is assigned to the LAN yet, so https://192.168.2.1 may not
load over Ethernet until you select the LAN interface and your laptop is on
that port. You do not need this to reach the UI now — use USB or the WAN
address above.
When you are ready to give the aircraft its own LAN (gateway/DHCP/NAT for connected devices), the supported path is the web UI: open it (USB/WAN above) and use Settings → LAN — the picker labels each port and refuses the Starlink/WAN port. Do the rest of LAN setup in the Configure guide.
Only if you cannot open the UI at all, you can set the LAN port from the root
shell. Pick the port your laptop is on (its name, e.g. eth1), then let the
shell read that port's MAC for you — do not type a MAC by hand, and do not
paste the <…> text literally:
ip route show default # the 'dev <name>' here is the WAN/Starlink port — do NOT pick it
ip -br link show | grep -i ' up' # ports with a live link; pick the one your laptop is on
LAN_NIC=eth1 # <-- replace eth1 with YOUR LAN port name from the line above
LAN_MAC=$(cat /sys/class/net/"$LAN_NIC"/address) # reads that port's MAC; no hand-typing
sed -i "s/^LAN_MAC=.*/LAN_MAC=$LAN_MAC/" /etc/tl-starnav/network.conf
docker exec tl-starnav /opt/tl-starnav/container/tl-starnav-lan-apply
After that, https://192.168.2.1 loads on that port. Full LAN setup — gateway,
DHCP, NAT — is in the Configure guide.
First boot expects the mandatory update
The first time you open the aircraft web app, it shows an "update required before first flight" banner across the top. This is expected: the aircraft ships ready to fly after you run the required pre-first-flight update (the last step of this guide). The banner clears on its own once that update completes.
First-boot health check (for technicians)
A freshly flashed aircraft is up and answering as soon as it boots: a request
to /api/discovery/self returns 200 OK. Until you bind it to a GCS
(step 5), its role may read unknown — that is healthy on a fresh
unbound unit, not a fault. Binding settles the role.
Do not paste sign-in keys
tl-starnav uses the standard interactive Tailscale / Headscale sign-in — never a key paste. The aircraft UI walks you through it (next step).
3. Join the aircraft to your private network¶
A fresh aircraft is not on your private network yet, so you do this from the
aircraft's local web app — opened by whichever method you used in
step 2d (over USB, https://localhost:8443, is
the easiest and needs no network setup).
First visit: trust the aircraft once (expected security warning)
The aircraft serves its web app over HTTPS with its own self-signed
certificate, so the very first time your browser opens the aircraft
(whether at https://localhost:8443 over USB, its WAN address, or
https://192.168.2.1) it shows a security warning. This is expected
and safe on the local aircraft — it just means the certificate is the
aircraft's own, not one issued by a public authority. You tell the browser
to trust this device once per machine; after that, the app opens
normally with no warning on every visit.
The aircraft's certificate is issued for localhost, 127.0.0.1, its LAN
address, and its private-network name — so the USB method
(https://localhost:8443) opens with only the issuer warning, while
reaching it by an IP not on the certificate (e.g. the WAN address) adds a
name-mismatch you click through the same way.
On the warning page, click Advanced, then Proceed … (unsafe) (the button names the address you opened). The app loads, and this browser will not warn again for this aircraft.
On the warning page, click Advanced…, then Accept the Risk and Continue. The app loads, and this browser will not warn again for this aircraft.
On the warning page, click Show Details, then visit this website, and confirm Visit Website. The app loads, and this browser will not warn again for this aircraft.
- Open the aircraft web app using the method from
step 2d (over USB:
adb forward tcp:8443 tcp:443, thenhttps://localhost:8443). - When prompted, follow the "Sign in to Tailscale" link in the popup.
- Sign in via the browser (Tailscale, or your organization's Headscale control server using the "Advanced: control server" field) and approve the device.
- The aircraft joins the network and reports its private-network address. The bridge and dashboard panels unlock once it reports as connected.
Headscale / self-hosted control server
If your organization runs its own Headscale control server, enter its URL in the popup's "Advanced: control server" field during sign-in. The appropriate relay configuration is delivered automatically — no extra client settings are needed.
Make sure your GCS is also signed in to the same Tailscale or Headscale network so the two can reach each other.
4. Bind the aircraft to your GCS¶
Setting up the GCS itself is a separate guide
Installing and signing in to your GCS is covered in the dedicated GCS guide. The steps below are the aircraft-side view of binding — run them from your GCS once it is set up and on the same private network as the aircraft.
With your GCS set up and on the same private network as the aircraft:
- In the GCS app, open the Binding tab.
- Click Scan Network — the GCS discovers peers on your private network.
- Find your aircraft in the list and click Bind.
- The GCS exchanges trust material with the aircraft, configures both sides, and starts the bridge. A setup window streams progress and closes when it finishes.
Re-running bind on a live link is safe.
Binding a VOXL2 is the same as any aircraft
From the operator's point of view, binding a VOXL2 aircraft is identical to binding any tl-starnav aircraft — the only visible difference is one line in the setup stream noting the aircraft platform.
5. Verify the install¶
On your GCS dashboard, once the aircraft is bound:
- the aircraft shows as bound and online;
- the bridge link comes up and the transport state reads healthy;
- the Navigation status reports a position.
Because the GCS web app mirrors the aircraft, navigation cards, flight logs, and (for a VOXL2 aircraft) the LAN settings card all appear on the GCS once bound.
Before-you-fly checks live in the Operate guide
The full pre-flight verification — EKF source switching, navigation "sending" state, and acknowledgement rates — is in the Operate guide.
Next step¶
With the pair bound and reachable, the journey is Install → Configure → Update → Operate:
- Configure the aircraft for your setup — its LAN, the Starnav navigation settings, and the ArduPilot parameters that let the autopilot accept Starlink-derived position aiding.
- Run the Mandatory Update to bring both ends to a known-good, mutually compatible release.
Proceed to Configure next.
Do not fly before the mandatory update
Provisioning is not finished until you run the required pre-first-flight update, which brings your aircraft and GCS to a known-good, mutually compatible version. Run it after you have configured the aircraft, before any flight.
Uninstall / start over¶
If you need to remove tl-starnav from the aircraft — to start from a clean slate
before re-installing, or to return the VOXL2 to stock — run the uninstaller from a
root shell on the aircraft (the same adb shell you installed from):
curl -fsSL -A tl-starnav-updater/1.0 -o /tmp/uninstall.sh \
https://dl.tyrlaboratories.com/first-install/aircraft-voxl2/uninstall.sh \
&& sh /tmp/uninstall.sh
It stops and removes the tl-starnav container and image, the system services, the host components, and the aircraft's configuration, then re-enables the stock services. It is idempotent (safe to re-run) and leaves the host reachable throughout.
Uninstall removes the binding and the Tailscale sign-in
By default the uninstaller deletes the aircraft's saved configuration —
including its binding to the GCS and its Tailscale sign-in — so a
re-install needs a fresh bind and a fresh Tailscale sign-in. To keep that
state across a re-install, add --keep-data:
(Advanced: --purge-docker also removes the Docker configuration and image
store — a full wipe; not needed for a normal start-over.)
To re-install after uninstalling, run the install command from Provision the aircraft again — it downloads a fresh signed image and brings the aircraft back up.