Connect devices outside your tailnet
Aperture runs on a tailnet, and devices in that tailnet can reach it directly. But not every device that needs LLM access can join the tailnet. CI/CD runners, contractor machines, personal devices, and devices in a different tailnet can all connect to Aperture through an embedded Tailscale node that joins your tailnet and proxies local traffic to Aperture. The device does not need Tailscale installed.
There are two ways to do this:
- An Aperture CLI bridge (recommended). The Aperture CLI creates the embedded node for you and launches your coding agent already pointed at it. Use this for interactive coding sessions.
ts-unplug. A standalone proxy from the ts-plug repository that listens on a local port you choose. Use this when you need a fixed local endpoint for tools the Aperture CLI does not launch, such as scripts, CI jobs, or custom API clients.
Both methods authenticate requests using the embedded node's Tailscale identity, not a shared API key. If each person runs their own instance, Aperture attributes activity to individual users.
ts-unplug is also referred to as bridge mode or standalone mode. Despite the name, bridge mode is the ts-unplug workflow, not the Aperture CLI bridge feature.
Use cases
Connect from outside the tailnet when devices cannot or should not join your tailnet directly.
- CI/CD runners: Ephemeral environments like GitHub Actions runners that need LLM access during builds. Use an auth key to skip interactive approval.
- Contractor or vendor machines: External collaborators who need Aperture access without joining your organization's tailnet.
- Personal devices: Team members who prefer not to install Tailscale on personal hardware.
- Cross-tailnet access: Devices in a different tailnet that need to reach your Aperture instance.
For devices that are already in your tailnet, connecting directly requires fewer steps and provides the same per-user identity. Refer to set up LLM clients for connection instructions.
Connect using an Aperture CLI bridge
A bridge is an embedded Tailscale node that runs inside the Aperture CLI. When you activate a bridge endpoint, the Aperture CLI joins your tailnet, opens a local proxy, and configures the coding agent it launches to use that proxy.
Prerequisites
Before you begin, confirm you have the following:
- The Aperture CLI. Refer to install the Aperture CLI.
- The URL of your Aperture instance. By default, this is
http://<aperture-hostname>.<tailnet-name>.ts.net. Find your tailnet DNS name in the DNS page of the admin console. - Permission to approve devices. You must be an Owner, Admin, or Network admin to approve the bridge node in the admin console, unless you use an auth key to authenticate automatically.
Step 1: Create a bridge
-
Run
aperture, then presssto open settings. -
Select Bridges, press
a, and enter a name for the bridge, such asci-runner.
Step 2: Assign the bridge to an endpoint
-
Return to the settings menu and select Aperture Endpoints.
-
Press
a, select Bridge, choose the bridge you created, and enter your Aperture URL.
Step 3: Activate the endpoint
-
Select the new endpoint to activate it.
The first activation prints a Tailscale authentication URL in the bridge logs. Open the URL in a browser to authenticate the node. If your tailnet requires device approval, also approve the device in the Machines page of the admin console for the tailnet hosting Aperture.
-
After the connection check passes, select a coding agent from the main menu.
The Aperture CLI starts the agent with the bridge proxy as its base URL.
For more detail on how bridges work, refer to bridges.
Connect using ts-unplug
ts-unplug creates a lightweight tailnet node and opens a local port that forwards traffic to Aperture. Unlike an Aperture CLI bridge, the port is one you choose and stays fixed, so any tool on the device can use it as a base URL.
The ts-plug and ts-unplug tools are under active development. Refer to the ts-plug repository for the latest status and release information.
Prerequisites
Before you begin, confirm you have the following:
- Go toolchain.
ts-unplugis built from source. Install Go 1.21 or later. - Git. Required to clone the ts-plug repository.
- The FQDN of your Aperture instance. By default, this is
<aperture-hostname>.<tailnet-name>.ts.net. Find your tailnet DNS name in the DNS page of the admin console. - Permission to approve devices. You must be an Owner, Admin, or Network admin to approve the
ts-unplugnode in the admin console, unless you use an auth key to authenticate automatically.
Step 1: Build ts-unplug
Clone the ts-plug repository and build ts-unplug:
git clone https://github.com/tailscale/ts-plug.git
cd ts-plug
make ts-unplug
This creates the binary at ./build/ts-unplug.
Step 2: Start ts-unplug
Run ts-unplug and point it at your Aperture instance. Replace <tailnet-name> with your tailnet DNS name and choose a local port:
./build/ts-unplug -dir ./state -port 8080 <aperture-hostname>.<tailnet-name>.ts.net
On the first run, ts-unplug prints a URL to authenticate the new node. Open the URL in a browser to complete authentication.
Step 3: Approve the device
Approve the new device in the Machines page of the admin console for the tailnet hosting Aperture.
After approval, ts-unplug displays HTTP proxy listening and you can access Aperture at http://localhost:8080.
Step 4: Verify the connection
After ts-unplug is running, confirm the connection works by sending a test request:
curl -s http://localhost:8080/v1/messages \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 25,
"messages": [{"role": "user", "content": "respond with: hello"}]
}'
If the request succeeds, open the Aperture dashboard at http://localhost:8080/ui/ to find the request in your usage history.
Next steps
-
Configure tools to use the
ts-unplugproxyAfter you confirm the connection works, configure your tools to use
http://localhost:<port>as the base URL for API requests. For tool-specific configuration, refer to set up LLM clients and replacehttp://<aperture-hostname>withhttp://localhost:<port>in any configuration example. Agents launched by the Aperture CLI are configured automatically and need no changes. -
Manage your instances
Stop the proxy when it's not in use, remove devices from your tailnet when they're no longer needed, and run multiple
ts-unpluginstances with separate state directories if multiple users need access. To remove a bridge, refer to delete a bridge.
Limitations
The following limitations apply while these connection methods are in beta:
- The Aperture CLI bridge proxy listens on a random local port and configures the agents the Aperture CLI launches. Use
ts-unplugwhen you need a fixed port for other tools. ts-unplugmust be built from source. Pre-built binaries are not available.ts-unpluglistens onlocalhostonly. Other devices on the same network cannot access the proxy.- Each bridge or
ts-unpluginstance creates a separate tailnet node. If you need many instances, consider using auth keys with appropriate tags and access control policies.