Easily expose services on your Tailscale network.
This project provides an extremely easy to use proxy for exposing services on your Tailscale network under their own MagicDNS name. It is particularly useful if you're hosting several services on the same machine and want to access them by name instead of needing to remember port numbers.
go install github.com/sierrasoftworks/tailservice@latest
At its simplest, you can expose a service on your local machine by running the
tailservice
command with a --name
and one or more --tcp
, --udp
, or --tls
arguments specifying the ports to expose.
# Expose port 80 on the local machine as my-service on your tailnet,
# listening on ports 80 and 443 (port 443 will get a TLS certificate
# automatically).
tailservice --name my-service --tls 443:80 --tcp 80:80
The tailservice
command supports exposing ports using TCP and UDP
network protocols. It also supports automatically generating TLS certificates
for your services using Let's Encrypt (if you
have configured your Tailscale account to support HTTPS certificates).
When specifying a port to expose, you first indicate the type of protocol
you'd like to receive traffic on (e.g. --tcp
, --udp
or the special --tls
variant), followed by the listener specification.
# Forwards raw TCP traffic from port 80 on the Tailnet service
# to port 8080 on the local machine.
tailservice --name my-service --tcp 80:8080
# Forwards raw UDP traffic from port 53 on the Tailnet service
# to port 53 on a remote machine.
tailservice --name my-service --udp 53:8.8.4.4:53
# Forwards TLS traffic from port 443 on the Tailnet service
# to port 8080 on another Tailnet node.
tailservice --name my-service --tls 443:example-node.tails-scales.ts.net:8080
Tailscale's Funnel functionality allows you to expose tailnet services to the public
internet, allowing clients without Tailscale installed to access the service. To enable
this functionality, you can use the --funnel
flag when starting tailservice
and
configure a listener on port 443
, 8443
or 10000
.
# Forwards TLS traffic from port 443 on your funnel endpoint to
# port 8080 on the local machine.
tailservice --name my-service --tls 443:8080 --funnel
By default, tailservice
will save its configuration to disk so that it can
be restarted without the need to re-authenticate. Running in this manner retains
the IP address of the service on your Tailnet, allowing you to use the same
DNS name to access it regardless of how fresh your DNS cache is.
If you'd prefer that the service is removed from your Tailnet when it is
stopped, you can use the --ephemeral
flag to run in ephemeral mode. This
mode is particularly useful if you're running tailservice
in a container
or for test purposes.
tailservice --name my-service --tcp 80:80 --ephemeral
If you're running tailservice
in a container or on a headless machine,
you may find it useful to specify the Tailscale Authkey using an environment
variable. Doing so is only necessary on the first run, as the resulting config
will be saved to disk (note that this does not apply if --ephemeral
is used
or if the config file is deleted).
# Configure your Tailscale authentication key
export TS_AUTHKEY="tskey-1234567890abcdef"
If you're having trouble getting tailservice
to work, you can enable debug
logging by passing the --ts-debug
flag. This will cause tailservice
to
print out the raw Tailscale logs to the console, which may help you to
diagnose the problem.
tailservice --name my-service --tcp 80:80 --ts-debug