Skip to content

Latest commit

 

History

History
157 lines (120 loc) · 3.95 KB

File metadata and controls

157 lines (120 loc) · 3.95 KB

Quick Start Guide

Get tsbridge running in 5 minutes.

1. Get OAuth Credentials

  1. Go to https://login.tailscale.com/admin/settings/oauth
  2. Click Generate OAuth client...
  3. Name it something like tsbridge
  4. Under ScopesAuth Keys, check both Read and Write
  5. Tags: Select a tag (e.g., tag:server) - this tag will be used by your services
  6. Click Generate client
  7. Save the Client ID and Secret

2. Create Config File

Create tsbridge.toml:

[tailscale]
oauth_client_id_env = "TS_OAUTH_CLIENT_ID"
oauth_client_secret_env = "TS_OAUTH_CLIENT_SECRET"
default_tags = ["tag:server"]  # Must match or be owned by your OAuth client's tag

[[services]]
name = "app"
backend_addr = "localhost:8080"

3. Run It

export TS_OAUTH_CLIENT_ID=your-client-id
export TS_OAUTH_CLIENT_SECRET=your-client-secret
tsbridge -config tsbridge.toml

Your service is now available at https://app.<tailnet>.ts.net

Common Patterns

Multiple Services

[[services]]
name = "api"
backend_addr = "localhost:8080"

[[services]]
name = "web"
backend_addr = "localhost:3000"

Unix Sockets

[[services]]
name = "app"
backend_addr = "unix:///var/run/app.sock"

Add Identity Headers

[[services]]
name = "internal-api"
backend_addr = "localhost:8080"
whois_enabled = true  # Adds X-Tailscale-User headers

Streaming/SSE Support

[[services]]
name = "events"
backend_addr = "localhost:3000"
write_timeout = "0s"     # No timeout
flush_interval = "-1ms"  # No buffering

Production Setup

[tailscale]
oauth_client_id_file = "/etc/tsbridge/oauth-id"
oauth_client_secret_file = "/etc/tsbridge/oauth-secret"
state_dir = "/var/lib/tsbridge"
default_tags = ["tag:server", "tag:prod"]

[global]
metrics_addr = ":9090"  # Prometheus metrics

[[services]]
name = "api"
backend_addr = "api.internal:8080"
whois_enabled = true
downstream_headers = {
  "Strict-Transport-Security" = "max-age=63072000"
}

Docker

With Docker Compose

services:
  tsbridge:
    image: ghcr.io/jtdowney/tsbridge:latest
    command: ["--provider", "docker"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - tsbridge-state:/var/lib/tsbridge
    environment:
      - TS_OAUTH_CLIENT_ID=${TS_OAUTH_CLIENT_ID}
      - TS_OAUTH_CLIENT_SECRET=${TS_OAUTH_CLIENT_SECRET}
    labels:
      - "tsbridge.tailscale.oauth_client_id_env=TS_OAUTH_CLIENT_ID"
      - "tsbridge.tailscale.oauth_client_secret_env=TS_OAUTH_CLIENT_SECRET"
      - "tsbridge.tailscale.state_dir=/var/lib/tsbridge"
      - "tsbridge.tailscale.default_tags=tag:server"  # Must match or be owned by your OAuth client's tag

  myapp:
    image: myapp:latest
    labels:
      - "tsbridge.enabled=true"
      - "tsbridge.service.name=myapp"
      - "tsbridge.service.port=8080"
      # Optional: Override default tags for this service
      # - "tsbridge.service.tags=tag:api,tag:prod"

volumes:
  tsbridge-state:

Network Requirements: tsbridge and service containers must be on the same Docker network. They don't need to be in the same compose file, but network connectivity is required. See Docker Labels - Docker Networking for multi-compose setups.

Troubleshooting

Validate Your Config

tsbridge -config tsbridge.toml -validate

Common Issues

  • "services must have at least one tag": Add default_tags to [tailscale] section
  • "OAuth client ID not set": Check your environment variables
  • Connection timeouts: For streaming, set write_timeout = "0s"
  • Tag authorization errors: Ensure tags match or are owned by your OAuth client's tag. See Tag Ownership and OAuth Security

Next Steps