FAQ
Frequently asked questions about TSLink
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.
Is TSLink free to use?
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.
What platforms does TSLink support?
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.
Does TSLink require the Tailscale app to be installed?
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.
tslink add temp-service --proxy localhost:3000 --ephemeralAuthentication
What's the difference between API access tokens and OAuth client secrets?
| API Access Token | OAuth Client Secret | |
|---|---|---|
| Prefix | tskey-api-* | tskey-client-* |
| Expiration | Expires periodically | Never expires |
| How auth works | Current most complete path for Tailscale REST tag/device automation and auth material derivation | Used directly by tsnet for authentication; REST tag/device automation is narrower today |
| Best for | Automation and tag/device management | Long-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.
Can I use TSLink with Headscale?
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:
tslink config set control-url https://headscale.example.comYou 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.
What config settings does tslink config support?#
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:
tslink add internal --proxy localhost:9090 --allow user@example.com,tag:adminThis 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.
Do I need to configure tags before using TSLink?
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:
# 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:prodTechnical boundaries
Can an agent use TSLink?
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?
| Type | Flag | Use Case |
|---|---|---|
| Proxy | --proxy | Web apps, APIs, any HTTP service |
| File | --dir | Serve a directory over HTTPS |
| TCP | --tcp | Databases, 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.
tslink add mydb --tcp localhost:5432After 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:
psql -h <hostname-returned-by-tslink-url> -p 5432Can 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 nameX-Tailscale-User-Name— the user's display nameX-Tailscale-User-Picture— profile picture URL, when availableX-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.
tslink add myapp --proxy localhost:3000 --funnel --publicIs 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
Does TSLink expose Prometheus metrics?
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.
What log format does TSLink use?
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
Does TSLink need port forwarding?
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.
Can I use TSLink with Tailscale ACLs?
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:
tslink list --json
tslink add myapp --proxy localhost:3000 --json
tslink remove myapp --json
tslink status --json2. 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
Where does TSLink store its data?
By default, TSLink stores local configuration and runtime files under ~/.config/tslink/ (keychain credentials remain in the system keychain):
| Path | Description |
|---|---|
registry.json | Service registry (all registered services) |
config.json | Global configuration (control URL, etc.) |
tslink.pid | Daemon PID file |
apikey | API access token (file fallback) |
clientsecret | OAuth client secret (file fallback) |
authkey | Legacy 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.