TSLinkTSLink Docs

FAQ

Frequently asked questions about TSLink

View as Markdown

General

Why not just use tailscale serve or Tailscale Services?#

Tailscale Serve publishes endpoints through the host's Tailscale client. Tailscale Services provides named services with separate MagicDNS names. Its setup requires the documented administrative role and a tagged host; host approval can be automatic when the tailnet has a matching auto-approval policy.

TSLink adds a local multi-app registry, private HTTP/file people grants with deadlines, invitation bundles, recipes, health checks, and CLI/MCP lifecycle operations. Each service uses an embedded tsnet node, so the TSLink host does not need a system Tailscale daemon.

Default tslink add myapp --proxy localhost:3000 --json ensures the gateway is running. Without stored credentials, its node enrolls as a user-owned, untagged node. First enrollment can return needs_login and auth_url: hand that URL to the human to complete browser login and any approval required by tailnet policy. Then use tslink url myapp --wait --json and use the exact address it returns. See Quick Start for this handoff; registration alone does not prove readiness.

TSLink is licensed under Apache-2.0 and is free for commercial use. Install with Homebrew on macOS or Linux, release archives, Linux packages or a Windows zip. The macOS binary is signed and notarized; the Windows zip is not Authenticode-signed. See Installation for verification and source builds. Tailscale account terms apply separately.

TSLink is written in Go and supports macOS, Linux, and Windows. Platform-specific autostart is available on all three: LaunchAgent (macOS), systemd user service (Linux), and Task Scheduler with a built-in supervisor (Windows); --startup selects a fallback without crash recovery.

On the machine running TSLink: No. TSLink embeds its own Tailscale node (via tsnet), so it operates independently of the system Tailscale daemon.

On devices accessing your services: Yes for private tailnet access. Those devices need Tailscale and network permission: either membership in your tailnet or an accepted app-device share for an outside account. The exception is proxy services exposed via Funnel (--funnel --public), which are intentionally reachable from the public internet and are not covered by TSLink identity enforcement.

What are ephemeral nodes?

The --ephemeral flag requests an ephemeral tsnet node for a temporary service. Tailscale's control plane removes ephemeral nodes after a period of inactivity; disconnecting does not prove immediate remote removal. The local service registration remains until you remove it with tslink remove.

bash
tslink add temp-service --proxy localhost:3000 --ephemeral

Authentication

What's the difference between API access tokens and OAuth client secrets?

API Access TokenOAuth Client Secret
Prefixtskey-api-*tskey-client-*
ExpirationExpires periodicallyNever expires
How auth worksCurrent most complete path for Tailscale REST tag/device automation and auth material derivationUsed directly by tsnet for authentication; REST tag/device automation is narrower today
Best forAutomation and tag/device managementLong-running setups after validating required operations

Both are entered during tslink login. Either one can authenticate services, but do not treat OAuth client secrets as universally recommended for full automation until your required tag/device operations are validated.

Where are my credentials stored?

Credentials prefer the system keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager). Plaintext 0600 file fallback is allowed only on macOS/Linux after TSLink proves an old keychain value is absent or has been deleted. An unreachable or uncertain keychain fails closed; restore access and retry. Windows does not allow credential file fallback. Headless operation alone does not guarantee fallback.

Auth keys used internally by tsnet are not stored on disk. In API-token mode, TSLink derives fresh auth material as each service starts, scoped to that service's tags, ephemeral setting, and service-specific description.

TSLink accepts a custom control URL, but Headscale end-to-end enrollment and HTTPS validation remain pending. Use it without stored Tailscale credentials, or with a user-supplied auth key issued by the selected server. TSLink refuses auth material derived from stored Tailscale credentials for another control server with credential_control_url_mismatch. See Configuration: Available Settings before changing the URL.

Set the custom control URL globally:

bash
tslink config set control-url https://headscale.example.com

You can also set it per-service in registry.json. A deliberately manual gateway can use tslink serve --control-url <url> for one session. For a running managed gateway, follow Restarting After Configuration Changes rather than starting a second serve process.

Currently tslink config supports control-url for pointing TSLink at a custom coordination server (e.g., Headscale). Use tslink config set, tslink config get, and tslink config list to manage global settings. Global config is stored in ~/.config/tslink/config.json.

Security

Is my traffic encrypted?

