Get started - it's free!
Log in
© 2025

Tailscale Services

Tailscale Services is currently in private alpha. Therefore, this topic is currently hidden.

Tailscale Services provide a streamlined, secure alternative to traditional load balancers, letting you publish internal resources (like databases or web servers) as first-class network endpoints in your Tailscale network (known as a tailnet). Users can connect to Services using stable MagicDNS names rather than connecting to specific devices while Tailscale automatically routes traffic to available Service Proxies across your infrastructure.

Tailscale Services consist of a custom DNS name, an IPv4 and IPv6 address pair, a description, an optional tag, and one or more back-end Service Proxies. Tailscale Services support built-in traffic steering across multiple backend Service Proxies, granular access control for each Tailscale Service, an approval workflow for new Service Proxies, as well as variations of the Service Proxy for different layers of the OSI model.

This matters because it decouples your resources from the devices hosting them, increases reliability, leverages Tailscale's access-controlled routing, and gives you a way to manage all resources available in your tailnet. Because Services integrates with Tailscale's access controls, you avoid the complexity of mutual TLS setups and complicated firewall rules.

Use cases

Use Services when you need to make internal resources consistently accessible across your tailnet, regardless of which devices are hosting them with support for automatic routing and high-availability through multi-region deployments. Examples include:

  • Developer workflows and internal tooling: Make any internal application or developer resource highly available, horizontally scalable, and secure without complex load balancer configurations.
  • Database connectivity: Connect securely to database clusters (PostgreSQL, MySQL, RDS) with simplified connection scaling and identity-based access controls.
  • Cluster meshes: Enable cross-cluster or hybrid-cloud connectivity between any compute resources like EC2 instances, Kubernetes services, or containers.
  • Version-controlled applications: Generate stable hostnames for frequently updated, version-controlled, or ephemeral resources that persist across deployments.
  • IoT integrations: Stream device logs and telemetry securely to SIEM or logging services without exposing IoT devices to the public internet.
  • Internal APIs and webhooks: Expose internal APIs securely without public domains or complex mTLS configurations while maintaining granular access control.

Prerequisites

To get started with Tailscale Services, you must:

  • Contact your Tailscale account team to enable the Tailscale Services feature.
  • Ensure the devices in your tailnet use Tailscale v1.86.0 or later, or an unstable v1.87.x release.
  • Be an Owner, Admin, or Network admin. This is required to define a Service, create grants, and configure auto-approval policies.
  • Have a resource running on a tailnet device that you can expose as a Tailscale Service.
  • Have one or more pre-defined tags to assign identities to your Services.

Get started

To get started with Tailscale Services, you need to define a Service through the admin console, configure a Service Proxy on a tailnet device, then advertise the Service Proxy.

Step 1: Define a Tailscale Service

Creating a Tailscale Service establishes the definition that Service Proxies will connect to. This process happens in the admin console and creates the MagicDNS name and IP addresses for your Service.

  1. Open the Services page of the admin console.
  2. Select Advertise, and then select Define a Service.
  3. Within the Define a Service dialog, provide a name and description for your Service.
  4. Choose a port or set of ports your Service will advertise, including the tcp: transport protocol prefix (for example, tcp:443). Currently, TCP is the only supported transport protocol. Alternatively, enter do-not-validate to skip port validation.
  5. Provide the Service with an identity by adding one or more tags.
  6. Select Add service.

You are now ready to configure and advertise a Service Proxy for a resource running on a tailnet device. The Service exists as a logical endpoint, that you can populate by one or more Service Proxies.

Step 2: Start a resource to expose as a Service

Start a resource on a tailnet device that you want to expose as a Tailscale Service. This resource can be a web server, database, or any other service that you want to make available through Tailscale.

For example, you might start a basic web server using Node.js and the http-server package that listens on port 8080:

# Install globally
npm install -g http-server

# Then start a basic web server
http-server -p 8080

This example starts a basic web server that serves static files from the current directory on port 8080.

Step 3: Create a Service Proxy

You can configure Service Proxies using either the tailscale serve CLI command or using a configuration file. We recommend using the CLI method because it automatically handles both configuration and advertisement, while the configuration file method gives you control over these as separate steps.

  1. Run the tailscale serve command with the --service flag followed by the service name, the protocol, the port number, and the destination:
tailscale serve --service=svc:<service-name> --https=443 127.0.0.1:8080

The command returns output similar to the following:

This machine is configured as a service proxy for `svc:web-server`, but approval from an admin is required. Once approved, it will be available in your Tailnet as:

http://web-server.<tailnet-name>.ts.net:3000/
|-- proxy http://127.0.0.1:3000

When you configure and advertise a Service Proxy using the tailscale serve CLI command, it automatically uses background mode (which you would normally need to use the --bg flag for when using the tailscale serve command).

