Setting up a home server so that you can access it over tailscale network using a domain you own
If you would like to leave feedback, please use the Github discussions for this blog post.
This is how I setup my server so I can access things such as Audiobookshelf, Jellyfin, makemkv and more over the Internet.
Doing this also allows you to allow others of your choice to be able to access whatever apps you want them to, as well.
Through NPM and Tailscale Access controls, you can even control the ability for a user to be able to even attempt to access a service or port on the machine you share with them.
Requirements
You will need the following:
- A Tailscale account, which is free to sign up and use.
- Your own domain name you can manage
AandAAAArecords. I bought mine through Cloudflare. - A computer to run tailscale and OCI Containers, such as Docker or Podman.
- TrueNAS Community Edition can run Tailscale under their “Apps” section.
I recommend choosing “Host Network” for the Network Configuration so it isn’t behind another layer of networking. It is also recommended to bring the administrative interface to another port, so http
80/tcpand https443/tcp and 443/udpare available for your apps. I also had to make nginx-proxy-manager a custom app and having it usenetwork_mode: hostfor it to be able to access the container networks.- Proxmox can now run OCI images apparently.
- uCore which I have ran in the past.
- Really any computer if you go looking how to set things up.
Tailscale setup
Register your server
Once you have your account and have access to the dashboard, you will want to add your server to the Tailnet. I recommend creating a a tag and Disable key expiry during adding your server or shortly afterward. You don’t want to have to log into the server to renew the keys and it is much easier to manage ACLs based on tags.
Setup Tailscale DNS
DuckDNS is supported for NPM’s Let’s Encrypt, so you might want to try it out.
You will want to keep a subdomain in mind for your server to use for your custom domain, as you will want to use Split DNS for just that subdomain. Even though it will be a publicly resolvable domain, since it will point to CGNAT IPv4 and ULA IPv6 addresses, routers such as OpenSense will refuse to provide the records to clients due to DNS Rebind Protection.
To get around this problem, enable the following:
- Under DNS settings, click
Add nameserver. - Click the 3-dot button next to whatever nameserver you added and click
Edit.... - Turn on
Restrict to domain Split DNSand enter the subdomain in the text field. Mine isserver.melzaks.com. - Click
Save - Still under DNS settings, click
Add search domain.... - Enter the subdomain in the text field. Again mine is
server.melzaks.com - Click
Add search domain
Setting up the search domain will allow your clients reach out to the provided name server to get the Tailnet device IP. An example would be for my domain, http://jellyfin would get me to the same device and then I can have NPM redirect to https://jellyfin.server.melzaks.com
Do not add the same SSL certificates to the redirection hosts. If you do, you will get an SSL warning, as the certificate does not match the domain.
Just know that if you type something like
https://jellyfin, it won’t load anything, as no certificate is applied to the redirect. Only thehttp://jellyfinwould have the response to redirect to the FQDN.
Setup Access Control Policies
Add tcp:80, tcp:443 and upd:443 in your Tailscale Access control policy to allow devices to access your apps. I have mine setup as Sources: All users and devices can access destinations: tag:apps on port and protocol tcp:80, tcp:443, udp:80, udp:443.
In order to access the NPM web GUI, you should have another rule that allows only your account as a Source, your tag or server device group as the destination and tcp:81 for the port. This will allow you to access it over the Tailnet, making it easy and secure to setup.
Share your server with your friends and family
You can share your just the server with anyone you want after you get things up and running.
Domain setup
Log into your DNS registrar and get to the part where you can edit your A and AAAA records. Guide to create records for Cloudflare DNS
It should not offer the ability to Proxy the connection, but if it does, make sure it is turned off.
- You will want to create four new records, two
Aand twoAAAA.- One
Arecord will be for the server name. For me, it wasserver.melzaks.com. Use the IPv4 address of the Tailnet for your server. - The other
Arecord will be for the wildcard subdomains for the server. For me, it was*.server.melzaks.com. Use the same IPv4 address of the Tailnet for your server. - Repeat for both of the
AAAArecords, instead use the IPv6 address of the server.
- One
This should all that is needed for setting up your custom domain.
Repeat the process if you want other Tailnet devices to be resolvable with your DNS.
Also, make sure to update the records if your devices ever have their IPs change.
Container setups
Time to setup the container images and start serving content!
I had to use firewall-cmd to unblock http, https and other ports on Fedora server even if the container binds to a Tailnet IP, so keep local firewalls in mind.
NPM
I changed the TrueNAS administration web port to be 8080 and 8443. It is under
General Settings, thenGUI Settingsbutton. Remember to put that HTTPS port into the server URL going forward to get back to the TrueNAS web GUI.
I am currently running nginx-proxy-manager as a custom app on TrueNAS. The Custom Config looks like this:
services:
nginx-proxy-manager:
container_name: nginx-proxy-manager
image: jc21/nginx-proxy-manager:latest
network_mode: host
restart: unless-stopped
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
version: '3.9'
volumes:
npm_data: Null
npm_letsencrypt: Null
Log into the web interface using your domain name for the server and port 81. The my URL would be
http://server.melzaks.com:81orhttp://server:81lettings the search domain do the work.- If you have MagicDNS turned on, you can also use the Tailnet name of the server, too.
Setup your username and password for NPM. You will want to save these somewhere.
Click on
Certificateson the web interface.- This is where things get complicated. You can get certificates all sorts of ways from different providers. Just keep in mind that the server will not be accessible on the public Internet, so
Let's Encrypt via HTTPwon’t work. - Since I registered my domain with Cloudflare, I ended up using a Cloudflare API token for this next part. If you create a token, you will want to securely save that somewhere to be able to reference later.
- Enter both the wildcard subdomain and the domain of the server in the
Domain Namestext field. Mine was*.server.melzaks.comandserver.melzaks.com. - Leave
ECDSA 256as theKey Type. - Under
DNS Provider, choose whichever DNS you signed up with and are using. I haveCloudflare, so I replaced the string after=to be the API token I generated for this purpose. - Click
Savebutton.
- This is where things get complicated. You can get certificates all sorts of ways from different providers. Just keep in mind that the server will not be accessible on the public Internet, so
Click on Access Lists`. Having this list setup can deny access to apps that are not on the allow list.
- On the details tab:
- Name the Access list using the
Nametext field. Mine isSecure Tailnet Systems.
- Name the Access list using the
- On the rules tab:
- Click
Addbutton.- Create an
Allowfor the IPv4 or IPv6 address of the Tailnet device you want to allow. - Leave
Denyasall - Click
Savebutton.
- Create an
- Repeat for each IPv4 and IPv6 address of all the Tailnet devices you want to allow.
- Click
- On the details tab:
Click on
Hostsand thenProxy Hosts.Click
Add Proxy Host.- On the details tab:
- Enter the apps domain name in
Domain Namestext field. Example would bejellyfin.server.melzaks.com. Schemeishttp,Forward Hostname / IPis the IP address of the docker container for the app,Forward Portis the internal port of the app. Example would behttp,172.16.2.2,8096.- You will have to use
docker container inspector some other method to determine the internal IP address of the app. A lot of chicken and egg going on here. - You will also have to look up what the internal port of the service should be, looking at other docker-compose setups, how the image is built or even the default ports for the app when it isn’t in a container can help you figure out what the correct port for the web interface should be.
- If you can, try to manually assign the internal IP address of the container. You will have to get back into NPM to change it if the container pulls a different IP.
- You can turn off Port Bind mode when setting up apps in TrueNAS, as you won’t be accessing them directly.
- You will have to use
Access Listshould bePublicly Accessibleif you want anyone that has shared access to the device to be able to access it, otherwise select the correct Access List.- Turn on
Websockets Support. It might be needed, depending on the app.
- Enter the apps domain name in
- On the SSL tab:
SSL Certificateselect the certificate you setup earlier. Mine says*.server.melzaks.com, server.melzaks.com.- Turn on
Force SSL - Turn on
HTTP/2 Support, some apps might work better with it on. - Feel free to turn on or keep off the rest of the settings
- Click
Savebutton.
- On the details tab:
Repeat for each app you want to host.
Optional redirects
- Click on
Hostsand thenRedirection Hosts. - Click
Add Redirection Host.- Start enter apps short domain name in
Domain Namestext field. Example would bejellyfin. - Leave
SchemeasAuto. Enter FDQN for the app inForward Domain. Example would bejellyfin.server.melzaks.com. - Leave
HTTP Codeas301 Moved permanently - Click
Savebutton.- Do not set SSL, as it will not match properly and you will get an error on page load of the short domain.
- Start enter apps short domain name in
WARNING! If you have to make a change to the SSL Certificate by removing one, make sure it is removed from every host before deleting it. If you do not, the container will break and you will have to manually edit the files in the /data volume to remove traces of trying to load the now deleted SSL folder. This bug should probably be brought up to the NPM container maintainers at some point.
Also, NPM can do a Proxy redirect of it’s own container port, just use localhost and port 81. Just don’t block port 81 in case things go bad.
Jellyfin
I am not going to mention much here except make sure to have the Published Server URL be the same as what you have in the NPM Proxy setting. Mine is https://jellyfin.server.melzaks.com
Follow this official Jellyfin container documentation to help you get started with that. You shouldn’t need to use the ports section, though.
Wrap up
I wrote this to help me look up how to do this again, as it is not easy and also to share with other interested people.
As for sharing the connection with your friends and family, just have then sign up for Tailscale account and then send the share with a link they can click or via email.
All they would need is to install Tailscale app on their ChromeCast, AndroidTV, computer or phone and type in the URL you want them to access. Don’t forget to get them any additional usernames and passwords for Jellyfin and such.
Feel free to let me know if I should expand on a thing, have a question or comment using the Github discussions for this blog post.