Partly. The tailnet leg — traffic between devices on your tailnet and the TSLink node — is WireGuard-encrypted, so it stays protected even if the underlying network is compromised. TSLink also provisions HTTPS certificates for the tailnet listener of HTTP proxy and file services. Two boundaries to be aware of: the short backend hop from the TSLink node to your local service is whatever you configured (often plain HTTP or plain TCP, and may be plaintext), and raw TCP services have no TSLink TLS termination. So the tailnet transport is encrypted, but the path is not encrypted end-to-end across the whole chain.

Can people outside my Tailscale network access my services?

By default, services listen on the private tailnet and are subject to its access policy.

The exception is Tailscale Funnel (--funnel --public). When enabled on a proxy service, it makes that service accessible from the public internet. Only enable Funnel when you intentionally want public access; public Funnel traffic is not covered by TSLink identity enforcement.

Can I restrict access to specific people?

Yes. For proxy/file HTTP services, use --allow to limit access to specific Tailscale identities:

bash
tslink add internal --proxy localhost:9090 --allow user@example.com,tag:admin

This works in addition to standard Tailscale ACLs.

What are ACL tags and how do I use them?

ACL tags (e.g., tag:admin) identify tagged Tailscale devices. Proxy/file HTTP --allow can match a caller's device tags. Service --tags configures the TSLink node's tags in credential-backed mode; default zero-credential (Tier 1) nodes remain user-owned and untagged, even if the registry contains tags.

Ordinary remote tag-owner provisioning requires explicit --manage-acl on login or serve and credentials with the required policy permissions. API-token mode currently supports the broadest REST tag/device automation; client-secret-only operations are narrower. Explicitly acknowledged public Funnel has a separate provisioning flow. See Tag Configuration.

Default zero-credential enrollment does not require tags. Credential-backed services use the configured tags, or the default tag:tsmain when --tags is omitted. Setting a local tag does not create remote policy: configure tag ownership yourself, or explicitly opt into ordinary --manage-acl provisioning with sufficient permissions. Editing tags on a Tier 1 service retains its existing user enrollment.

To customize tags, use the tslink tags command group:

bash
# See current tags
tslink tags list

# Change the default tag for future credential-backed services
tslink tags set-default tag:myteam

# Add custom tags to a specific service
tslink add api --proxy localhost:8080 --tags tag:api,tag:prod

Technical boundaries

Yes. CLI --json provides a versioned envelope, and owner sessions expose 44 MCP tools for app/access management; reduced roles see fewer tools. tslink mcp reserves stdout for protocol frames and rejects --json. See the MCP reference for transport, parameter, cancellation, and log-redaction boundaries.

Can I share an MCP or local LLM server?

Register an existing HTTP endpoint with tslink add llm --proxy localhost:11434 --allow you@example.com. Receiving clients must be able to reach the tailnet address. Keep application authorization where the application needs it; TSLink does not convert stdio to HTTP or replace MCP OAuth. Raw TCP has no HTTP identity headers or TSLink --allow check.

What does the standards mapping cover?

TSLink is not certified against a security standard. The Standards Alignment page is an educational, partial mapping to NIST SP 800-207 concepts. Separate nodes give services network identities, not process or host isolation. WireGuard protects the tailnet leg; the backend hop may be plaintext. HTTP identity resolution is best-effort, cached for 60 seconds, and enforced by TSLink only when --allow is configured.

Services

How many services can I run?

There is no hard limit in TSLink itself. Each service creates a hostname on your tailnet. Practical limits depend on your Tailscale plan and system resources.

What service types are supported?

TypeFlagUse Case
Proxy--proxyWeb apps, APIs, any HTTP service
File--dirServe a directory over HTTPS
TCP--tcpDatabases, Redis, any raw TCP protocol

How do TCP services work?

TCP services forward raw TCP connections byte-for-byte. This is useful for exposing databases (PostgreSQL, MySQL), Redis, message brokers, or any TCP-based protocol to your tailnet. Unlike proxy services, TCP services do not perform HTTP processing, HTTP --allow, middleware, TLS termination, or header injection.

bash
tslink add mydb --tcp localhost:5432

After enrollment and readiness, obtain the actual address with tslink url mydb --wait. Use its hostname and recorded TCP port from a device permitted by tailnet policy. Keep the database's own authentication and any required application TLS:

bash
psql -h <hostname-returned-by-tslink-url> -p 5432

Can I expose services on remote machines?

TSLink proxies to a host:port, so the target service must be reachable from the machine running TSLink. If you can reach it via curl http://host:port, TSLink can proxy it.

Can I expose a service on a non-standard port?

TSLink proxy and file services are accessed over HTTPS on port 443. TCP services created by the CLI are accessed on the port recorded from --tcp host:port; if a manually edited registry omits port, runtime falls back to 443.

Do I need to restart the gateway when adding services?

No. TSLink supports hot-reload. When you run tslink add or tslink remove, the gateway detects changes automatically and updates without restarting.

What changes are hot-reloaded vs. require a node restart?

Registry changes to a service's type, target/path, port, tags, HTTP access list, ephemeral setting, Funnel settings, or effective control URL restart the affected runtime through hot reload. A Tier 1 tag edit retains user enrollment; effective credential-backed tag changes can reset node identity. Credential mode swaps and legacy authkey file changes require a gateway process restart; follow daemon management for your platform. Configurable middleware is roadmap/experimental; the removed middleware registry key is rejected even when empty.

What are identity headers?

For proxy services, TSLink injects Tailscale identity headers when Tailscale WhoIs resolves the caller for a request forwarded to your local service:

  • X-Tailscale-User-Login — the authenticated user's login name
  • X-Tailscale-User-Name — the user's display name
  • X-Tailscale-User-Picture — profile picture URL, when available
  • X-Tailscale-Node — requesting node's computed name, when available

TSLink strips incoming X-Tailscale-* headers before injecting WhoIs-derived values. Resolution is best-effort: without --allow, a failed lookup can forward a request with no identity headers; with --allow, missing identity is denied before the backend.

Trust these headers only across a controlled TSLink-to-backend path that prevents callers from bypassing the proxy and forging them. If your application requires an identified user, reject missing identity and retain its required authentication and authorization. The headers alone do not authenticate every request.

Are identity headers available for file and TCP services?

No. Identity headers are only injected for proxy services, since they rely on HTTP request processing. File services serve static files directly, and TCP services forward raw bytes without HTTP awareness.

Funnel

What is Tailscale Funnel?

Tailscale Funnel allows you to expose a service publicly on the internet, without requiring the accessing device to be on your tailnet. The service remains available at the same https://<service-name>.<tailnet-name>.ts.net URL.

Which service types support Funnel?

Only proxy services support Funnel (--funnel --public). File services and TCP services do not support Funnel.

bash
tslink add myapp --proxy localhost:3000 --funnel --public

Is Funnel safe to use?

Funnel exposes your service to the public internet. Only enable it when you intentionally want public access. Do not rely on the roadmap/experimental middleware package for Funnel protection in the launch candidate. Note that identity headers (X-Tailscale-User-*) are not available for public Funnel requests.

For questions about middleware, Docker auto-discovery, and other experimental features, see Experimental & Roadmap.

Monitoring

Prometheus /metrics is roadmap/experimental. See the Experimental & Roadmap page for details on available metrics.

Where are access logs stored?

Use tslink access log --app photos --since 24h for retained local HTTP/file/TCP/guest events and authority-change receipts. Daemon JSONL history is in ~/.config/tslink/access-log/; the mutation journal is mcp-audit.json. tslink logs reads daemon diagnostics under logs/. See access history for path privacy, independent bounds and gaps.

History uses typed schema-version-1 events: time, kind, app/service, decision, optional WhoIs-attested identity, and HTTP/TCP metadata or typed guest/MCP/lifecycle details. It stores no headers, cookies, bodies or secrets. Default path mode records a sanitized prefix. Events and intent/completion receipts are not unique visits or proof of successful completion. Missing identity, dropped events and crash gaps remain possible; status and doctor report current history health. There is no complete-audit or compliance guarantee. Prometheus, flow analysis and cluster telemetry remain planned.

Can someone visit without Tailscale?

Guest links support one HTTP proxy app through explicitly public Funnel with a mandatory gate, optional PIN and finite expiry. Link/PIN is forwardable and does not verify a person. File/raw TCP are unsupported. Open Funnel is a separate public publication; keep the app's own authentication.

Is there a home page for my apps?

The private portal lists permitted apps on one host and offers opt-in requests for private HTTP/file apps. Visitors still need the right Tailscale login, network policy and node shares. QR onboarding does not install apps or grant access automatically. Multi-host inventory and an admin management dashboard/REST API remain planned.

