Reverse Proxy or Not?

I’ve setup a Homelab recently and I’m quiet new to it so pardon my ignorance.
I haven’t exposed my Homelab to the internet (apparently) yet, therefore I’m using Tailscale for remote access, my question is what’s the purpose of using Reverse Proxies (RP) like Nginx, Traefik etc. as in my understanding it exposes you (securely) to the internet, but still there are risks…

Everybody on YT and Reddit seems to use RP and I don’t understand why, So is there a good reason to use it or should I just rely on Tailscale. Are there other benefits of using a RP I would like to get enlightened about Reverse Proxies…
Thanks in Advance.

The biggest feature of RPs is hosting multiple (web) services on the same port.

A port can be bound by max one running process. You can run multiple web services on a single host (=single IP address) but then you’d have to use a different port for each service. Typically those ports would be 8080, 3000, etc. Even with static host entries or DNS for each of your services, you’d still need to use the port number in URLs, e.g. grafana.mydomain.com:3000.

A RP runs a client-facing web server and uses TLS SNI to know what “backend” service is being accessed. The URLs then don’t need to use the port number and are just grafana.mydomain.com.

There are some security advantages in using RPs (they tend to be well-tested mature services, as opposed to whatever each individual service may be using for its web interface) but they are irrelevant for small internal environments not exposed to the public Internet.

A reverse proxy do not expose services to the internet by default. You still have to set it up that services are reachable from the outside. The benefit and why most people use a reverse proxy is that they don’t have to remember multiple IP and Ports. For example: If I have a service like Portainer. I can enter this service with the IP let’s say 192.168.10.20 and the port for Portainer which is 9443. So I have to enter 192.168.10.20:9443 to enter Portainer. This is difficult to remember. With a reverse proxy you set up a domain example.com and maybe subdomain for your service. If we stick to the example with Portainer you can call the url portainer.example.com. It’s a lot easier to remember because if you want to access Portainer you just type portainer instead of a number you associate with portainer. The Reverse proxy is the link between the url and the IP.

I would just use cloudflare tunnels.

If you want to start easy, I’d recommend using Caddy. It’s super simple to set up for the simple use cases. It even handles certificate management, if you happen for have a domain.

If you’re just starting out then I’d recommend Caddy as the easiest reverse proxy to set up.

Nginx is very powerful, but quite complex and overkill for home usage.