This command configures and automatically advertises a Service Proxy for the resource. When you use the tailscale serve command with the HTTPS protocol, Tailscale automatically provisions a TLS certificate for your unique tailnet DNS name.

  1. Run the tailscale serve status command to verify your configuration:
tailscale serve status --json

Step 4: Approve the Service Proxy

If your tailnet has auto-approval policies set up for the Service, the Service Proxy is automatically approved. If not, an Admin, Network admin, or Owner must approve the Service Proxy before it becomes active.

  1. Open the Services page of the admin console.
  2. Select the name of the Service you created earlier.
  3. Locate the pending Service Proxy advertisement in the Service hosts section.
  4. Select Approve.

After approval, the Service Proxy becomes active and starts handling traffic for the Tailscale Service. Users in the tailnet can now connect to the Service using its MagicDNS name or IP addresses (provided they have the necessary access permissions).

Drain a Service Proxy

Use the tailscale serve drain command to stop the Service Proxy from advertising itself for a service (svc:<service-name>):

tailscale serve drain svc:<service-name>

After you run the serve drain command, the Service Proxy stops accepting new incoming connections. However, any ongoing connections remain alive until they close normally.

After all connections close gracefully, you can safely remove the Service Proxy configuration.

Remove a Service Proxy configuration

Do not remove a Service Proxy configuration before draining it. Doing so abruptly ends all connections to the advertised resource.

After draining the Service Proxy for a resource, you can remove its configuration using one of three ways: remove a specific configuration (such as for a specific port number), remove the entire configuration, or reset the configuration file. The best method depends on how much of the configuration file you want to preserve.

You can check your serve configuration file at any point using the tailscale serve status command.

tailscale serve status -json

Remove a specific Service Proxy configuration

If you configured multiple Service Proxies for a single resource using different port numbers or protocols, you can use the off argument to remove only a specific port configuration. To remove a specific Service Proxy configuration for a resource for a specific port number, re-run the original tailscale serve command (that you used to configure the Service Proxy) with the off argument. You must run the command with the same values and flags as you did to set up the Service Proxy.

tailscale serve --service:"svc:<service-name>" --https:<port> <additional-flags> off

Adding the off argument at the end of the command you used to advertise the Service Proxy with the same flag removes the Server Proxy configured for a port. For example, have a Service Proxy for web-server on HTTPS port 443 and a Service Proxy for web-server on HTTP ports 80 and 3000 and you need to remove the Service Proxy for HTTPS port 443:

  1. Run this command to disable its configuration for only HTTPS port 443:
tailscale serve --service="svc:web-server" --https=443 off
  1. Then, re-advertise with only HTTP port 80:
tailscal serve advertise svc:web-server
Here's a more complete example of removing a specific Service Proxy configuration:
# Run tailscale up <...>
# Set up a few L7 Service Proxies:

tailscale serve --service="svc:web-server" --https=443 8080
tailscale serve --service="svc:web-server" --https=443 --set-path /mt2 8081
tailscale serve --service="svc:web-server" --http=80 3000

# When you want to modify config, drain it first.

tailscale serve drain svc:web-server

# Wait until all connections close.

# To only remove the Service Proxy configuration for the /mt2 path on port 443:

tailscale serve --service="svc:web-server" --https=443 --set-path /mt2 off

# Then, advertise it again and it will only create one Service Proxy on HTTPS port 443

tailscal serve advertise svc:web-server

# To remove the Service Proxy configuration for for HTTPS port 443:

tailscale serve --service:"svc:web-server" --https=443 off
# You will see a prompt asking you to confirm
# After you confirm, it removes all configured Service Proxies on port 443 but preserves other port configured for the same service resource.
# Advertise the service again without the removed HTTPS port:

tailscale serve advertise svc:web-server

Remove all Service Proxy configurations for a resource

To remove the configuration for a specific (which can have one or more Service Proxies), use the tailscale serve clear command.

tailscale serve clear svc:<service-name>

This removes all Service Proxy configurations for the resource from serve configuration file.

Here's a more complete example of removing all Service Proxy configurations for a resource:
# Run tailscale up <...>
# Set up a few L7 Service Proxies:

tailscale serve --service="svc:web-server" --https=443 8080
tailscale serve --service="svc:web-server" --https=443 --set-path /mt2 8081
tailscale serve --service="svc:web-server" --http=80 3000

# When you want to modify config, drain it first:

tailscale serve drain svc:web-server

# Wait until all connections close.

# Remove the configuration for svc:web-server:

tailscale serve clear svc:web-server

Remove all Service Proxy configurations

To reset the entire configuration file (removing all configured Service Proxy configurations), use the tailscale serve reset command.

