TSDProxy: Automatic Tailscale Reverse Proxy for Docker Containers
Automatic Tailscale reverse proxy for Docker containers. Zero sidecars. Label-based config. Automatic HTTPS.
At a glance
- What is it?
- TSDProxy exposes Docker containers on your Tailscale network with a single Docker label and zero sidecars. One TSDProxy instance watches your Docker daemon for labeled containers, creates a Tailscale machine for each one via tsnet, and reverse-proxies traffic with automatic HTTPS. It handles HTTP, HTTPS, TCP, UDP, and port ranges from the same configuration.
- Who is it for?
- TSDProxy is the right choice for a Tailscale user who runs Docker containers and wants them available on their tailnet with minimal configuration. One label per container, one TSDProxy instance, and automatic HTTPS covers the common case entirely.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What TSDProxy Does and Who It Is For
Tailscale makes it straightforward to access a machine securely from anywhere. The friction point comes when you run dozens of Docker containers: each one that needs a Tailscale URL would traditionally require either port forwarding, a separate Tailscale sidecar container per service, or manual tsnet configuration. TSDProxy eliminates this by running a single proxy container that watches the Docker daemon and automatically creates a Tailscale machine for every container tagged with a label.
The target audience is self-hosters, homelab operators, and small development teams who use Tailscale and Docker together. TSDProxy is not a general-purpose reverse proxy: it is designed specifically for the Tailscale use case and depends on the tsnet library to create Tailscale machines programmatically.
How TSDProxy Works Internally
TSDProxy mounts the Docker socket and watches for container events. When a container with tsdproxy.enable: "true" appears, TSDProxy calls tsnet to create a Tailscale machine. The machine receives a hostname from the tsdproxy.name label or the container name, appears in the Tailscale admin console, and gets an automatic HTTPS certificate via Tailscale's Let's Encrypt integration.
Incoming requests to https://myapp.<tailnet>.ts.net are reverse-proxied to the container's internal address. When the container stops, TSDProxy removes the Tailscale machine and its routes. The machine appears and disappears with the container lifecycle.
Beyond the label-based container path, TSDProxy also supports a list provider: a simple YAML file that defines non-Docker services. This lets you expose services that run directly on a host or on a different machine without modifying a Docker Compose file.
Getting Started: One Compose File and One Label
The quickest setup uses a Docker Compose file with two services:
services:
tsdproxy:
image: almeidapaulopt/tsdproxy:2
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- tsdproxy-data:/data
- ./config:/config
ports:
- "8080:8080"
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
myapp:
image: nginx:alpine
labels:
tsdproxy.enable: "true"
tsdproxy.name: "myapp"
volumes:
tsdproxy-data:Start the stack:
docker compose up -dTSDProxy creates a default configuration file at /config/tsdproxy.yaml on first run. Open the dashboard at http://localhost:8080, click the proxy card, and authenticate with Tailscale. The container is then available at https://myapp.<tailnet-name>.ts.net with automatic HTTPS. For automated headless setup, configure an AuthKey or OAuth credential before adding services.
Multi-Port Configuration: TCP, UDP, and Ranges
TSDProxy's port label syntax supports multiple ports per container with per-port protocol control:
labels:
tsdproxy.enable: "true"
tsdproxy.name: "myservice"
tsdproxy.port.1: "443/https:80/http"
tsdproxy.port.2: "80/http:8080/http"
tsdproxy.port.3: "81/http->https://myservice.tailnet.ts.net"
tsdproxy.port.4: "22/tcp:22/tcp"
tsdproxy.port.5: "5060/udp:5060/udp"
tsdproxy.port.6: "2222-2230/tcp:2222-2230/tcp"Port 1 maps HTTPS on 443 to HTTP on container port 80. Port 4 is a TCP proxy for SSH. Port 5 is a UDP proxy for a SIP service or game server. Port 6 is a TCP port range. An HTTP-to-HTTPS redirect can be expressed inline as shown in port 3. This syntax handles the common cases for database access, SSH tunneling, VoIP, and gaming without requiring separate proxy definitions per protocol.
TSDProxy vs Traefik and Caddy for Tailscale Deployments
Traefik and Caddy are general-purpose reverse proxies that support label-based Docker configuration and automatic HTTPS. The difference from TSDProxy is scope. Traefik and Caddy manage certificates and routing for publicly reachable domains, whether from Let's Encrypt or a custom CA. TSDProxy is Tailscale-specific: it uses tsnet to create Tailscale machines directly, so the HTTPS certificate comes from Tailscale's infrastructure and the hostname exists only on your tailnet.
A Tailscale Funnel option is available in TSDProxy to expose a service to the public internet. Funnel routes traffic through Tailscale's edge infrastructure, so you do not need to open a port in your firewall. That is a meaningful difference from Traefik and Caddy, which require the host to be directly reachable from the internet for certificate validation.
The trade-off is portability: TSDProxy only works with Tailscale. If your organization uses headscale or plain WireGuard, TSDProxy is not applicable.
Operational Features: Dashboard, Webhooks, REST API, and Health Checks
TSDProxy provides a web dashboard at port 8080 with real-time status via server-sent events, access logs, and a status timeline for each proxy. Role-based access offers admin and viewer roles with an optional admin allowlist.
Webhook notifications are configurable for proxy events. Supported targets include ntfy, Discord, Slack, Gotify, and a generic webhook endpoint. Health monitoring runs automatic backend health probes with recovery and target re-resolution when a container restarts or changes its internal address.
A REST API provides programmatic control: proxies can be paused, resumed, and managed via API calls. Live configuration reload means you can change settings without restarting TSDProxy. These operational features distinguish TSDProxy from simpler tsnet wrappers that provide no visibility into proxy state.
Maintenance, Beta Status, and License
The last push was on 2026-09-21. The most recent release is v3.0.0-beta.3, published on 2026-06-26. The v3 line has been in beta since June 2026. The stable v2 tag remains available as almeidapaulopt/tsdproxy:2 for production use while v3 stabilizes. The project is licensed under MIT.
The repository is built in Go with a Bun-based frontend. The Dockerfile uses a multi-stage build: a Bun frontend build stage, a Go builder stage, and a final scratch image with only the binary and CA certificates. The resulting image is minimal. An air.toml is included for hot-reload during development.
The go.mod file requires Go 1.26.4 and references tailscale.com v1.100.0 and tailscale.com/client/tailscale/v2 v2.10.1. End-to-end tests run in Docker with the TSDPROXY_E2E_AUTHKEY environment variable, which requires a real Tailscale auth key to execute. Sponsorship information is in the README: the author accepts GitHub Sponsors to support continued development.
Editorial conclusion
TSDProxy is the right choice for a Tailscale user who runs Docker containers and wants them available on their tailnet with minimal configuration. One label per container, one TSDProxy instance, and automatic HTTPS covers the common case entirely. Teams whose containers need public internet exposure can use the funnel option without any additional infrastructure. The limitation is that TSDProxy is Tailscale-specific: it does not work with headscale or other WireGuard-based overlays. The v3 line is still in beta as of June 2026, so verify that the release notes for v3.0.0-beta.3 cover your specific port configuration before upgrading from v2.
Frequently asked questions
How does TSDProxy differ from Traefik for Docker Tailscale setups?
TSDProxy creates Tailscale machines directly via tsnet, so each proxied service gets a tailnet hostname with automatic HTTPS from Tailscale's certificate infrastructure. Traefik is a general-purpose reverse proxy that handles public-internet routing and certificate management, and does not integrate with the Tailscale machine API. TSDProxy only works with Tailscale; Traefik works with any reachable host.
How does TSDProxy compare to Caddy for Tailscale container routing?
TSDProxy creates Tailscale machines via tsnet, so each container gets its own tailnet hostname and HTTPS certificate managed by Tailscale's infrastructure. Caddy is a general-purpose web server with automatic HTTPS via ACME. Caddy does not integrate with the Tailscale machine API, so it cannot automatically register containers on a tailnet the way TSDProxy does.
Does TSDProxy support exposing services to the public internet?
Yes, through Tailscale Funnel. Setting the tailscale_funnel option on a proxy routes traffic from the public internet through Tailscale's edge infrastructure to the container, without requiring a firewall port to be opened directly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/almeidapaulopt-tsdproxy)