Networking

You normally do not need an inbound router port-forwarding rule. The TSLink host still needs working Tailscale connectivity, and receiving devices need a reachable tailnet path and permission under its access policy.

What happens if my machine goes to sleep?

The gateway cannot serve while its host sleeps. After wake, availability depends on the gateway process, network connectivity, and node authentication still being ready; check tslink status --json and tslink url <name> --wait. For persistent availability, use an awake host or an always-on server.

Yes. Tailscale Access Control Lists (ACLs) apply to TSLink services just like any other device on your tailnet. You can restrict which users or devices can access specific services.

For questions about custom domains and ACME certificates, see Experimental & Roadmap.

Automation

Can I manage services programmatically?

Yes. You have two shipped options, plus one roadmap item:

1. --json on published manifest commands — every command in the published manifest except the stdio tslink mcp server accepts --json and returns one versioned envelope. Cobra's help and completion commands are not in the manifest and print plain text:

bash
tslink list --json
tslink add myapp --proxy localhost:3000 --json
tslink remove myapp --json
tslink status --json

2. MCP — tslink mcp serves the same operations as MCP tools over stdio for a client on this machine, and tslink serve --mcp serves them over HTTPS on a dedicated tailnet-only node for clients on other tailnet machines. See TSLink as an MCP Server.

3. Admin REST API — roadmap/experimental; not launched by the current runtime.

Use the CLI with --json for local scripting and CI/CD pipelines, MCP for agents, and treat REST management as roadmap/experimental.

Configuration

By default, TSLink stores local configuration and runtime files under ~/.config/tslink/ (keychain credentials remain in the system keychain):

PathDescription
registry.jsonService registry (all registered services)
config.jsonGlobal configuration (control URL, etc.)
tslink.pidDaemon PID file
apikeyAPI access token (file fallback)
clientsecretOAuth client secret (file fallback)
authkeyLegacy auth key (backward compatibility)
nodes/Per-service tsnet node state
logs/Daemon and access logs

Can I change the config directory?

Set TSLINK_CONFIG_DIR to select another directory. CLI and gateway must use the same value; an installed supervisor also needs the matching environment. Follow daemon management when changing an existing setup, and do not operate on one directory while another gateway serves from a different one.

Troubleshooting

My service was working but suddenly stopped

Check if the local service (the host:port target) is still running. TSLink proxies traffic but doesn't manage the lifecycle of your local services.

I see "address already in use" errors

Another gateway or process may be using the same resources. Inspect tslink status --json, including data.daemon_running and data.supervision, before changing anything. A macOS managed gateway can restart after stop; manual and managed gateways need different handling. Follow verified shutdown or the applicable restart procedure, and identify the actual conflicting process before retrying.

For more detailed troubleshooting, see the Troubleshooting guide.

Table of Contents

GeneralWhy not just use tailscale serve or Tailscale Services?Is TSLink free to use?What platforms does TSLink support?Does TSLink require the Tailscale app to be installed?What are ephemeral nodes?AuthenticationWhat's the difference between API access tokens and OAuth client secrets?Where are my credentials stored?Can I use TSLink with Headscale?What config settings does tslink config support?SecurityIs my traffic encrypted?Can people outside my Tailscale network access my services?Can I restrict access to specific people?What are ACL tags and how do I use them?Do I need to configure tags before using TSLink?Technical boundariesCan an agent use TSLink?Can I share an MCP or local LLM server?What does the standards mapping cover?ServicesHow many services can I run?What service types are supported?How do TCP services work?Can I expose services on remote machines?Can I expose a service on a non-standard port?Do I need to restart the gateway when adding services?What changes are hot-reloaded vs. require a node restart?What are identity headers?Are identity headers available for file and TCP services?FunnelWhat is Tailscale Funnel?Which service types support Funnel?Is Funnel safe to use?MonitoringDoes TSLink expose Prometheus metrics?Where are access logs stored?What log format does TSLink use?Can someone visit without Tailscale?Is there a home page for my apps?NetworkingDoes TSLink need port forwarding?What happens if my machine goes to sleep?Can I use TSLink with Tailscale ACLs?AutomationCan I manage services programmatically?ConfigurationWhere does TSLink store its data?Can I change the config directory?TroubleshootingMy service was working but suddenly stoppedI see "address already in use" errors