Skip to content

Add Documentation for Tailscale Ingress (HTTP/HTTPS Service Exposure) #19

@Soypete

Description

@Soypete

Add Documentation for Tailscale Ingress (HTTP/HTTPS Service Exposure)

Summary

The current Tailscale integration documentation (docs/tailscale-integration.md) covers LoadBalancer services but doesn't document using the Tailscale IngressClass for exposing HTTP/HTTPS services.

Problem

Users may try to expose web applications (like Grafana, Metabase, etc.) via Tailscale using LoadBalancer services, which doesn't work properly for HTTP/HTTPS traffic. This results in connection refused errors.

What Works (Documented)

  • ✅ LoadBalancer services for raw TCP (Kubernetes API, PostgreSQL)
  • ✅ VIP route advertisement
  • ✅ Magic DNS for .ts.net hostnames

What's Missing (Undocumented)

  • ❌ Using Tailscale Ingress for HTTP/HTTPS services
  • ❌ Difference between LoadBalancer vs Ingress approaches
  • ❌ When to use which method

Proposed Solution

Add a new section to docs/tailscale-integration.md explaining Tailscale Ingress usage.

Suggested Content

When to Use LoadBalancer vs Ingress

LoadBalancer Services - For raw TCP services:

  • Databases (PostgreSQL, MySQL, Redis)
  • SSH services
  • Kubernetes API
  • Any service that doesn't use HTTP protocol

Ingress Resources - For HTTP/HTTPS services:

  • Web applications (Grafana, Metabase, etc.)
  • REST APIs
  • Web dashboards
  • Any HTTP-based service

Example: Exposing a Web Application

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: grafana-tailscale
  namespace: monitoring
  annotations:
    tailscale.com/tailnet-fqdn: grafana.tail6fbc5.ts.net
    tailscale.com/tags: tag:k8s-foundry,tag:production
spec:
  ingressClassName: tailscale  # Use Tailscale ingress controller
  defaultBackend:
    service:
      name: grafana
      port:
        number: 3000
  tls:
    - hosts:
        - grafana

Result: Accessible at https://grafana-1.tail6fbc5.ts.net (TLS auto-provisioned)

How It Works

  1. Tailscale operator creates a dedicated proxy pod for the Ingress
  2. The proxy handles HTTP/HTTPS routing and TLS termination
  3. Traffic flows: Browser → Tailscale → Ingress Proxy → Service → Pod
  4. The operator automatically assigns a .tail6fbc5.ts.net hostname

LoadBalancer Example (for comparison)

For TCP services like PostgreSQL:

apiVersion: v1
kind: Service
metadata:
  name: postgres-tailscale
  annotations:
    tailscale.com/expose: "true"
    tailscale.com/hostname: postgres
    tailscale.com/tags: tag:k8s-foundry,tag:production
spec:
  type: LoadBalancer
  loadBalancerClass: tailscale
  selector:
    app: postgresql
  ports:
    - port: 5432
      targetPort: 5432

Result: Accessible at postgres.tail6fbc5.ts.net:5432

Real-World Example

This issue was discovered when trying to expose Metabase (web analytics tool):

  • Initial attempt: LoadBalancer service → Connection refused
  • Solution: Tailscale Ingress → Works perfectly

The Ingress approach properly handles HTTP routing and TLS, while LoadBalancer is meant for raw TCP forwarding.

Suggested Documentation Location

Add a new section after "What Gets Deployed" (around line 205):

## Exposing Services via Tailscale

### HTTP/HTTPS Services (Web Apps)

Use Kubernetes Ingress resources with `ingressClassName: tailscale`:

[Include Ingress example from above]

### TCP Services (Databases, APIs)

Use LoadBalancer services with `loadBalancerClass: tailscale`:

[Include LoadBalancer example from above]

Additional Resources

Benefits

  1. Prevents users from wasting time debugging LoadBalancer services for HTTP apps
  2. Shows the correct pattern for each use case
  3. Helps users understand when Foundry's Tailscale integration ends and manual Kubernetes configuration begins
  4. Provides copy-paste examples for common scenarios

Labels: documentation, tailscale, enhancement
Priority: Medium - Affects user experience but workaround exists

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions