One TSDProxy, three containers, one shared Tailscale connection
One TSDProxy, three containers, one shared Tailscale connection
Three containers share one Tailscale machine using SNI routing, each with its own custom domain.
TSDProxy Config
/config/tsdproxy.yaml
defaultProxyProvider: shared
dnsProviders:
cloudflare:
provider: cloudflare
apiToken: "your-cloudflare-api-token"
tlsProviders:
acme:
provider: acme
email: "admin@example.com"
defaultDNSProvider: cloudflare
defaultTLSProvider: acme
cleanupDNS: true
docker:
local:
host: unix:///var/run/docker.sock
targetHostname: host.docker.internal
defaultProxyProvider: shared
tailscale:
providers:
shared:
clientId: "your_client_id"
clientSecret: "your_client_secret"
tags: "tag:shared-proxy"
shared: true
hostname: "shared-proxy"
dataDir: /data/
http:
hostname: 0.0.0.0
port: 8080
log:
level: infoDocker Compose
services:
webapp:
image: nginx:alpine
labels:
tsdproxy.enable: "true"
tsdproxy.name: "webapp"
tsdproxy.domain: "webapp.example.com"
tsdproxy.port.1: "443/https:80/http"
portainer:
image: portainer/portainer-ee
labels:
tsdproxy.enable: "true"
tsdproxy.name: "portainer"
tsdproxy.domain: "portainer.example.com"
tsdproxy.port.1: "443/https:9000/http"
memos:
image: neosmemo/memos:stable
labels:
tsdproxy.enable: "true"
tsdproxy.name: "memos"
tsdproxy.domain: "memos.example.com"
tsdproxy.port.1: "443/https:5230/http"How it works
All three containers share the shared Tailscale provider, which creates a single Tailscale machine named shared-proxy. Each container gets its own custom domain (webapp.example.com, portainer.example.com, memos.example.com). DNS CNAME records point each domain to the same Tailscale machine, and TLS connections are routed by SNI to the correct container. Only HTTPS ports are supported in shared mode. The shared Tailscale machine starts when the first container appears and stops when the last one is removed.
Last updated on