Skip to content

Add an option to bind the server to a tailnet#960

Closed
MasonEgger wants to merge 4 commits intotemporalio:mainfrom
MasonEgger:tailnet
Closed

Add an option to bind the server to a tailnet#960
MasonEgger wants to merge 4 commits intotemporalio:mainfrom
MasonEgger:tailnet

Conversation

@MasonEgger
Copy link

What was changed

Add Tailscale (tsnet) integration to temporal server start-dev, allowing the dev server to be exposed on a
Tailscale network without manual port forwarding or VPN configuration.

d83bb51 — add tsnet (Tailscale) support for dev server

  • New internal/devserver/tsnet.go with StartTsnet(), TCP proxy (proxy()/acceptLoop()), and TsnetServer with
    graceful shutdown
  • Tests for bidirectional proxy, connection close, and unreachable destinations

b252afb — wire tsnet into server start-dev command

  • Add --tsnet, --tsnet-hostname, --tsnet-authkey, --tsnet-state-dir flags to commands.yaml
  • Run make gen to produce flag bindings
  • Call StartTsnet from commands.server.go when --tsnet is set, proxy both gRPC and UI ports

7eb244f — docs: add tsnet usage guide

  • tailnet.md documenting usage, auth options, hostname/port customization, headless mode, and shutdown

dbe1d27 — fix tsnet proxy correctness and shutdown reliability

  • TCP half-close in proxy() — use CloseWrite() instead of full Close() so bidirectional flows complete
    correctly
  • Idempotent Stop() via sync.Once, nil-safe server close
  • Goroutine tracking with sync.WaitGroup — Stop() drains in-flight proxies before closing the tsnet server
  • Logger plumbing into proxy()/acceptLoop() for observability
  • Transient accept error handling — net.ErrClosed returns silently, other errors log and retry
  • context.Context on StartTsnet for cancellation propagation
  • filepath.Join for state directory path
  • Naming bridge doc on TsnetOptions.AuthKey

Why?

Running temporal server start-dev only listens on localhost, which makes it inaccessible from other machines.
Tailscale's tsnet library lets us expose the dev server on a tailnet with zero configuration beyond --tsnet,
making it easy to develop against a shared dev server from multiple machines.

Checklist

  1. Closes
  2. How was this tested:
    - 8 tsnet-specific tests: TestProxyBidirectional, TestProxyConnectionClose, TestProxyUnreachableDestination,
    TestStopIdempotent, TestProxyLogsDialError, TestAcceptLoopTransientError, TestAcceptLoopTracksGoroutines,
    TestProxyHalfClose
    - go test ./internal/devserver/... — 12/12 pass
    - go test ./internal/temporalcli/ -run TestServer_StartDev_TsnetFlags — pass
    - go vet ./internal/devserver/ — clean
    - make build — pass
    - Manual testing: go run ./cmd/temporal server start-dev --tsnet on a tailnet, connected from a second
    machine via temporal workflow list --address temporal-dev:7233
  3. Any docs updates needed?
    - tailnet.md included in this PR, we may want to turn this into a tutorial or docs. Including now for context but we can move it later
    - May want to add a section to docs.temporal.io under CLI/dev serve

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants