Normally we don’t have to use SSL when we connect to the services via Tailscale as all connections are end-to-end encrypted and only allowed users could access your network. But there are always exceptions like you want put your tailscale domain behind a public domain or you have to use SSL for internal connections. For example, horader on ios requires the SSL and it won’t work when we host hoarder using docker even we enable HTTPS on tailscale DNS and add cert to the NAS. When I access hoarder via the tailscale of the NAS, it always returns insecure connection. I tried created the SSL cert using tailscale cert and make it the default cert of my Synology, it still fails as tailscale cert only cover the port 443 so the services running at other ports are not covered.

Use Tailscale as Sidecar

In Remote Accessing NAS Using Tailscale, I introduced three methods to access the services hosted on the NAS. One of them is to run a sidecar of tailscale with the containerized service to expose it to the tailnet. Here we can run it with an reverse proxy and put the containerized service behind the reverse proxy. Moreover, we could use a public domain to access our containerized service. The below is my docker-compose.yaml which runs tailscale container as a sidecar with NPM (Nginx Proxy Manager).

version: "3.9"
	services:
	  tailscale:
	    image: tailscale/tailscale:latest
	    container_name: tailscale
	    hostname: tailscale-router
	    restart: unless-stopped
	    networks:
	      - tailnet
	    environment:
	      - TS_AUTHKEY=tskey-auth-your-key
	      - TS_EXTRA_ARGS=--accept-routes
	      - TS_AUTH_ONCE=false
	      - TS_STATE_DIR=/var/lib/tailscale
	      - TS_DEBUG_FIREWALL_MODE=auto
	      - TS_USERSPACE=false
	    cap_add:
	      - NET_RAW
	      - NET_ADMIN
	    privileged: true
	    volumes:
	      - "/dev/net/tun:/dev/net/tun"
	      - "/your/tailscale/config:/var/lib/tailscale"
	      - "/your/tailscale/state:/var/run/tailscale"
	      
	  npm:
	    container_name: npm
	    image: 'jc21/nginx-proxy-manager:latest'
	    restart: unless-stopped
	    network_mode: "service:tailscale"
	    volumes:
	      - "/your/nginx_proxy_manager/data:/data"
	      - "/your/nginx_proxy_manager/letsencrypt:/etc/letsencrypt"
	
	networks:
	  tailnet:
	    driver: bridge

Proxying

Once we have both containers up and running, we can use your.ts.net:81 to access the NPM since they share the same network. And we can create SSL cert for our public domain like hoarder.your.domain and it only works with DNS challenge for me. To use DNS challenge, we need to get the API key from the DNS provider to get the edit permission on our DNS records shown below (I’m using Cloudflare).

Then we can create proxy host for hoarder.your.domain and use the SSL cert created above. The destination should be your-nas-local-ip:port.

Setup Public Domain

The next step is to set up the public domain on the DNS resolver and I’m using Cloudflare which is highly recommended. We can create a CNAME record for hoarder.your.domain or use a wildcard like *.your.domain, and the value will be the domain of the tailscale container (it can be found on the admin console of tailscale). In this way, we don’t need to add any new record to Cloudflare even we want to add more services later. All we need is to add a proxy host in NPM since the wildcard will resolve any subdomains to the domain of our tailscale container. Then NPM will pick it up and do the heavy-lifting work for us.

Final thoughts

This will do the job and allow us to access these containerized services using SSL and the public domain but it still requires the device in the tailnet (aka. the device must install the tailscale client or use subnet router) to actually access the service as we just resolve the public domain to the tailnet domain. Now I have two tailscale clients on my Synology, one is installed via package center and another one is hosted by docker, But I’m thinking of removing the one I installed via package center to reduce the redundancy.