tailscale serve reset

This removes all configured Service Proxies from the serve configuration file.

Update a Service Proxy

You can update or modify a Service configuration using the tailscale serve command or by editing the serve configuration file directly. You should drain the service before modification.

To update a Service Proxy configuration for a given protocol, port, and path, run tailscale serve with the same flags. For example, to start a Service Proxy configured with HTTPS on port 443 pointed to a text snippet:

  1. Run the following command to start a Service Proxy configured with HTTPS on port 443 pointed to a text snippet:
tailscale serve --service="svc:web-server" --https=443 text:example
  1. Then, check the configuration with tailscale serve status --json:
{
  "Services": {
    "svc:web-server": {
      "TCP": {
        "443": {
          "HTTPS": true
        }
      },
      "Web": {
        "web-server:443": {
          "Handlers": {
            "/": {
              "Text": "example"
            }
          }
        }
      }
    }
  }
}

To update the Service Proxy default path point to local port 8081:

  1. Run the following command:
tailscale serve --service="svc:web-server" --https=443 8081
  1. Then, check the configuration with tailscale serve status --json:
{
  "Services": {
    "svc:web-server": {
      "TCP": {
        "443": {
          "HTTPS": true
        }
      },
      "Web": {
        "web-server:443": {
          "Handlers": {
            "/": {
              "Proxy": "http://127.0.0.1:8081"
            }
          }
        }
      }
    }
  }
}

To run a different protocol on a port for a local resource, you need to remove all existing Service Proxy configurations on the port, then add the configuration again. For example, let's say you have a Service Proxy configured for my-web-app with HTTPS on port 443 pointed to a text example, but you need to update it to use HTTP instead of HTTPS:

  1. Remove the Service Proxy configuration for port 443 by running the following command:
tailscale serve --service="svc:my-web-app" --https=443 off
  1. Then, re-run the tailscale serve command to set up the Service Proxy with HTTP:
tailscale serve --service="svc:my-web-app" --http=443 text:example

The command returns output similar to the following:

Available within your tailnet:

http://web-server.king-grouse.ts.net:443/
|-- text  "example"

Configure a Service Proxy using a configuration file

To configure a Service Proxy using a configuration file, you need to create a serveconfig.json file that contains the configuration for the Service Proxy. Note that when you use the configuration file method, you must configure the Service Proxy, then advertise it as two separate steps.

  1. Create a file named serveconfig.json that contains a tailscale serve configuration. This example configures a Service Proxy for a local web server exposed on port 443 over HTTPS:
{
  "Services": {
    "svc:<service-name>": {
      "TCP": {
        "443": {
          "HTTPS": true
        }
      },
      "Web": {
        "<service-name>:443": {
          "Handlers": {
            "/": {
              "Proxy": "http://127.0.0.1:8080"
            }
          }
        }
      }
    }
  }
}
  1. Run a localAPI call to apply the configuration:
tailscale debug localapi POST serve-config - <serveconfig.json
  1. Run the tailscale serve status command to verify your configuration:
tailscale serve status --json
  1. Advertise the Service Proxy:
tailscale serve advertise svc:<service-name>

Your Service Proxy is now handling traffic for your Tailscale Service. You can validate this by running tailscale status --json | jq '.Self.CapMap."service-host"' to check the service-host status.

Set up automatic approval

Tailscale clients can advertise new Service Proxies, but administrators must approve or deny new advertisements (similar to subnet route approval). You can set auto-approval policies to enable certain clients, users, or tags to automatically advertise and approve new Service Proxies for a specific Service or group of Services.

  1. Go to the Access Control page of the admin console.

  2. Create an auto-approval policy to approve new Service Proxies for an individual Tailscale Service or groups of Tailscale Services (defined by a tag). The following shows an example:

    "autoApprovers": {
      "services": {
        "svc:<service-name>": ["tag:server"],
        "tag:prod-service": ["tag:prod-infra"]
      },
    },
    

The example creates an auto-approval rule for Tailscale clients tagged with the tag:server to advertise new Service Proxies, for the Tailscale Service svc:<service-name>. Additionally, it specifies that Tailscale clients with the tag tag:prod-infra can advertise new Service Proxies, and automatically receive approval, for Tailscale Services with the tag tag:prod-service.

Validate your Service

You can validate that your Service successfully advertised locally, and that it passed port validation. To do this, run the following tailscale status command and pass its output to the jq command-line JSON processor:

tailscale status --json | jq '.Self.CapMap."service-host"'

The jq output should show the service-host status.

Configure Service access

