> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tailscale

> Request private functions by name from a Tailscale network through a Tailscale Subnet Router.

A [Tailscale Subnet Router](https://developers.telnyx.com/docs/network/tailscale-subnet-router.md) on the [*Network*](https://developers.telnyx.com/docs/network/overview.md) lets every device on your tailnet request private functions by their [private names](https://developers.telnyx.com/docs/edge-compute/private-ingress/how-it-works/private-names.md), with no WireGuard peer per device.

Set up the router as in the [Tailscale Subnet Router Quick Start](https://developers.telnyx.com/docs/network/tailscale-subnet-router/quick-start.md), in the region of the *Network*'s DNS resolver. Private names then need two more things on the tailnet: the resolver's route and split DNS.

| Tailnet setting | Value |
| - | - |
| Route | The WireGuard Interface subnet, such as `172.27.0.0/24`, which holds the [ingress](https://developers.telnyx.com/docs/edge-compute/private-ingress/how-it-works/ingress.md) address |
| Route | The DNS resolver's address as a `/32`, such as `172.27.240.14/32` |
| Split DNS | `private.telnyxcompute.com` → the DNS resolver's address |

## The Resolver's Route

The resolver adds its `/32` to the advertised routes of every router on the *Network*, whether the router or the resolver came first. You advertise only the interface subnet:

```bash theme={null}
telnyx-edge network router create pi-demo --region ashburn-va \
    --route 172.27.0.0/24 --auth-key-file key.txt --wait
```

`telnyx-edge network router get pi-demo-ashburn-va-ts` then shows both routes under `Routes`.

Approve the `/32` on the router's machine in the [Machines](https://login.tailscale.com/admin/machines) page of the admin console, as in Tailscale's [Enable subnet routes from the admin console](https://tailscale.com/docs/features/subnet-routers#enable-subnet-routes-from-the-admin-console), and grant access to it as for the interface subnet in the [Quick Start](https://developers.telnyx.com/docs/network/tailscale-subnet-router/quick-start.md#prepare-the-tailnet). To cover it in advance, add the resolver's address to the `autoApprovers` routes and the access rule's `dst`. Resolvers currently get addresses in `172.27.240.0/21`.

## Split DNS

Open the [DNS](https://login.tailscale.com/admin/dns) page of the Tailscale admin console and add a nameserver under **Nameservers**:

* **Nameserver**: the resolver's address, `172.27.240.14` here.
* **Restrict to domain**: on, with the domain `private.telnyxcompute.com`.

Tailscale calls this a [restricted nameserver](https://tailscale.com/docs/reference/dns-in-tailscale#restricted-nameservers), or split DNS, and its guide to [route DNS lookups to an internal DNS server](https://tailscale.com/docs/features/subnet-routers#route-dns-lookups-to-an-internal-dns-server) shows the same setup. Devices keep their own DNS for every other name.

Devices need to accept Tailscale's DNS settings as well as its [routes](https://developers.telnyx.com/docs/network/tailscale-subnet-router/concepts/routes.md#for-the-tailnet-admin). macOS, Windows, iOS, and Android do both by default. Linux devices need [`tailscale set`](https://tailscale.com/docs/reference/tailscale-cli#set):

```bash theme={null}
tailscale set --accept-routes --accept-dns
```

## Request the Function by Name

```bash theme={null}
curl http://internal-api-5aca61c5-4.private.telnyxcompute.com/
```

The function sees the router's [`customer_address`](https://developers.telnyx.com/docs/network/tailscale-subnet-router/security/source-address) as the sender, at the start of `X-Forwarded-For`.

## Several *Networks* in One Tailnet

> [!WARNING]
>
> By default, Tailscale sends each route to one primary router, the one that joined the tailnet first, and moves it to another only when that router goes offline. Tailscale calls this [active-passive failover](https://tailscale.com/docs/features/route-selection#active-passive-failover). *Networks* often reuse addresses: a first WireGuard Interface is usually `172.27.0.0/24`, and resolvers in different regions can share an address. If routers of two *Networks* in one tailnet advertise the same route, requests reach whichever router is primary, which may be the other *Network*.

[Route Approval](https://developers.telnyx.com/docs/network/tailscale-subnet-router/security/route-approval.md) shows how to read which machine serves a route. Give each *Network* its own interface subnet with `telnyx-edge network interface create --subnet`. For a shared resolver address, turn the route off on the other router in its **Edit route settings**, in the [Machines](https://login.tailscale.com/admin/machines) page; removing its machine logs that router out for good.

## Troubleshooting

| Symptom | Cause |
| - | - |
| The private name does not resolve | Split DNS is missing, the device does not accept Tailscale DNS, or the resolver's `/32` is not approved |
| Requests time out or reach another service | Another router is primary for the route |
| `Host is unreachable` on the first request | The ingress's WireGuard peer is still connecting; retry after a minute |
| `404` with an empty body | The function's route is not ready yet, a few minutes after `ship`; retry |
| `404 no private function is bound to this host` | The `Host` header is not a [private name](https://developers.telnyx.com/docs/edge-compute/private-ingress/how-it-works/private-names.md) on this ingress |
