Skip to content
slopscale
Esc
↑↓navigate↵open⌘Jpreview
On this page

Apps

Route traffic for chosen domains through tagged app connector nodes: define apps, how learned and static routes and split DNS work, and manage them.

An app is a set of domains reached through app connectors, following Tailscale’s app connectors. Instead of routing all Internet traffic through an exit node or advertising broad subnets, an app connector lets devices on your tailnet reach specific applications and SaaS domains (such as example.com or *.example.com) through designated connector nodes in your network.

How it works

  1. Connector node. A machine runs the app connector service and advertises itself as a connector.
  2. App definition. An operator defines the app with its domains, static routes, and connector selectors.
  3. Route learning and approval. The connector resolves the app’s domains, advertises single-address host routes for the learned IPs, and the server approves them automatically.
  4. DNS. The server sends every machine split DNS for the app’s domains that points at the connectors, so queries reach a connector and it learns the addresses.

Setting up a connector node

A connector node must be a tagged machine because connectors act as shared network infrastructure; user-owned machines cannot serve as connectors.

On the machine, advertise the connector service:

tailscale set --advertise-connector

When registering a new node, pass --advertise-connector to tailscale up along with the node’s tags:

sudo tailscale up --login-server <YOUR_SLOPSCALE_URL> --auth-key <KEY> \
  --advertise-connector

The node reports to the server that it runs the app connector service. The server sends app definitions to matching connector nodes using the tailscale.com/app-connectors node capability.

Defining apps

An app has:

  • Name: 1 to 63 characters.
  • Description: an optional summary.
  • Domains: domain names or wildcard domains the connectors watch and resolve, such as example.com or *.example.com.
  • Connectors: node tag selectors (such as tag:connector) that specify which connector nodes serve the app, or * to select every tagged machine running the connector. If omitted, * is the default.
  • Routes: optional static CIDR prefixes (such as 198.51.100.0/24) that connectors always advertise. Full internet routes (0.0.0.0/0 and ::/0) are refused.

Learned and static routes

Connector nodes watch the app’s configured domains and resolve them. Whenever a connector learns an address for a domain, it advertises a host route (/32 for IPv4 or /128 for IPv6).

The server approves learned single-address routes automatically. If an app defines static routes, any prefix within those routes is also approved automatically for the app’s connectors. Any other advertised routes, such as broader subnets (10.0.0.0/16) or exit routes, are not covered by the app and require manual approval by an operator (or policy autoApprovers.routes).

When a domain leaves an app, or the app is deleted, the connector withdraws the routes it learned for it and the server drops their approvals with them, so the connector’s route list only holds what it advertises. Exit routes are left alone, and a plain subnet router keeps its approvals when it stops advertising a route, as before.

DNS

The server sends every machine split DNS for the app’s domains, pointing at the connectors’ DNS endpoints over the tailnet, the way Tailscale’s control plane does: a query for example.com goes to a connector, the connector answers it and learns the addresses in the answer. A machine sees only the connectors it has as peers, online ones first, and a connector is never sent its own apps. A wildcard domain (*.example.com) routes the base domain too. Nothing has to be configured under DNS; a split DNS rule for the same domain, if one exists, comes first.

A connector answers a peer’s query only when the policy lets that peer send traffic to the internet through it, which is the same access the peer needs for the addresses the connector learns: a rule with autogroup:internet or the addresses themselves as the destination and the peer as the source.

Machines at the connector’s site

A machine that reaches the internet from the same public address as a connector skips that connector. The app already sees the address it allows, so going through the connector would only add a hop. Say the connector sits in the office: a laptop in the office goes out directly, while the same laptop at home still goes through the office connector.

The server compares the public IPv4 address each client reports among its endpoints, the address its NAT shows the internet, so nothing has to be configured. When a machine or a connector moves, its peers get a new netmap. A machine that skips a connector does not get these from it:

  • the host routes the connector learned from the app’s domains
  • the public prefixes inside the app’s static routes
  • the split DNS for the app’s domains

Private prefixes such as 10.0.0.0/8 in an app’s static routes stay routed through the connector, since sharing a public address says nothing about reaching a private network. If an app has connectors at several sites, a machine skips only the connector behind its own address and still uses the others.

Console and API

The admin console has an Apps page under Connectivity (Connectivity › Apps), listing configured apps, their domains, connector selectors, static routes, and the connector nodes assigned to each app with counts of learned and pending routes.

From the CLI:

slopscale apps list
slopscale apps show --id 1
slopscale apps create --name "Internal Tools" \
  --domain tools.corp.example.com --domain "*.tools.corp.example.com" \
  --connector tag:connector \
  --route 192.0.2.0/24
slopscale apps update --id 1 --route 198.51.100.0/24
slopscale apps delete --id 1

Through the API:

  • GET /api/v1/apps: list all apps (requires policy_file:read).
  • POST /api/v1/apps: create an app (requires policy_file).
  • GET /api/v1/app/{id}: retrieve an app (requires policy_file:read).
  • PUT /api/v1/app/{id}: update an app definition (requires policy_file).
  • DELETE /api/v1/app/{id}: delete an app (requires policy_file).

Creating, updating and deleting an app are audited as app.create, app.update and app.delete.

Last updated on October 1, 2026

Was this page helpful?