Having a reverse proxy in a Tailscale network can be very useful of you have a lot of services and have a hard time remembering the ports for all your services. It also comes with the added bonus of removing the pesky “This site is not secure” warning since we’ll be generating signed certificates for our domain.
It's important to follow this guide step by step.
Preparation
- A custom Docker network to put Tailscale and all of the services we want to be able to access through Tailscale on. Below is my
Docker network create
command:
sudo docker network create --driver=bridge --ip-range=100.10.0.0/24 --gateway=100.10.0.1 --subnet=100.10.0.0/24 tail-net
- A Tailscale docker container on the custom Docker network we created above. I recommend either “EDACerton”s container for its continued (at the time of writing at least!) updates, but I’ve not had any problems running “deasmi”s container either. So whichever you prefer there.
- A Nginx Proxy Manager (hereafter referred to as NPM) Docker container. NPM Plus will also work well here.
- A domain that you’ll use to access your services. Since I use Cloudflare, thats what I’ll be using for this guide.
- A Tailscale account
Tailscale Container Config
Important
In the TS container settings, add
--accept-dns=false
in the “Extra Arguments” field. 1
- If you have not done so already, set TS to use the custom docker network (in this example, Tail-net) you’ve created by changing its “Network Type”
- Give the container whatever hostname you like using the provided field (this is the name the device will have in your “My Devices” list in Tailscale)
- Follow the directions in the container to add the node to your account
- I recommend disabling key expiry for this node in your TS admin panel
NPM Container Config
- In the container config, toggle on “Advanced View” in the top right
- Change the “Network Type” to “None”
- In the “Extra Parameters” field add
--net=container:[name-of-TS-container]
- Ensure the TS container starts before NPM by placing it higher in your list of Docker containers than NPM. There should be a little green lock icon on the right of your Unraid navigation bar that will let you rearrange containers after you click it.Â
Tailscale FIRST! NPM Second!
If NPM ever starts while TS is not running, it will go into a crash loop and you might have to disable autostart on the container and restart the Docker service to recover.
NPM Config
- Open your NPM web UI. You won’t have any ports on your Unraid host to do this anymore, but that’s not a problem, you can access it at the Tailscale address of your Docker node, port 81. The default login can be found in the overview in the container settings if you haven’t already changed it.
- Add a new admin user for yourself, log in using the new credentials, then delete the default one.
- Go to the SSL certificates tab and click “Add SSL Certificate” (if you using NPM Plus, its called “TLS Certificate”) to add a new Let’s Encrypt (NPM Plus, certbot) cert.
- I like using wildcard certs for this for simplicity, so I use “*.example.com”; if you aren’t sure about this, just use a wildcard cert.
- Enter your email, toggle on “Use a DNS Challenge”, toggle to agree to the ToS, then select Cloudflare as your DNS provider; the DNS challenge option is used because NPM is not running at a public IP address.
- In the text box that shows up, paste the API token you copied down earlier in where the placeholder text is
- Save it, and if it fails, try it again with longer propagation time; I’ve had to increase it to 30s in the past to get it to work for me.
Tailnet Config
- In the TS Admin panel, go into “DNS”, then scroll down to “Nameserves”. Under “Global Nameservers”, add “Cloudflare Public DNS”
- Change the “Override local DNS” toggle to ON
Normally you don't want to use the "Override local DNS" function, but I couldn't get it to work any other way.
- Now go to “Access Controls” and edit the
hosts
anddacls
part to something like this:
Tricky ACLs!
A lot of Tailscale problems can stem from poorly configured ACLs! Always double check you ACL rules to make sure they work as intended. Errors can be really tricky to spot!
Cloudflare Config
- For the domain you want to use, set your A record 2 to point to your TS Docker node’s address (get this by going into your TS Admin console and copying the devices “Adress” field) and disable Cloudflare’s proxy; you don’t need it. Anyone can look up the address, but it’s a private IP that’s only accessible to your Tailnet or those you’ve shared the node with.
- Create a zone edit token for your domain and copy it to a notepad. You create tokens in your Cloudflare profile, use the “Edit zone DNS” template and in the “Zone Resources” section, set it to Include, Specific Zone, [Your Domain]. The first two entries should already be set, so all you really need to do is set it to your domain.
Extra Instructions for NPM
Each host obviously needs to be set up in Cloudflare as a CNAME (and remember, you don’t want any of them proxied), but also in NPM. For NPM, you can use the name of the Docker containers as the destination address.
The last thing to keep in mind is that when you set up your proxy hosts, you need to use the internal port the container is listening on, not whatever port you have mapped on the host because NPM is connecting directly to the containers, not through the host IP.
Setting up CNAMEs in Cloudflare
The CNAMEs in Cloudflare can be tricky to set up for our Tailscale This is how I set up mine:
Type = CNAME
Name (required) = foo.bar
Target (required) = bar.example.com
or bar.@
Proxy Status = OFF
TTL = Auto
Remember that we already have a A Record for "bar.example.com" so we only need to CNAME "foo.bar" to get it to work!
Refrences
- HOW TO: Reverse Proxy with Tailscale on Reddit https://www.reddit.com/r/unRAID/comments/1darur5/how_to_reverse_proxy_with_tailscale/
- NPM Plus on Github https://github.com/ZoeyVid/NPMplus
Footnotes
-
The “—accept-dns=false” flag in TS that was added earlier is to make sure that Docker host names keep working. Without that flag, TS may override the Docker DNS and those hostnames may not work depending on what settings you’re using on your TS admin panel. Since the DNS is kind of irrelevant for this Docker node it’s fine to disable it here. This was a detail that caused me a lot of headaches before I figured out what the problem was and how to solve it, so don’t overlook it. ↩
-
You can have more than one A record on a domain, as long as they don’t conflict with each other! Take my setup for example: “example.com → A record (proxied) → IP adress” and then “foo.example.com → A record (DNS only) → Tailscale IP”. Then a bunch of CNAMEs pointing to those A records. This allows me to use only 1 domain but split it between Tailscale and the few services I expose to the web.. ↩