{"slug":"tailscale-services","title":"Tailscale Services","tags":["tailscale"],"agent_summary":"Last validated: Feb 2, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Tailscale Services\r\n\r\nLast validated: Feb 2, 2026\r\n\r\nServices increase reliability, leverage Tailscale's access-controlled routing, and provide a centralized way to manage all internal resources available in your Tailscale network (known as a tailnet). You can focus on maintaining your applications while Tailscale handles the networking complexity.\r\n\r\nTailscale Services let you publish internal resources (like databases or web servers) as named services in your tailnet.\r\n\r\nInstead of connecting to specific devices, users connect to Tailscale Services using stable [MagicDNS](https://tailscale.com/docs/features/magicdns) names while Tailscale automatically routes traffic to available hosts across your infrastructure.\r\n\r\nThis approach decouples your resources from the devices hosting them. For example, a database service remains accessible at the same address even when you migrate it to a different host, add redundant hosts for high availability, or route traffic across regions. You gain built-in traffic steering, granular access control, approval workflows, and the ability to configure different endpoint types for different layers of the networking stack.\r\n\r\n## [Use cases](https://tailscale.com/docs/features/tailscale-services\\#use-cases)\r\n\r\nYou can use Tailscale Services in a variety of scenarios to securely expose internal resources within your tailnet in a way that decouples them from the devices hosting them. For example:\r\n\r\n- **Developer workflows and internal tooling**: Make any internal application or developer resource highly available, horizontally scalable, and secure without complex load balancer configurations.\r\n- **Database connectivity**: Connect securely to database clusters (PostgreSQL, MySQL, RDS) with simplified connection scaling and identity-based access controls.\r\n- **Cluster meshes**: Enable cross-cluster or hybrid-cloud connectivity between any compute resources like EC2 instances, Kubernetes services, or containers.\r\n- **Version-controlled applications**: Generate stable hostnames for frequently updated, version-controlled, or ephemeral resources that persist across deployments.\r\n- **IoT integrations**: Stream device logs and telemetry securely to SIEM or logging services without exposing IoT devices to the public internet.\r\n- **Internal APIs and webhooks**: Expose internal APIs securely without public domains or complex mTLS configurations while maintaining granular access control.\r\n\r\n## [Prerequisites](https://tailscale.com/docs/features/tailscale-services\\#prerequisites)\r\n\r\nTo get started with Tailscale Services, you must have:\r\n\r\n- An active tailnet.\r\n- One or more devices running Tailscale v1.86.0 or later, or an [unstable](https://tailscale.com/docs/install/unstable) v1.87.x release.\r\n- [Owner, Admin, or Network admin](https://tailscale.com/docs/reference/user-roles) account permissions.\r\n- An internal resource running on a tailnet device that you want to expose as a Tailscale Service. The device hosting the resource must use a [tag-based](https://tailscale.com/docs/features/tags) identity.\r\n\r\n## [Get started](https://tailscale.com/docs/features/tailscale-services\\#get-started)\r\n\r\nTo get started with Tailscale Services, you need to define a Service through the admin console, configure an endpoint on a tailnet device (the host), then advertise the endpoint.\r\n\r\n### [Step 1: Define a Tailscale Service](https://tailscale.com/docs/features/tailscale-services\\#step-1-define-a-tailscale-service)\r\n\r\nYou define a Tailscale Service using the admin console. Each Tailscale Service consists of a MagicDNS name, a TailVIP (Tailscale Virtual IP address), a resource definition, and one or more back-end hosts.\r\n\r\n1. Open the [Services](https://login.tailscale.com/admin/services) page of the admin console.\r\n2. Select **Advertise**, and then select **Define a Service**.\r\n3. Within the **Define a Service** dialog, provide a name and description for your Service.\r\n4. Choose a port or set of endpoints 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 endpoint validation.\r\n5. (Optional) Provide the Service with an identity by adding one or more [tags](https://tailscale.com/docs/features/tags).\r\n6. Select **Add service**.\r\n\r\nYou have now defined the Service interface. Next, you need to configure a tailnet device as a Service host.\r\n\r\n### [Step 2: Configure a Service host](https://tailscale.com/docs/features/tailscale-services\\#step-2-configure-a-service-host)\r\n\r\nA Service host is a Tailscale device that runs the Tailscale client and advertises one or more endpoints for a specific Tailscale Service. The host handles incoming connections to the Service and routes them to the appropriate resource. Hosts can advertise both local and remote resources.\r\n\r\nAny device you want to use as a Service host must use a [tag-based identity](https://tailscale.com/docs/features/tags). You cannot use a device authenticated with a user account as a Service host.\r\n\r\nMake sure to start the 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.\r\n\r\nFor example, you might start a basic web server using Node.js and the [`http-server` package](https://www.npmjs.com/package/http-server) that listens on port `8080`:\r\n\r\n```shell\r\n# Install globally\r\nnpm install -g http-server\r\n\r\n# Then start a basic web server\r\nhttp-server -p 8080\r\n```\r\n\r\nThis example starts a basic web server that serves static files from the current directory on port `8080`.\r\n\r\nAfter you have your resource running and listening for connections, you can configure it as a Service host.\r\n\r\nYou can configure a Service host using either the `tailscale serve` CLI command or using a [Service configuration file](https://tailscale.com/docs/reference/tailscale-services-configuration-file).\r\n\r\nTailscale recommends 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.\r\n\r\n1. Run the `tailscale serve` command with the `--service` flag followed by the service name, the protocol, the port number, and the destination:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=svc:web-server --https=443 127.0.0.1:8080\r\n```\r\n\r\n\r\n\r\nThe command returns output similar to the following:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\nThis machine is configured as a service host for `svc:web-server`, but approval from an admin is required. Once approved, it will be available in your Tailnet as:\r\n\r\nhttp://web-server.<tailnet-name>.ts.net:443/\r\n|-- proxy http://127.0.0.1:8080\r\n```\r\n\r\n\r\n\r\n\r\n\r\nWhen you configure and advertise an endpoint 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).\r\n\r\n\r\n\r\nThis command configures and automatically advertises an endpoint 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.\r\n\r\n2. Run the `tailscale serve status` command to verify your configuration:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve status --json\r\n```\r\n\r\n\r\nTo use [regional routing](https://tailscale.com/docs/how-to/set-up-high-availability#regional-routing)'s in-region load balancing with Tailscale Services, you will need to enable it on your tailnet.\r\n\r\n### [Step 3: Approve a Service host](https://tailscale.com/docs/features/tailscale-services\\#step-3-approve-a-service-host)\r\n\r\nIf your tailnet has [auto-approval](https://tailscale.com/docs/reference/syntax/policy-file#autoapprovers) policies set up for the Service, the host is automatically approved. If not, an [Admin, Network admin, or Owner](https://tailscale.com/docs/reference/user-roles) must approve the host before it becomes active.\r\n\r\n1. Open the [Services](https://login.tailscale.com/admin/services) page of the admin console.\r\n2. Select the name of the Service you created earlier.\r\n3. Locate the pending advertisements in the **Service hosts** section.\r\n4. Select **Approve**.\r\n\r\nAfter approval, the host 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).\r\n\r\n### [Step 4: Access Tailscale Services from other devices](https://tailscale.com/docs/features/tailscale-services\\#step-4-access-tailscale-services-from-other-devices)\r\n\r\nAfter you configure and approve a Tailscale Service, you need to ensure that other devices in your tailnet can discover and use the routes to the advertised resources.\r\n\r\nTailscale clients version 1.94 and later no longer require enabling `accept-routes` to use Tailscale Services. This lets all clients leverage Tailscale Services by default while simultaneously not enabling `accept-routes` which can lead to route clashes.\r\n\r\nLinux devices running Tailscale version 1.93 or earlier don't discover new routes to Tailscale Services by default. You must explicitly enable accepting routes using the `--accept-routes` flag with the [`tailscale set`](https://tailscale.com/docs/reference/tailscale-cli#set) command:\r\n\r\n```shell\r\nsudo tailscale set --accept-routes\r\n```\r\n\r\n## [Common scenarios](https://tailscale.com/docs/features/tailscale-services\\#common-scenarios)\r\n\r\nThis section covers common scenarios for managing Tailscale Service hosts, including draining a host, removing a host configuration, and updating a Service host configuration.\r\n\r\n### [Drain a host](https://tailscale.com/docs/features/tailscale-services\\#drain-a-host)\r\n\r\nWhen you need to take a Service host offline, you should first drain the host. Draining a host stops it from accepting new incoming connections while letting existing connections to close gracefully.\r\n\r\nUse the `tailscale serve drain` command to stop the host from advertising itself for a service (`svc:<service-name>`):\r\n\r\n```shell\r\ntailscale serve drain svc:<service-name>\r\n```\r\n\r\nAfter you run the `tailscale serve drain` command, all associated endpoints on the host stop accepting new incoming connections. However, any ongoing connections remain alive until they close normally.\r\n\r\nAfter all connections close gracefully, you can safely remove all relevant endpoint configurations.\r\n\r\n### [Remove a host configuration](https://tailscale.com/docs/features/tailscale-services\\#remove-a-host-configuration)\r\n\r\nDo not remove an endpoint configuration before draining it. Doing so abruptly ends all connections to the advertised resource.\r\n\r\nAfter draining the endpoint for a resource, you can remove its configuration using one of three ways: remove a specific endpoint (for a single `protocol:port` endpoint mapping), remove the entire host configuration, or reset the configuration file. The best method depends on how much of the configuration file you want to preserve.\r\n\r\nYou can check your Service configuration file at any point using the `tailscale serve status` command.\r\n\r\n```shell\r\ntailscale serve status -json\r\n```\r\n\r\n#### [Remove an endpoint](https://tailscale.com/docs/features/tailscale-services\\#remove-an-endpoint)\r\n\r\nIf you configured multiple endpoints for a single resource using different port numbers or protocols, you can use the `off` argument to remove only a specific endpoint mapping. To remove a specific endpoint mapping for a resource for a specific port number, re-run the original `tailscale serve` command (that you used to configure the endpoint) with the `off` argument. You must run the command with the same values and flags as you did to set up the endpoint.\r\n\r\n```shell\r\ntailscale serve --service:\"svc:<service-name>\" --https:<port> <additional-flags> off\r\n```\r\n\r\nAdding the `off` argument at the end of the command you used to advertise the endpoint with the same flag removes the endpoint configured for a port. For example, have an endpoint for `web-server` on HTTPS port `443` and an endpoint for `web-server` on HTTP ports `80` and `3000` and you need to remove the endpoint for HTTPS port `443`:\r\n\r\n1. Run this command to disable its configuration for only HTTPS port `443`:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=\"svc:web-server\" --https=443 off\r\n```\r\n\r\n2. Then, re-advertise with only HTTP port `80`:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve advertise svc:web-server\r\n```\r\n\r\n\r\nHere's a more complete example of removing an endpoint:\r\n\r\n```shell\r\n# Run tailscale up <...>\r\n# Set up a few L7 endpoints:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 8080\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 8081\r\ntailscale serve --service=\"svc:web-server\" --http=80 3000\r\n\r\n# When you want to modify config, drain it first.\r\n\r\ntailscale serve drain svc:web-server\r\n\r\n# Wait until all connections close.\r\n\r\n# To only remove the endpoint configuration for the /mt2 path on port 443:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 off\r\n\r\n# Then, advertise it again and it will only create one endpoint on HTTPS port 443\r\n\r\ntailscale serve advertise svc:web-server\r\n\r\n# To remove the endpoint configuration for for HTTPS port 443:\r\n\r\ntailscale serve --service:\"svc:web-server\" --https=443 off\r\n# You will see a prompt asking you to confirm\r\n# After you confirm, it removes all configured endpoints on port 443 but preserves other port configured for the same service resource.\r\n# Advertise the service again without the removed HTTPS port:\r\n\r\ntailscale serve advertise svc:web-server\r\n```\r\n\r\n#### [Remove all endpoint mappings for a Service](https://tailscale.com/docs/features/tailscale-services\\#remove-all-endpoint-mappings-for-a-service)\r\n\r\nTo remove the configuration for a specific Service (which can have one or more endpoints), use the `tailscale serve clear` command.\r\n\r\n```shell\r\ntailscale serve clear svc:<service-name>\r\n```\r\n\r\nThis removes all endpoint configurations for the Service from service configuration file.\r\n\r\nHere's a more complete example of removing all endpoint configurations for a resource:\r\n\r\n```shell\r\n# Run tailscale up <...>\r\n# Set up a few L7 endpoints:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 8080\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 8081\r\ntailscale serve --service=\"svc:web-server\" --http=80 3000\r\n\r\n# When you want to modify config, drain it first:\r\n\r\ntailscale serve drain svc:web-server\r\n\r\n# Wait until all connections close.\r\n\r\n# Remove the configuration for svc:web-server:\r\n\r\ntailscale serve clear svc:web-server\r\n```\r\n\r\n#### [Remove all Service configurations](https://tailscale.com/docs/features/tailscale-services\\#remove-all-service-configurations)\r\n\r\nTo reset the entire configuration file (removing all configured Service configurations), use the `tailscale serve reset` command.\r\n\r\n```shell\r\ntailscale serve reset\r\n```\r\n\r\nThis removes all configured endpoints from the Services configuration file.\r\n\r\n### [Update a Service host configuration](https://tailscale.com/docs/features/tailscale-services\\#update-a-service-host-configuration)\r\n\r\nYou can update or modify a host's Service configuration using the `tailscale serve` command or by editing the Service configuration file directly. You should drain the host before modification.\r\n\r\nTo update an endpoint configuration for a given protocol, port, and path, run `tailscale serve` with the same flags. For example, to start an endpoint configured with HTTPS on port `443`:\r\n\r\n1. Run the following command to start an endpoint configured with HTTPS on port `443`:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=\"svc:web-server\" --https=443 https://localhost:443\r\n```\r\n\r\n2. Then, check the configuration with `tailscale serve get-config --all`:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```json\r\n{\r\n     \"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:443\"\r\n         }\r\n       }\r\n     }\r\n}\r\n```\r\n\r\n\r\n\r\nTo update the endpoint default path point to local port `8081`:\r\n\r\n3. Run the following command:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=\"svc:web-server\" --https=443 https://localhost:8081\r\n```\r\n\r\n4. Then, check the configuration with `tailscale serve get-config --all`:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```json\r\n{\r\n\"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:8081\"\r\n         }\r\n       }\r\n     }\r\n}\r\n```\r\n\r\n\r\nTo run a different protocol on a port for a local resource, you need to remove the existing endpoint configuration on the port, then add the configuration again. For example, let's say you have an endpoint 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:\r\n\r\n1. Remove the endpoint configuration for port `443` by running the following command:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=\"svc:my-web-app\" --https=443 off\r\n```\r\n\r\n2. Then, re-run the `tailscale serve` command to set up the endpoint with HTTP:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve --service=\"svc:my-web-app\" --http=443 http://localhost:8081\r\n```\r\n\r\n\r\n\r\nThe command returns output similar to the following:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\nAvailable within your tailnet:\r\n\r\nhttp://web-server.king-grouse.ts.net:443/\r\n|-- text  \"example\"\r\n```\r\n\r\n\r\n### [Configure a Service host using a configuration file](https://tailscale.com/docs/features/tailscale-services\\#configure-a-service-host-using-a-configuration-file)\r\n\r\nTo configure a Service host using the [Service configuration syntax](https://tailscale.com/docs/reference/tailscale-services-configuration-file), you need to create a configuration file (such as `serveconfig.json`) that contains the configuration for the Service host. Note that when you use the configuration file method, you must configure each endpoint mapping, then advertise it as two separate steps.\r\n\r\n1. Create a file named `serveconfig.json` that contains a [`tailscale serve`](https://tailscale.com/docs/reference/tailscale-cli/serve) configuration. This example configures an endpoint for a local web server exposed on port `443` over HTTPS:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```json\r\n{\r\n\"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:443\"\r\n         }\r\n       }\r\n     }\r\n}\r\n```\r\n\r\n2. Use the `tailscale serve set-config` command to apply the configuration file:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve set-config --all serveconfig.json\r\n```\r\n\r\n3. Run the `tailscale serve status` command to verify your configuration:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve get-config --all\r\n```\r\n\r\n4. Advertise the endpoint:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale serve advertise svc:<service-name>\r\n```\r\n\r\n\r\nYour service host 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.\r\n\r\n### [Set up automatic approval](https://tailscale.com/docs/features/tailscale-services\\#set-up-automatic-approval)\r\n\r\nTailscale clients can advertise new Service hosts, but administrators must approve or deny new advertisements (similar to [subnet route approval](https://tailscale.com/docs/features/subnet-routers#enable-subnet-routes-from-the-admin-console)). You can set auto-approval policies to enable certain clients, users, or tags to automatically advertise and approve new hosts for a specific Service or group of Services.\r\n\r\n1. Go to the [Access controls](https://login.tailscale.com/admin/acls) page of the admin console.\r\n\r\n2. Create an auto-approval policy to approve new hosts for an individual Tailscale Service or groups of Tailscale Services (defined by a [tag](https://tailscale.com/docs/features/tags)). The following shows an example:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```json\r\n\"autoApprovers\": {\r\n     \"services\": {\r\n       \"svc:<service-name>\": [\"tag:server\"],\r\n       \"tag:prod-service\": [\"tag:prod-infra\"]\r\n     },\r\n},\r\n```\r\n\r\n\r\n\r\n\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\n\r\nThe 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`.\r\n\r\n### [Validate your Service](https://tailscale.com/docs/features/tailscale-services\\#validate-your-service)\r\n\r\nYou can validate that your Service successfully advertised locally, and that it passed validation. To do this, run the following [`tailscale status`](https://tailscale.com/docs/reference/tailscale-cli#status) command and pass its output to the [`jq`](https://jqlang.org/) command-line JSON processor:\r\n\r\n```shell\r\ntailscale status --json | jq '.Self.CapMap.\"service-host\"'\r\n```\r\n\r\nThe `jq` output should show the `service-host` status.\r\n\r\n#### [Configure Service access](https://tailscale.com/docs/features/tailscale-services\\#configure-service-access)\r\n\r\nYou can use a Tailscale Service as a destination in [grant](https://tailscale.com/docs/features/access-control/grants) access control policies.\r\n\r\n1. Go to the [Access controls](https://login.tailscale.com/admin/acls) page of the admin console.\r\n2. 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`.\r\n\r\n```json\r\n{\r\n  \"src\":  [\"autogroup:member\"],\r\n  \"dst\":  [\"svc:web-server\"],\r\n  \"ip\": [\"443\"],\r\n},\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nYou 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`.\r\n\r\n```json\r\n{\r\n  \"src\":  [\"tag:prod-service\"],\r\n  \"dst\":  [\"svc:database\"],\r\n  \"ip\": [\"5432\"],\r\n},\r\n```\r\n\r\n### [Use access control tests](https://tailscale.com/docs/features/tailscale-services\\#use-access-control-tests)\r\n\r\nTailscale Services are valid `accept` or `deny` destinations in [access control tests](https://tailscale.com/docs/reference/syntax/policy-file#tests).\r\n\r\n### [Check availability](https://tailscale.com/docs/features/tailscale-services\\#check-availability)\r\n\r\nTo check the availability of your Service, you can use the [Services](https://login.tailscale.com/admin/services) page of the admin console.\r\n\r\n1. Open the [Services](https://login.tailscale.com/admin/services) page of the Tailscale admin console.\r\n2. Within the **Advertised** section, you should find your Tailscale Service listed with configured endpoints.\r\n\r\n## [Reference](https://tailscale.com/docs/features/tailscale-services\\#reference)\r\n\r\nThis section provides reference information about Tailscale Services, including endpoint types and service states.\r\n\r\n### [Endpoint types](https://tailscale.com/docs/features/tailscale-services\\#endpoint-types)\r\n\r\nTailscale supports three types of endpoints, 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 endpoints: 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\r\n\r\n#### [Layer 7 endpoints (application layer)](https://tailscale.com/docs/features/tailscale-services\\#layer-7-endpoints-application-layer)\r\n\r\nLayer 7 (application) endpoints 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 endpoints 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.\r\n\r\nYou can create a layer 7 endpoint by setting the protocol value to `http` or `https` when using `tailscale serve`.\r\n\r\n- The port number is the port to expose the endpoint on.\r\n- You can use the optional `--set-path` flag to use a custom file path. By default, it uses `/`.\r\n- The destination can be text, a file path, or a local address. Refer to [Tailscale Serve examples](https://tailscale.com/docs/reference/examples/serve) for more examples.\r\n\r\n#### [Layer 4 endpoints (transport layer)](https://tailscale.com/docs/features/tailscale-services\\#layer-4-endpoints-transport-layer)\r\n\r\nLayer 4 (transport) endpoints operate at the transport (TCP) layer of the [OSI model](https://tailscale.com/docs/concepts/tailscale-osi). They act as TCP forwarders that don't modify packet data, but might not preserve packet boundaries and metadata. These types of endpoints work well for standard TCP services like web servers and databases. They have less overhead than layer 7 endpoints because they don't parse application layer protocols.\r\n\r\nYou can create a layer 4 endpoint by setting the protocol value to `tcp` or `tls-terminated-tcp` when using `tailscale serve`.\r\n\r\n- The port number is the port to expose a TCP forwarder on. The TCP forwarder forwards raw TLS-terminated brackets.\r\n- You cannot use the `--set-path` flag to use a custom file path. It must be empty or unset.\r\n- The destination is the local address where the raw TCP packets will be forwarded to (for example, `tcp://localhost:5432`).\r\n\r\n#### [Layer 3 endpoints (network layer)](https://tailscale.com/docs/features/tailscale-services\\#layer-3-endpoints-network-layer)\r\n\r\nLayer 3 (network) endpoints are a special type of endpoint that operates at the IP packet level and forwards all traffic, unmodified, to the operating system networking stack.\r\n\r\nYou might consider using a layer 3 endpoint 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:\r\n\r\n- Require additional operating system configuration to handle the unmodified packets.\r\n- Don't have any built-in application layer features like authentication headers.\r\n- Only work on Linux.\r\n\r\nYou can create a layer 3 endpoint on a Linux device by running the `tailscale serve` command (with the service information) with the `--tun` flag.\r\n\r\n```shell\r\ntailscale serve --service=svc:<service-name> --tun\r\n```\r\n\r\nUsing the `--tun` flag creates a layer 3 protocol-agnostic endpoint, which offers more control over the way packets flow to the resource. This type of endpoint 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.\r\n\r\n### [Service states](https://tailscale.com/docs/features/tailscale-services\\#service-states)\r\n\r\nThis 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:\r\n\r\n- **Pending approval**: The Service has one or more hosts that have been advertised but are awaiting approval from an [Admin, Network admin, or Owner](https://tailscale.com/docs/reference/user-roles).\r\n- **Needs configuration**: The host has been defined but has an invalid or missing configuration.\r\n- **Connected**: At least one host is actively advertising the Service.\r\n- **Offline**: No hosts are currently advertising the Service.\r\n- **Pre-approved**: A device has been automatically approved based on an auto-approval policy but is not yet advertising the Service.\r\n- **Draining**: The host is in the process of draining, meaning it is no longer accepting new connections but is still handling existing ones.\r\n\r\n## [Limitations](https://tailscale.com/docs/features/tailscale-services\\#limitations)\r\n\r\nTailscale Services has the following limitations:\r\n\r\n- **TCP-only protocol support**: Services currently only support TCP transport protocol, with UDP unavailable except through layer 3 endpoints on Linux that require additional operating system (OS) level configuration.\r\n- **No outgoing connections**: Virtual IP addresses (TailVIPs) assigned to Services can only accept incoming connections, preventing any outgoing connections from being initiated.\r\n- **No hairpinning**: Service host devices cannot access the Services they host.\r\n- **Linux-only layer 3 endpoints**: Layer 3 endpoints that preserve packet boundaries only work on Linux and require additional tool configuration, such as `iptables`.\r\n- **Text and file endpoints**: The Service configuration file method does not support `text:` or `file:` destinations. These are only available when using the `tailscale serve` CLI command.\r\n- **Limitations with multiple network interfaces**: Service Hosts that have multiple network interfaces and define remote resource destinations might experience issues in specific circumstances. For example, a connection to a remote destination might fail if:\r\n  - The Service Host (1) is a Linux device, (2) is running `tailscaled` without `SO_MARK`, (3) has multiple network interfaces, and (4) does not have the remote destination in its default route table. You can bypass this limitation by running `tailscaled` in [userspace-networking mode](https://tailscale.com/docs/reference/kernel-vs-userspace-routers#userspace-netstack-mode).\r\n  - The Service Host (1) is a macOS device using the [Mac App Store or Standalone variant](https://tailscale.com/docs/concepts/macos-variants), (2) has multiple network interfaces, and (3) does not have the remote endpoint in its default route table. In this case, you can bypass the issue by running the [open source macOS variant](https://tailscale.com/docs/concepts/macos-variants#open-source-tailscaled-variant) (which uses `tailscaled` in userspace-networking mode by default).\r\n\r\n## [Additional information](https://tailscale.com/docs/features/tailscale-services\\#additional-information)\r\n\r\n- Use the [Services endpoint](https://tailscale.com/api#tag/services) in the [Tailscale API](https://tailscale.com/docs/reference/tailscale-api) to manage Services for your tailnet.\r\n  - [List all services](https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services)\r\n  - [Get a service](https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D)\r\n  - [Update a service](https://tailscale.com/api#tag/services/put/tailnet/%7Btailnet%7D/services/%7BserviceName%7D)\r\n  - [Delete a service](https://tailscale.com/api#tag/services/delete/tailnet/%7Btailnet%7D/services/%7BserviceName%7D)\r\n  - [List devices hosting a service](https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/devices)\r\n  - [Get approval status of service on a device](https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/device/%7BdeviceId%7D/approved)\r\n  - [Update approval status of service on a device](https://tailscale.com/api#tag/services/post/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/device/%7BdeviceId%7D/approved)\r\n- For more information about using the [`tsnet`](https://tailscale.com/docs/features/tsnet) package and `Server.ListenService` with Go programs, refer to [`tsnet` server](https://tailscale.com/docs/reference/tsnet-server-api).\r\n- For a complete example that uses `Server.ListenService` and `ServiceModeHTTP` with Tailscale Services, refer to [`tsnet` and Tailscale Services](https://tailscale.com/docs/features/tsnet/how-to/register-service).\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Tailscale Services</h1>\n<p>Last validated: Feb 2, 2026</p>\n<p>Services increase reliability, leverage Tailscale's access-controlled routing, and provide a centralized way to manage all internal resources available in your Tailscale network (known as a tailnet). You can focus on maintaining your applications while Tailscale handles the networking complexity.</p>\n<p>Tailscale Services let you publish internal resources (like databases or web servers) as named services in your tailnet.</p>\n<p>Instead of connecting to specific devices, users connect to Tailscale Services using stable <a href=\"https://tailscale.com/docs/features/magicdns\">MagicDNS</a> names while Tailscale automatically routes traffic to available hosts across your infrastructure.</p>\n<p>This approach decouples your resources from the devices hosting them. For example, a database service remains accessible at the same address even when you migrate it to a different host, add redundant hosts for high availability, or route traffic across regions. You gain built-in traffic steering, granular access control, approval workflows, and the ability to configure different endpoint types for different layers of the networking stack.</p>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#use-cases\">Use cases</a></h2>\n<p>You can use Tailscale Services in a variety of scenarios to securely expose internal resources within your tailnet in a way that decouples them from the devices hosting them. For example:</p>\n<ul>\n<li><strong>Developer workflows and internal tooling</strong>: Make any internal application or developer resource highly available, horizontally scalable, and secure without complex load balancer configurations.</li>\n<li><strong>Database connectivity</strong>: Connect securely to database clusters (PostgreSQL, MySQL, RDS) with simplified connection scaling and identity-based access controls.</li>\n<li><strong>Cluster meshes</strong>: Enable cross-cluster or hybrid-cloud connectivity between any compute resources like EC2 instances, Kubernetes services, or containers.</li>\n<li><strong>Version-controlled applications</strong>: Generate stable hostnames for frequently updated, version-controlled, or ephemeral resources that persist across deployments.</li>\n<li><strong>IoT integrations</strong>: Stream device logs and telemetry securely to SIEM or logging services without exposing IoT devices to the public internet.</li>\n<li><strong>Internal APIs and webhooks</strong>: Expose internal APIs securely without public domains or complex mTLS configurations while maintaining granular access control.</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#prerequisites\">Prerequisites</a></h2>\n<p>To get started with Tailscale Services, you must have:</p>\n<ul>\n<li>An active tailnet.</li>\n<li>One or more devices running Tailscale v1.86.0 or later, or an <a href=\"https://tailscale.com/docs/install/unstable\">unstable</a> v1.87.x release.</li>\n<li><a href=\"https://tailscale.com/docs/reference/user-roles\">Owner, Admin, or Network admin</a> account permissions.</li>\n<li>An internal resource running on a tailnet device that you want to expose as a Tailscale Service. The device hosting the resource must use a <a href=\"https://tailscale.com/docs/features/tags\">tag-based</a> identity.</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#get-started\">Get started</a></h2>\n<p>To get started with Tailscale Services, you need to define a Service through the admin console, configure an endpoint on a tailnet device (the host), then advertise the endpoint.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#step-1-define-a-tailscale-service\">Step 1: Define a Tailscale Service</a></h3>\n<p>You define a Tailscale Service using the admin console. Each Tailscale Service consists of a MagicDNS name, a TailVIP (Tailscale Virtual IP address), a resource definition, and one or more back-end hosts.</p>\n<ol>\n<li>Open the <a href=\"https://login.tailscale.com/admin/services\">Services</a> page of the admin console.</li>\n<li>Select <strong>Advertise</strong>, and then select <strong>Define a Service</strong>.</li>\n<li>Within the <strong>Define a Service</strong> dialog, provide a name and description for your Service.</li>\n<li>Choose a port or set of endpoints your Service will advertise, including the <code>tcp:</code> transport protocol prefix (for example, <code>tcp:443</code>). Currently, TCP is the only supported transport protocol. Alternatively, enter <code>do-not-validate</code> to skip endpoint validation.</li>\n<li>(Optional) Provide the Service with an identity by adding one or more <a href=\"https://tailscale.com/docs/features/tags\">tags</a>.</li>\n<li>Select <strong>Add service</strong>.</li>\n</ol>\n<p>You have now defined the Service interface. Next, you need to configure a tailnet device as a Service host.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#step-2-configure-a-service-host\">Step 2: Configure a Service host</a></h3>\n<p>A Service host is a Tailscale device that runs the Tailscale client and advertises one or more endpoints for a specific Tailscale Service. The host handles incoming connections to the Service and routes them to the appropriate resource. Hosts can advertise both local and remote resources.</p>\n<p>Any device you want to use as a Service host must use a <a href=\"https://tailscale.com/docs/features/tags\">tag-based identity</a>. You cannot use a device authenticated with a user account as a Service host.</p>\n<p>Make sure to start the 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.</p>\n<p>For example, you might start a basic web server using Node.js and the <a href=\"https://www.npmjs.com/package/http-server\"><code>http-server</code> package</a> that listens on port <code>8080</code>:</p>\n<pre><code class=\"language-shell\"># Install globally\r\nnpm install -g http-server\r\n\r\n# Then start a basic web server\r\nhttp-server -p 8080\n</code></pre>\n<p>This example starts a basic web server that serves static files from the current directory on port <code>8080</code>.</p>\n<p>After you have your resource running and listening for connections, you can configure it as a Service host.</p>\n<p>You can configure a Service host using either the <code>tailscale serve</code> CLI command or using a <a href=\"https://tailscale.com/docs/reference/tailscale-services-configuration-file\">Service configuration file</a>.</p>\n<p>Tailscale recommends 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.</p>\n<ol>\n<li>Run the <code>tailscale serve</code> command with the <code>--service</code> flag followed by the service name, the protocol, the port number, and the destination:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=svc:web-server --https=443 127.0.0.1:8080\n</code></pre>\n<p>The command returns output similar to the following:</p>\n<pre><code class=\"language-shell\">This machine is configured as a service host for `svc:web-server`, but approval from an admin is required. Once approved, it will be available in your Tailnet as:\r\n\r\nhttp://web-server.&#x3C;tailnet-name>.ts.net:443/\r\n|-- proxy http://127.0.0.1:8080\n</code></pre>\n<p>When you configure and advertise an endpoint using the <code>tailscale serve</code> CLI command, it automatically uses background mode (which you would normally need to use the <code>--bg</code> flag for when using the <code>tailscale serve</code> command).</p>\n<p>This command configures and automatically advertises an endpoint for the resource. When you use the <code>tailscale serve</code> command with the HTTPS protocol, Tailscale automatically provisions a TLS certificate for your unique tailnet DNS name.</p>\n<ol start=\"2\">\n<li>Run the <code>tailscale serve status</code> command to verify your configuration:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve status --json\n</code></pre>\n<p>To use <a href=\"https://tailscale.com/docs/how-to/set-up-high-availability#regional-routing\">regional routing</a>'s in-region load balancing with Tailscale Services, you will need to enable it on your tailnet.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#step-3-approve-a-service-host\">Step 3: Approve a Service host</a></h3>\n<p>If your tailnet has <a href=\"https://tailscale.com/docs/reference/syntax/policy-file#autoapprovers\">auto-approval</a> policies set up for the Service, the host is automatically approved. If not, an <a href=\"https://tailscale.com/docs/reference/user-roles\">Admin, Network admin, or Owner</a> must approve the host before it becomes active.</p>\n<ol>\n<li>Open the <a href=\"https://login.tailscale.com/admin/services\">Services</a> page of the admin console.</li>\n<li>Select the name of the Service you created earlier.</li>\n<li>Locate the pending advertisements in the <strong>Service hosts</strong> section.</li>\n<li>Select <strong>Approve</strong>.</li>\n</ol>\n<p>After approval, the host 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).</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#step-4-access-tailscale-services-from-other-devices\">Step 4: Access Tailscale Services from other devices</a></h3>\n<p>After you configure and approve a Tailscale Service, you need to ensure that other devices in your tailnet can discover and use the routes to the advertised resources.</p>\n<p>Tailscale clients version 1.94 and later no longer require enabling <code>accept-routes</code> to use Tailscale Services. This lets all clients leverage Tailscale Services by default while simultaneously not enabling <code>accept-routes</code> which can lead to route clashes.</p>\n<p>Linux devices running Tailscale version 1.93 or earlier don't discover new routes to Tailscale Services by default. You must explicitly enable accepting routes using the <code>--accept-routes</code> flag with the <a href=\"https://tailscale.com/docs/reference/tailscale-cli#set\"><code>tailscale set</code></a> command:</p>\n<pre><code class=\"language-shell\">sudo tailscale set --accept-routes\n</code></pre>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#common-scenarios\">Common scenarios</a></h2>\n<p>This section covers common scenarios for managing Tailscale Service hosts, including draining a host, removing a host configuration, and updating a Service host configuration.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#drain-a-host\">Drain a host</a></h3>\n<p>When you need to take a Service host offline, you should first drain the host. Draining a host stops it from accepting new incoming connections while letting existing connections to close gracefully.</p>\n<p>Use the <code>tailscale serve drain</code> command to stop the host from advertising itself for a service (<code>svc:&#x3C;service-name></code>):</p>\n<pre><code class=\"language-shell\">tailscale serve drain svc:&#x3C;service-name>\n</code></pre>\n<p>After you run the <code>tailscale serve drain</code> command, all associated endpoints on the host stop accepting new incoming connections. However, any ongoing connections remain alive until they close normally.</p>\n<p>After all connections close gracefully, you can safely remove all relevant endpoint configurations.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#remove-a-host-configuration\">Remove a host configuration</a></h3>\n<p>Do not remove an endpoint configuration before draining it. Doing so abruptly ends all connections to the advertised resource.</p>\n<p>After draining the endpoint for a resource, you can remove its configuration using one of three ways: remove a specific endpoint (for a single <code>protocol:port</code> endpoint mapping), remove the entire host configuration, or reset the configuration file. The best method depends on how much of the configuration file you want to preserve.</p>\n<p>You can check your Service configuration file at any point using the <code>tailscale serve status</code> command.</p>\n<pre><code class=\"language-shell\">tailscale serve status -json\n</code></pre>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#remove-an-endpoint\">Remove an endpoint</a></h4>\n<p>If you configured multiple endpoints for a single resource using different port numbers or protocols, you can use the <code>off</code> argument to remove only a specific endpoint mapping. To remove a specific endpoint mapping for a resource for a specific port number, re-run the original <code>tailscale serve</code> command (that you used to configure the endpoint) with the <code>off</code> argument. You must run the command with the same values and flags as you did to set up the endpoint.</p>\n<pre><code class=\"language-shell\">tailscale serve --service:\"svc:&#x3C;service-name>\" --https:&#x3C;port> &#x3C;additional-flags> off\n</code></pre>\n<p>Adding the <code>off</code> argument at the end of the command you used to advertise the endpoint with the same flag removes the endpoint configured for a port. For example, have an endpoint for <code>web-server</code> on HTTPS port <code>443</code> and an endpoint for <code>web-server</code> on HTTP ports <code>80</code> and <code>3000</code> and you need to remove the endpoint for HTTPS port <code>443</code>:</p>\n<ol>\n<li>Run this command to disable its configuration for only HTTPS port <code>443</code>:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=\"svc:web-server\" --https=443 off\n</code></pre>\n<ol start=\"2\">\n<li>Then, re-advertise with only HTTP port <code>80</code>:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve advertise svc:web-server\n</code></pre>\n<p>Here's a more complete example of removing an endpoint:</p>\n<pre><code class=\"language-shell\"># Run tailscale up &#x3C;...>\r\n# Set up a few L7 endpoints:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 8080\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 8081\r\ntailscale serve --service=\"svc:web-server\" --http=80 3000\r\n\r\n# When you want to modify config, drain it first.\r\n\r\ntailscale serve drain svc:web-server\r\n\r\n# Wait until all connections close.\r\n\r\n# To only remove the endpoint configuration for the /mt2 path on port 443:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 off\r\n\r\n# Then, advertise it again and it will only create one endpoint on HTTPS port 443\r\n\r\ntailscale serve advertise svc:web-server\r\n\r\n# To remove the endpoint configuration for for HTTPS port 443:\r\n\r\ntailscale serve --service:\"svc:web-server\" --https=443 off\r\n# You will see a prompt asking you to confirm\r\n# After you confirm, it removes all configured endpoints on port 443 but preserves other port configured for the same service resource.\r\n# Advertise the service again without the removed HTTPS port:\r\n\r\ntailscale serve advertise svc:web-server\n</code></pre>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#remove-all-endpoint-mappings-for-a-service\">Remove all endpoint mappings for a Service</a></h4>\n<p>To remove the configuration for a specific Service (which can have one or more endpoints), use the <code>tailscale serve clear</code> command.</p>\n<pre><code class=\"language-shell\">tailscale serve clear svc:&#x3C;service-name>\n</code></pre>\n<p>This removes all endpoint configurations for the Service from service configuration file.</p>\n<p>Here's a more complete example of removing all endpoint configurations for a resource:</p>\n<pre><code class=\"language-shell\"># Run tailscale up &#x3C;...>\r\n# Set up a few L7 endpoints:\r\n\r\ntailscale serve --service=\"svc:web-server\" --https=443 8080\r\ntailscale serve --service=\"svc:web-server\" --https=443 --set-path /mt2 8081\r\ntailscale serve --service=\"svc:web-server\" --http=80 3000\r\n\r\n# When you want to modify config, drain it first:\r\n\r\ntailscale serve drain svc:web-server\r\n\r\n# Wait until all connections close.\r\n\r\n# Remove the configuration for svc:web-server:\r\n\r\ntailscale serve clear svc:web-server\n</code></pre>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#remove-all-service-configurations\">Remove all Service configurations</a></h4>\n<p>To reset the entire configuration file (removing all configured Service configurations), use the <code>tailscale serve reset</code> command.</p>\n<pre><code class=\"language-shell\">tailscale serve reset\n</code></pre>\n<p>This removes all configured endpoints from the Services configuration file.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#update-a-service-host-configuration\">Update a Service host configuration</a></h3>\n<p>You can update or modify a host's Service configuration using the <code>tailscale serve</code> command or by editing the Service configuration file directly. You should drain the host before modification.</p>\n<p>To update an endpoint configuration for a given protocol, port, and path, run <code>tailscale serve</code> with the same flags. For example, to start an endpoint configured with HTTPS on port <code>443</code>:</p>\n<ol>\n<li>Run the following command to start an endpoint configured with HTTPS on port <code>443</code>:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=\"svc:web-server\" --https=443 https://localhost:443\n</code></pre>\n<ol start=\"2\">\n<li>Then, check the configuration with <code>tailscale serve get-config --all</code>:</li>\n</ol>\n<pre><code class=\"language-json\">{\r\n     \"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:443\"\r\n         }\r\n       }\r\n     }\r\n}\n</code></pre>\n<p>To update the endpoint default path point to local port <code>8081</code>:</p>\n<ol start=\"3\">\n<li>Run the following command:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=\"svc:web-server\" --https=443 https://localhost:8081\n</code></pre>\n<ol start=\"4\">\n<li>Then, check the configuration with <code>tailscale serve get-config --all</code>:</li>\n</ol>\n<pre><code class=\"language-json\">{\r\n\"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:8081\"\r\n         }\r\n       }\r\n     }\r\n}\n</code></pre>\n<p>To run a different protocol on a port for a local resource, you need to remove the existing endpoint configuration on the port, then add the configuration again. For example, let's say you have an endpoint configured for <code>my-web-app</code> with HTTPS on port <code>443</code> pointed to a text example, but you need to update it to use HTTP instead of HTTPS:</p>\n<ol>\n<li>Remove the endpoint configuration for port <code>443</code> by running the following command:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=\"svc:my-web-app\" --https=443 off\n</code></pre>\n<ol start=\"2\">\n<li>Then, re-run the <code>tailscale serve</code> command to set up the endpoint with HTTP:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve --service=\"svc:my-web-app\" --http=443 http://localhost:8081\n</code></pre>\n<p>The command returns output similar to the following:</p>\n<pre><code class=\"language-shell\">Available within your tailnet:\r\n\r\nhttp://web-server.king-grouse.ts.net:443/\r\n|-- text  \"example\"\n</code></pre>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#configure-a-service-host-using-a-configuration-file\">Configure a Service host using a configuration file</a></h3>\n<p>To configure a Service host using the <a href=\"https://tailscale.com/docs/reference/tailscale-services-configuration-file\">Service configuration syntax</a>, you need to create a configuration file (such as <code>serveconfig.json</code>) that contains the configuration for the Service host. Note that when you use the configuration file method, you must configure each endpoint mapping, then advertise it as two separate steps.</p>\n<ol>\n<li>Create a file named <code>serveconfig.json</code> that contains a <a href=\"https://tailscale.com/docs/reference/tailscale-cli/serve\"><code>tailscale serve</code></a> configuration. This example configures an endpoint for a local web server exposed on port <code>443</code> over HTTPS:</li>\n</ol>\n<pre><code class=\"language-json\">{\r\n\"version\": \"0.0.1\",\r\n     \"services\": {\r\n       \"svc:web-server\": {\r\n         \"endpoints\": {\r\n           \"tcp:443\": \"https://localhost:443\"\r\n         }\r\n       }\r\n     }\r\n}\n</code></pre>\n<ol start=\"2\">\n<li>Use the <code>tailscale serve set-config</code> command to apply the configuration file:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve set-config --all serveconfig.json\n</code></pre>\n<ol start=\"3\">\n<li>Run the <code>tailscale serve status</code> command to verify your configuration:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve get-config --all\n</code></pre>\n<ol start=\"4\">\n<li>Advertise the endpoint:</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale serve advertise svc:&#x3C;service-name>\n</code></pre>\n<p>Your service host is now handling traffic for your Tailscale Service. You can validate this by running <code>tailscale status --json | jq '.Self.CapMap.\"service-host\"'</code> to check the service-host status.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#set-up-automatic-approval\">Set up automatic approval</a></h3>\n<p>Tailscale clients can advertise new Service hosts, but administrators must approve or deny new advertisements (similar to <a href=\"https://tailscale.com/docs/features/subnet-routers#enable-subnet-routes-from-the-admin-console\">subnet route approval</a>). You can set auto-approval policies to enable certain clients, users, or tags to automatically advertise and approve new hosts for a specific Service or group of Services.</p>\n<ol>\n<li>\n<p>Go to the <a href=\"https://login.tailscale.com/admin/acls\">Access controls</a> page of the admin console.</p>\n</li>\n<li>\n<p>Create an auto-approval policy to approve new hosts for an individual Tailscale Service or groups of Tailscale Services (defined by a <a href=\"https://tailscale.com/docs/features/tags\">tag</a>). The following shows an example:</p>\n</li>\n</ol>\n<pre><code class=\"language-json\">\"autoApprovers\": {\r\n     \"services\": {\r\n       \"svc:&#x3C;service-name>\": [\"tag:server\"],\r\n       \"tag:prod-service\": [\"tag:prod-infra\"]\r\n     },\r\n},\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>The example creates an auto-approval rule for Tailscale clients tagged with the <code>tag:server</code> to advertise new Service Proxies, for the Tailscale Service <code>svc:&#x3C;service-name></code>. Additionally, it specifies that Tailscale clients with the tag <code>tag:prod-infra</code> can advertise new Service Proxies, and automatically receive approval, for Tailscale Services with the tag <code>tag:prod-service</code>.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#validate-your-service\">Validate your Service</a></h3>\n<p>You can validate that your Service successfully advertised locally, and that it passed validation. To do this, run the following <a href=\"https://tailscale.com/docs/reference/tailscale-cli#status\"><code>tailscale status</code></a> command and pass its output to the <a href=\"https://jqlang.org/\"><code>jq</code></a> command-line JSON processor:</p>\n<pre><code class=\"language-shell\">tailscale status --json | jq '.Self.CapMap.\"service-host\"'\n</code></pre>\n<p>The <code>jq</code> output should show the <code>service-host</code> status.</p>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#configure-service-access\">Configure Service access</a></h4>\n<p>You can use a Tailscale Service as a destination in <a href=\"https://tailscale.com/docs/features/access-control/grants\">grant</a> access control policies.</p>\n<ol>\n<li>Go to the <a href=\"https://login.tailscale.com/admin/acls\">Access controls</a> page of the admin console.</li>\n<li>Create a grant rule that grants access to your Service. For example, this grant uses <code>svc:web-server</code> a destination, on port <code>443</code>, with access granted to <code>\"autogroup:member</code>.</li>\n</ol>\n<pre><code class=\"language-json\">{\r\n  \"src\":  [\"autogroup:member\"],\r\n  \"dst\":  [\"svc:web-server\"],\r\n  \"ip\": [\"443\"],\r\n},\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>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 <code>svc:database</code>.</p>\n<pre><code class=\"language-json\">{\r\n  \"src\":  [\"tag:prod-service\"],\r\n  \"dst\":  [\"svc:database\"],\r\n  \"ip\": [\"5432\"],\r\n},\n</code></pre>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#use-access-control-tests\">Use access control tests</a></h3>\n<p>Tailscale Services are valid <code>accept</code> or <code>deny</code> destinations in <a href=\"https://tailscale.com/docs/reference/syntax/policy-file#tests\">access control tests</a>.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#check-availability\">Check availability</a></h3>\n<p>To check the availability of your Service, you can use the <a href=\"https://login.tailscale.com/admin/services\">Services</a> page of the admin console.</p>\n<ol>\n<li>Open the <a href=\"https://login.tailscale.com/admin/services\">Services</a> page of the Tailscale admin console.</li>\n<li>Within the <strong>Advertised</strong> section, you should find your Tailscale Service listed with configured endpoints.</li>\n</ol>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#reference\">Reference</a></h2>\n<p>This section provides reference information about Tailscale Services, including endpoint types and service states.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#endpoint-types\">Endpoint types</a></h3>\n<p>Tailscale supports three types of endpoints, 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 endpoints: 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</p>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#layer-7-endpoints-application-layer\">Layer 7 endpoints (application layer)</a></h4>\n<p>Layer 7 (application) endpoints 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 endpoints work well when you need Tailscale to inject authentication headers in the packets or path-based routing. For example, <code>/api/*</code> requests might go to one server while <code>/static/*</code> goes to another.</p>\n<p>You can create a layer 7 endpoint by setting the protocol value to <code>http</code> or <code>https</code> when using <code>tailscale serve</code>.</p>\n<ul>\n<li>The port number is the port to expose the endpoint on.</li>\n<li>You can use the optional <code>--set-path</code> flag to use a custom file path. By default, it uses <code>/</code>.</li>\n<li>The destination can be text, a file path, or a local address. Refer to <a href=\"https://tailscale.com/docs/reference/examples/serve\">Tailscale Serve examples</a> for more examples.</li>\n</ul>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#layer-4-endpoints-transport-layer\">Layer 4 endpoints (transport layer)</a></h4>\n<p>Layer 4 (transport) endpoints operate at the transport (TCP) layer of the <a href=\"https://tailscale.com/docs/concepts/tailscale-osi\">OSI model</a>. They act as TCP forwarders that don't modify packet data, but might not preserve packet boundaries and metadata. These types of endpoints work well for standard TCP services like web servers and databases. They have less overhead than layer 7 endpoints because they don't parse application layer protocols.</p>\n<p>You can create a layer 4 endpoint by setting the protocol value to <code>tcp</code> or <code>tls-terminated-tcp</code> when using <code>tailscale serve</code>.</p>\n<ul>\n<li>The port number is the port to expose a TCP forwarder on. The TCP forwarder forwards raw TLS-terminated brackets.</li>\n<li>You cannot use the <code>--set-path</code> flag to use a custom file path. It must be empty or unset.</li>\n<li>The destination is the local address where the raw TCP packets will be forwarded to (for example, <code>tcp://localhost:5432</code>).</li>\n</ul>\n<h4><a href=\"https://tailscale.com/docs/features/tailscale-services#layer-3-endpoints-network-layer\">Layer 3 endpoints (network layer)</a></h4>\n<p>Layer 3 (network) endpoints are a special type of endpoint that operates at the IP packet level and forwards all traffic, unmodified, to the operating system networking stack.</p>\n<p>You might consider using a layer 3 endpoint 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:</p>\n<ul>\n<li>Require additional operating system configuration to handle the unmodified packets.</li>\n<li>Don't have any built-in application layer features like authentication headers.</li>\n<li>Only work on Linux.</li>\n</ul>\n<p>You can create a layer 3 endpoint on a Linux device by running the <code>tailscale serve</code> command (with the service information) with the <code>--tun</code> flag.</p>\n<pre><code class=\"language-shell\">tailscale serve --service=svc:&#x3C;service-name> --tun\n</code></pre>\n<p>Using the <code>--tun</code> flag creates a layer 3 protocol-agnostic endpoint, which offers more control over the way packets flow to the resource. This type of endpoint 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 <code>iptables</code> configuration or something like that to take full control of the packet and make it go to your desired destination.</p>\n<h3><a href=\"https://tailscale.com/docs/features/tailscale-services#service-states\">Service states</a></h3>\n<p>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:</p>\n<ul>\n<li><strong>Pending approval</strong>: The Service has one or more hosts that have been advertised but are awaiting approval from an <a href=\"https://tailscale.com/docs/reference/user-roles\">Admin, Network admin, or Owner</a>.</li>\n<li><strong>Needs configuration</strong>: The host has been defined but has an invalid or missing configuration.</li>\n<li><strong>Connected</strong>: At least one host is actively advertising the Service.</li>\n<li><strong>Offline</strong>: No hosts are currently advertising the Service.</li>\n<li><strong>Pre-approved</strong>: A device has been automatically approved based on an auto-approval policy but is not yet advertising the Service.</li>\n<li><strong>Draining</strong>: The host is in the process of draining, meaning it is no longer accepting new connections but is still handling existing ones.</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#limitations\">Limitations</a></h2>\n<p>Tailscale Services has the following limitations:</p>\n<ul>\n<li><strong>TCP-only protocol support</strong>: Services currently only support TCP transport protocol, with UDP unavailable except through layer 3 endpoints on Linux that require additional operating system (OS) level configuration.</li>\n<li><strong>No outgoing connections</strong>: Virtual IP addresses (TailVIPs) assigned to Services can only accept incoming connections, preventing any outgoing connections from being initiated.</li>\n<li><strong>No hairpinning</strong>: Service host devices cannot access the Services they host.</li>\n<li><strong>Linux-only layer 3 endpoints</strong>: Layer 3 endpoints that preserve packet boundaries only work on Linux and require additional tool configuration, such as <code>iptables</code>.</li>\n<li><strong>Text and file endpoints</strong>: The Service configuration file method does not support <code>text:</code> or <code>file:</code> destinations. These are only available when using the <code>tailscale serve</code> CLI command.</li>\n<li><strong>Limitations with multiple network interfaces</strong>: Service Hosts that have multiple network interfaces and define remote resource destinations might experience issues in specific circumstances. For example, a connection to a remote destination might fail if:\n<ul>\n<li>The Service Host (1) is a Linux device, (2) is running <code>tailscaled</code> without <code>SO_MARK</code>, (3) has multiple network interfaces, and (4) does not have the remote destination in its default route table. You can bypass this limitation by running <code>tailscaled</code> in <a href=\"https://tailscale.com/docs/reference/kernel-vs-userspace-routers#userspace-netstack-mode\">userspace-networking mode</a>.</li>\n<li>The Service Host (1) is a macOS device using the <a href=\"https://tailscale.com/docs/concepts/macos-variants\">Mac App Store or Standalone variant</a>, (2) has multiple network interfaces, and (3) does not have the remote endpoint in its default route table. In this case, you can bypass the issue by running the <a href=\"https://tailscale.com/docs/concepts/macos-variants#open-source-tailscaled-variant\">open source macOS variant</a> (which uses <code>tailscaled</code> in userspace-networking mode by default).</li>\n</ul>\n</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/features/tailscale-services#additional-information\">Additional information</a></h2>\n<ul>\n<li>Use the <a href=\"https://tailscale.com/api#tag/services\">Services endpoint</a> in the <a href=\"https://tailscale.com/docs/reference/tailscale-api\">Tailscale API</a> to manage Services for your tailnet.\n<ul>\n<li><a href=\"https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services\">List all services</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D\">Get a service</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/put/tailnet/%7Btailnet%7D/services/%7BserviceName%7D\">Update a service</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/delete/tailnet/%7Btailnet%7D/services/%7BserviceName%7D\">Delete a service</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/devices\">List devices hosting a service</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/get/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/device/%7BdeviceId%7D/approved\">Get approval status of service on a device</a></li>\n<li><a href=\"https://tailscale.com/api#tag/services/post/tailnet/%7Btailnet%7D/services/%7BserviceName%7D/device/%7BdeviceId%7D/approved\">Update approval status of service on a device</a></li>\n</ul>\n</li>\n<li>For more information about using the <a href=\"https://tailscale.com/docs/features/tsnet\"><code>tsnet</code></a> package and <code>Server.ListenService</code> with Go programs, refer to <a href=\"https://tailscale.com/docs/reference/tsnet-server-api\"><code>tsnet</code> server</a>.</li>\n<li>For a complete example that uses <code>Server.ListenService</code> and <code>ServiceModeHTTP</code> with Tailscale Services, refer to <a href=\"https://tailscale.com/docs/features/tsnet/how-to/register-service\"><code>tsnet</code> and Tailscale Services</a>.</li>\n</ul>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}