You can use a Tailscale Service as a destination in grant access control policies.

  1. Go to the Access Control page of the admin console.
  2. Create a grant rule that grants access to your Service. For example, this grant uses svc:web-server a destination, on port 443, with access granted to "autogroup:member.
{
  "src":  ["autogroup:member"],
  "dst":  ["svc:web-server"],
  "ip": ["443"],
},

You can also reference groups of Tailscale Services using a tag you've assigned to each Service. This example grants access to a group of production Services with access to the Service svc:database.

{
  "src":  ["tag:prod-service"],
  "dst":  ["svc:database"],
  "ip": ["5432"],
},

Check Service status

To check the status of your Service, you can use the Services page of the admin console.

  1. Open the Services page of the Tailscale admin console.
  2. Within the Advertised section, you should find your Tailscale Service listed with configured Service Proxies.

Service Proxy types

Tailscale supports three types of Service Proxies, each operating at different layers of the networking stack. While the OSI model isn't a perfect representation of modern networking, it provides a useful framework for understanding these distinctions. There are three different types of Service Proxies: layer 7 (application), layer 4 (transport), and layer 3 (network). This section explains each type, when to use them, and notes about their specific capabilities

Layer 7 Service Proxies

Layer 7 (application) Service Proxies provide the most sophisticated forwarding mechanism by understanding and manipulating application layer protocols. It can inspect, modify, and route traffic based on application-specific content. These types of Service Proxies work well when you need Tailscale to inject authentication headers in the packets or path-based routing. For example, /api/* requests might go to one server while /static/* goes to another.

You can create a layer 7 Service Proxy by setting the protocol value to http or https when using tailscale serve.

  • The port number is the port to expose the Service Proxy on.
  • You can use the optional --set-path flag to use a custom file path. By default, it uses /.
  • The destination can be text, a file path, or a local address. Refer to Tailscale Serve examples for more examples.

Layer 4 Service Proxies

Layer 4 (transport) Service Proxies operate at the transport (TCP) layer of the OSI model. They act as TCP forwarders that don't modify packet data, but might not preserve packet boundaries and metadata. These types of Service Proxies work well for standard TCP services like web servers and databases. They have less overhead than layer 7 Service Proxies because they don't parse application layer protocols.

You can create a layer 4 Service Proxy by setting the protocol value to tcp or tls-terminated-tcp when using tailscale serve.

  • The port number is the port to expose a TCP forwarder on. The TCP forwarder forwards raw TLS-terminated brackets.
  • You cannot use the --set-path flag to use a custom file path. It must be empty or unset.
  • The destination is the local address where the raw TCP packets will be forwarded to (for example, tcp://localhost:5432).

Layer 3 Service Proxies

Layer 3 (network) Service Proxies are a special type of Service Proxy that operates at the IP packet level and forwards all traffic, unmodified, to the operating system networking stack.

You might consider using a layer 3 Service Proxy if the application or resource you're serving requires UDP support or you need to preserve exact packet boundaries and sizes. However, keep in mind that they have the following limitations:

  • Require additional operating system configuration to handle the unmodified packets.
  • Don't have any built-in application layer features like authentication headers.
  • Only work on Linux.

You can create a layer 3 Service Proxy on a Linux device by running the tailscale serve command (with the service information) with the --tun flag.

tailscale serve --service=svc:<service-name> --tun

Using the --tun flag creates a layer 3 protocol-agnostic Service Proxy, which offers more control over the way packets flow to the resource. This type of Service Proxy forwards all traffic heading to the Tailscale Service to your local device without modifying it. In this mode, you would likely be doing some of your own iptables configuration or something like that to take full control of the packet and make it go to your desired destination.

Service states

This section covers the states of Services in the admin console. In the Services page of the admin console, a Service can be in the following states:

  • Pending approval: The Service has one or more Service Proxies that have been advertised but are awaiting approval from an Admin, Network admin, or Owner.
  • Needs configuration: The Service Proxy has been defined but has an invalid or missing configuration.
  • Connected: At least one Service Proxy is actively advertising the Service.
  • Offline: No Service Proxies are currently advertising the Service.
  • Pre-approved: A device has been automatically approved based on an auto-approval policy but is not yet advertising the Service.
  • Draining: The Service Proxy is in the process of draining, meaning it is no longer accepting new connections but is still handling existing ones.

Limitations

Tailscale Services has the following limitations while in alpha:

  • TCP-only protocol support: Services currently only support TCP transport protocol, with UDP unavailable except through layer 3 Service Proxies on Linux that require additional OS configuration.
  • No outgoing connections: Virtual IP addresses assigned to Services can only accept incoming connections, preventing any outgoing connections from being initiated.
  • Linux-only layer 3 proxies: Layer 3 Service Proxies that preserve packet boundaries only work on Linux and require additional tool configuration, such as iptables.

Last updated Aug 29, 2025