tsproxy is an HTTP reverse proxy that configures a Tailscale device for each upstream.
This command exposes the backend at http://my-app
and https://my-app.<tailnet-name>.ts.net
:
tsproxy --upstream=my-app=http://127.0.0.1:8000
NOTE: MagicDNS must be enabled.
Repeat the --upstream
flag for each backends.
Backends can be exposed on the public Internet using Tailscale Funnel. Use the funnel
option:
tsproxy --upstream=my-public-app=http://127.0.0.1:8000;funnel
tsproxy
serves metrics about itself and Prometheus HTTP Service Discovery targets on the host's two tailscale IPs.
To add an upstream to service discovery, use the prometheus
option:
tsproxy --upstream=my-app=http://127.0.0.1:8000;prometheus
Then use this Prometheus scrape config:
- job_name: tsproxy
http_sd_configs:
- url: http://<tsproxy-host>:<tsproxy-port>/sd
The tsproxy metrics port (flag --port
) defaults to 32019
. It's automatically registered in service discovery.
The proxy sets the X-Webauth-User
and X-Webauth-Name
headers for requests made by users. This works well with Grafana's Auth Proxy.
Requests originating from tagged nodes (this includes Tailscale's Funnel nodes) are proxied as is, without any additional headers.
To add the ACL tag tag:tsnet
to all devices created by tsproxy, create an Auth key, then run the process with TS_AUTH_KEY=<key>
. All upstreams will automatically be tagged.
This works well for ACLs.
"acls": [
{"action": "accept", "src": ["group:admin"], "dst": ["tag:tsnet:80,443"]},
],
To change the ACL tag, update TS_AUTH_KEY
and set FORCE_REAUTH=1
.
This is the systemd unit I use to run tsproxy
: https://gist.github.com/sr/f8b1860cca428b04fc2b0b84ea561348.