Think of it like having groceries delivered. You could go to the store knowing the specific aisle (port #) an item is in and select the item yourself. Alternatively you could have the groceries ready for pickup. You just tell them you want a banana. You don’t have to know which aisle bananas are in. Someone else knows where they are and they’ll go get it for you.

If your the shop owner this gives you a few advantages. You could move the bananas to somewhere else in the store and not have to inform every customer that they’re in a new location. If you have a lot of customers coming in you could source bananas from multiple locations… maybe even a different store - customers don’t care they just want their banana, however you got it isn’t important to them.

Its simple: Do you need to provide access to “unknown” people? Proxy!

Do only you (and maybe people living in the house) need access? VPN!

Using a reverse proxy is beneficial for multiple Szenarios. Primarily, from a security point of view, a reverse proxy sits behind a firewall in front of your webserver(s). A reverse proxy intercepts traffic and decouples your server from frontend access. You can deploy a dedicated proxy server on Linux (nginx, haproxy etc) but you can also use your firewall (pfsense, opnsense etc) to act as a proxy. This provides you with additional security as you can use ips/ids mechanisms to look inside the encrypted traffic, automate certificate creation (acme) etc. Secondary, from a management perspective a reverse proxy helps you organizing your web exposed services.
As a rule of thumb: expose as little services as necessary to the www and use a vpn whenever you can.
Hope this helps.

Benefits:

  • running multiple “websites” (=services) on the same port and the same IP
  • TLS termination. Let a dedicated software manage it instead of whatever TLS library built in the image. +Efficiency. +Timely security patches.
  • authentication. From dead simple HTTP Basic to mTLS and/or SSO
  • complete control of your HTTP requests. Need URL rewriting or adding an extra HTTP header/cookie? Just add a couple of lines in the config

Tailscale/VPN is great, but it solves only one issue (allow outside access only to you, and not strangers), while leaving all other issues unsolved. Hey, do you like seeing “insecure site” warnings for your http://192.168.1.100:8080 ? Personally, I prefer working with https://cloud.home.arpa or https://cloud.example.com

Reverse proxies have several main benefits.

  1. They allow you to use virtual hosts (different hostnames) for the same IP/port combination. So you could point “servicea.domain.tld” and “serviceb.domain.tld” at the same reverse proxy, but have the proxy direct them to their respective backends. This can help avoid needing to use annoying port numbers, doubly-so if you have to change some due to conflicts. Most can also do some really advanced direction, for instance regex matches on URLs, to send clients to exactly where you want them to go.

  2. They can simplify SSL termination, authentication, etc. into a central place. Different services handle SSL, authentication, etc. in different ways, some annoyingly so. A reverse proxy can let you use, for instance, a single SSL certificate in a single place for a variety of different services, and on replacing it (e.g. with Let’s Encrypt automatically) reload only a single service for minimal interruption. Or let you set up an SSO provider for various apps in a central place and then authenticate all traffic through it.

  3. They can effectively hide the technology and shortcomings of the backend from clients. For instance, Node.JS applications often listen on 3000; if an attacker sees a service listening on 3000, they’re able to conclude it’s Node.JS and attack it with that knowledge. But if it’s just some other thing behind NGiNX listening on 443, it’s harder to find that information. This goes for various other crubs of data in the HTTP headers, like SSL versions, HTTP versions, etc. It’s like putting a nice strong metal gate in front of your flimsy front door.

  4. The more common reverse proxy apps are designed for - and thus really good at - serving HTTP traffic. Thus, they tend to be much better at it, in the sense of security vulnerabilities, bugfixing, performance, etc. than tons of individual apps, often with solo developers, are. For instance a vulnerability in how software handles HTTP/2 requests might leave your directly-exposed app vulnerable for a while as the developer struggles to fix all the dependencies and push out a new version, but NGiNX likely has a fix before it’s even released or extremely soon after. So you basically get the added security from the popularity and ubiquity of the tool. They can also speed things up by caching static assets for the backend, saving on work especially if the backend app is inefficient.

  5. They can let you load-balance among multiple backend instances. For small selfhosters and homelabbers this isn’t usually a big concern, but for redundancy or scalability it can be helpful to run multiple backend instances of a (relatively slow) app behind a single (relatively fast) reverse proxy, letting it direct clients to the least-busy backend, caching assets as mentioned above, etc. This is really common for production systems where you might have say 10 worker VMs/containers behind a proxy all handling the load. Because, as with 4, this is what they’re designed primarily for, they tend to be a lot better at it. For instance a single HAProxy instance can handle upwards of 10Gbps of web traffic on a relatively old quad-core CPU and barely break a sweat.

For all these reasons, reverse proxies are at this point basically a best-practice that everyone should follow, even if you never expose the service to the Internet. The setup is generally trivial in comparison to most actual backend apps, and the benefits, even if slight, outweigh the added complexity.

I guess a good question would, do you plan on having any services where you want others that don’t have excess to your VPN to use? Or is this all just used by you and nobody else?

I use a reverse proxy locally.

I resolve my services with a dns server so i can access them via a domain that isn’t exposed to the internet aka split dns.

For remote access, i use my own personal vpn server to access my domains, originally wg-easy but switched to Firezone.

I don’t forward my reverse proxy port and only the few services that i need forwarded, like plex and my vpn are open.

I can access my domains with my vpn client since i can set the dns server in the config.

I closed all my services up so they can’t be accessed via ip and port.

The reason for that is because i have additional protections like forwardAuth middleware, that offer auth on top of the services via Authelia and lldap as its backend and ipwhitelist middlware that keeps my services accessible local only if i ever forwarded the port accidently or something.

I prefer proper ssl and certs; a domain is overall easier :sweat_smile: imo.

Checkout my links and docs, i originally self hosted these sites but moved them to cf pages instead.

I use haproxy for things like super fine shaping of what requests go where.

For instance if you hit my domain you go to my web server, if you hit my domain with a specific path you go to home assistant callback URL on a different lxc.

You can also setup the reverse proxy with let’s encrypt for everything behind it instead of setting each thing up individually.

Here is the problem…it’s easier!!

Think about your first application. It’s easy…set it up and it works. Your second is just as easy on well known ports so that gives you say https and say DNS. So far so good. But say you have two https applications. Now there is a problem. With a reverse proxy you can use the “domain/application” syntax or alternatively create a CNAME on the DNS (if you can access a domain name) which is application.domain which effectively works the same way. Or manually type domain:port which bypasses the reverse proxy. You can of course buy more IPs and if we are all on IPv6 that’s the ideal situation. But we’re not and dedicated IPv4s are expensive. So reverse proxy means one IP or one tunnel for everythjng.

The biggest thing for me personally, and this could be niche, is that some of my devices don’t support running VPNs.

So for example I run a Calibre ebook server that I’d like to be able to access from my Kindle even when I’m not at home. Kindles do not support installing VPNs. So a reverse proxy was my only real option.

Apple TV until recently didn’t support VPNs either. So if I wanted to access JellyFin from my mom’s house (she has an ATV) then I had to use an RP.

My office’s network also blocks VPNs so if I want to listen to Navidrome at work, I had to create a RP for it.

If you are going to stay not exposed, for me, the advantage of using RPs is not having to add port numbers or ip addresses to get to my services.

E.g. mystuff.example.com vs mystuff.example.com:3037

Don’t expose your services to the internet unless you absolutely have to

And when you do, your public facing stuff should be in a DMZ network

Use a reverse proxy anyway because internal SSL is really nice (no more cert warnings and actually secure connections)

My model is

Remote user → WireGuard VPN server running on home server in DMZ VLAN → Pin hole firewall rules to services and 80 and 443 to reverse proxy → Reverse proxy forwards securely to service

I tested Traefik (which is good) but I settled for NGINX. However I deployed another location a second docker environment and I exclusively went with Cloudflare tunnel because it’s so mind boggling easy.

If you are only accessing these services from your own devices, using Tailscale or any other VPN, then there isn’t much security need for a reverse proxy.

If you’re looking to expose the services to the Internet, to access them from other devices without a VPN client installed, a reverse proxy can be an important part of your setup. It lets you route traffic for a given domain or subdomain, being requested from one of those external devices, to anywhere on your LAN – either with only opening ports for the reverse proxy itself or without any ports via something like a Cloudflare tunnel. That has the benefit both of letting you expose multiple services on your network without a bunch of open and forwarded ports at the router, and of making it harder for port scanners to notice services you’re running when scanning your IP (all they’ll find is the ports for the RP itself). It can usually handle requesting/renewing and applying SSL certificates for you more easily than managing them independently with each service you may want to run.