Sharing Services Across Tailnets (Day 24)

Using Tailscale's Kubernetes operator to share specific services across tailnets without inviting users directly to the network, while maintaining DNS.

Sharing Services Across Tailnets (Day 24)
Photo by Mohit Tomar / Unsplash

So I needed to share some services with friends outside my tailnet, but:

  • Didn't want to add users directly to my tailnet
  • Preferred not to add public records to Cloudflare (keep using my self-hosted DNS)

The Setup

The current infrastructure setup includes:

  • Traefik as the root reverse proxy in Kubernetes
  • A LoadBalancer service (traefik's) using a private, non-tailscale-routable IP
  • Self-hosted DNS server

The Solution

After doing some research and trials, the approach I went with was to expose the Traefik LoadBalancer service directly to Tailscale using their Kubernetes operator.

And tailscale does include a blog post on how to do this, I recommend checking it out.

1. Installing the Operator

Important: Create an OAuth client in the Tailscale console with Devices Core and Auth Keys write scopes first, (see the full post here).

Install the Tailscale operator using Helm:

  1. Add https://pkgs.tailscale.com/helmcharts to your local Helm repositories:
helm repo add tailscale https://pkgs.tailscale.com/helmcharts
  1. Update your local Helm cache:
helm repo update
  1. Install the operator passing the OAuth client credentials:
helm upgrade \
  --install \
  tailscale-operator \
  tailscale/tailscale-operator \
  --namespace=tailscale \
  --create-namespace \
  --set-string oauth.clientId="<client_id>" \
  --set-string oauth.clientSecret="<client_secret>" \
  --wait
Can be added to be part of helmfile template or argo deployment

2. Exposing the Service

With the operator running, exposing a service is as simple as adding an annotation:

annotations:
  tailscale.com/expose: "true"

3. Sharing Access

From the Tailscale console:

  1. Share both the Traefik node and DNS server
  2. Users can then set their Tailscale DNS to use the shared DNS server
  3. For more granular control, users can use Tailscale's split DNS to route only specific domains

4. ACL Configuration

One useful thing is to set up ACLs to restrict what autogroup:shared and specific tags (the operator is a tagged device) can access.

This ensures users only have access to the services you explicitly want to share.

So

The benefits are essentially:

  • Users don't need direct access to your tailnet
  • DNS resolution works seamlessly (I deployed a new separate DNS server with a limited amount of records just for tailnet shares)
  • No need for public DNS records
  • Fine-grained access control through Tailscale ACLs
  • Services remain secure behind Tailscale's encryption