What a domain and a reverse proxy are
Every app on your server lives at an address like 192.168.1.20:8096: the server’s number, then the app’s port. It works, but nobody remembers it, and the browser marks the page “Not secure” because the connection isn’t encrypted.
A domain is a name you rent by the year, such as yourname.com. Once it’s yours, you can make as many names under it as you like, such as jellyfin.yourname.com and photos.yourname.com. A reverse proxy is one program that receives every request, looks at the name that was typed, and passes it to the right app. Because everything goes through it, it can also handle HTTPS, the encryption behind the padlock, for every app at once. For that it uses certificates: small files that prove to the browser the name really is yours. They’re free.
Private or public: decide this first
A domain and a reverse proxy don’t make anything public by themselves. What makes an app public is forwarding ports 80 and 443 on your router to the proxy.
- Private, the right choice for nearly everything. Your names point to the server’s home address. They work at home, and away from home over Tailscale. Nothing is open on your router, and you still get the padlock, using the DNS challenge explained below.
- Public, only when strangers need it, such as a website. Read securing your homelab first, and look at Cloudflare Tunnel on the remote access page before you open any ports.
How the pieces fit together
| Piece | What it does | Where you set it up |
|---|---|---|
| Domain | The name you own | A registrar, such as those in the list below |
| DNS record | Points names under it at your server | Your DNS provider’s web page, usually the registrar’s |
| Reverse proxy | Sends each name to the right app | Nginx Proxy Manager, or Caddy, on your server |
| Certificate | Gives each name the padlock | Fetched and renewed by the proxy |
Certificates come free from Let’s Encrypt, which first checks that you control the name. The usual check visits your server from the internet, so it needs port 80 open. The DNS challenge works differently: your proxy adds a temporary record to your domain’s DNS using a key from your DNS provider, called an API token. Nothing at home has to be reachable from outside.
The DNS challenge can also issue a wildcard certificate, covering every name under one part of your domain, such as *.home.yourname.com. That helps privacy too: every certificate is published in public logs, so one per app would list every app’s name. A wildcard shows only the wildcard.
Let’s Encrypt certificates last 90 days today, and that falls to 45 days by 2028, so renewal has to be automatic. Nginx Proxy Manager and Caddy both renew by themselves.
What it needs
- A domain, paid by the year. Check the renewal price, not only the first-year offer.
- A DNS provider with an API token, for the DNS challenge. Cloudflare and Porkbun both work with Nginx Proxy Manager, along with dozens of others.
- A server running Docker, or ZimaOS or CasaOS, which run Docker for you. Nginx Proxy Manager only runs in Docker. See Docker and containers.
- An hour or two for the first app. Each app after that takes a few minutes.
How Nginx Proxy Manager fits in
Underneath it runs nginx, a widely used web server, and writes nginx’s settings from what you fill in:
- Proxy hosts. One form for each app: the name you’ll type, the address and port the app lives on, and a few switches.
- Free certificates from Let’s Encrypt, requested from the same form, which it renews by itself.
- The DNS challenge, built in. Choose your DNS provider from a list and paste its API token to get certificates, wildcards included, for apps that never leave your home network.
- Force SSL, a switch that sends plain HTTP visitors to HTTPS.
- WebSockets support, a switch for the live connections that apps such as Home Assistant rely on.
- Access lists, which put a username and password in front of an app that has no login of its own.
- Users and an audit log, so someone else can have a login with limited permissions, and you can see what changed.
The easy way to set it up
Everything here happens in web pages, with no terminal. On ZimaOS or CasaOS:
- Buy a domain and leave its DNS with the registrar.
- Add one DNS record in the registrar’s DNS page: an A record (the kind that points a name at an address) for *.home, pointing to your server’s home address, such as 192.168.1.20. On Cloudflare, set it to “DNS only”, because Cloudflare’s proxy can’t reach a home address.
- Create an API token in the same account, so the proxy can prove you own the domain. On Porkbun, also switch on API access for that domain.
- Move the dashboard off port 80. Nginx Proxy Manager needs ports 80 and 443, and uses 81 for its own page. The ZimaOS and CasaOS dashboard normally uses port 80, so change the dashboard’s port in its settings to one that isn’t 80, 81 or 443, and write down its new address before you leave the page.
- Install Nginx Proxy Manager from the App Store, reading its install note as you go.
- Open it on port 81, for example http://192.168.1.20:81. The install note lists the starting login. Replace it with your own email and a strong password straight away.
- Add a certificate for *.home.yourname.com, choosing the DNS challenge, your provider, and pasting the token.
- Add a proxy host for each app: the name (jellyfin.home.yourname.com), the server address and port (192.168.1.20 and 8096), the certificate from step 7, and Force SSL switched on.
On any other machine with Docker, the official setup page gives a short Docker Compose file and the one command that starts it. Everything from step 6 on is the same.
If you’re comfortable with a terminal and would rather keep your settings in a text file, Caddy from the options below does the same job. Each app is about three lines in its Caddyfile:
jellyfin.home.yourname.com {
reverse_proxy 192.168.1.20:8096
}
Caddy has no app-store button, so you run its official Docker image or the program for Windows, Mac or Linux, and restart it after each change. For the DNS challenge, its download page can build a copy with your DNS provider’s plugin included.
Questions people ask
Do I need a domain at all?
No. Your apps work at their address and port, and Tailscale’s MagicDNS gives you names such as http://homeserver:8096 for free. A domain is for when you want proper names and the padlock, or a website.
Does this make my apps public?
Not unless you forward ports 80 and 443 on your router to the proxy. With the setup above, the names point to a home address, which leads nowhere from outside your house.
Will the names work away from home?
Over Tailscale, yes, if the server is set up as a subnet router, which lets your Tailscale devices reach your whole home network. Another way is to point the record at the server’s Tailscale address, the one beginning 100. The names then work on any device signed in to your Tailscale, at home or away, but not on devices without it.
The address and port work, but the name doesn’t. Why?
Some routers block DNS answers that point to home addresses, a safety feature called DNS rebinding protection. Add an exception for your domain in the router’s settings, or, if you run AdGuard Home, add a DNS rewrite for the name there. A brand-new record can also take a little while to appear.
Which domain ending should I choose?
Any you like, as long as it’s short and easy to type. Some endings cost far more to renew than to register, so compare renewal prices. Browsers only open .dev and .app names over HTTPS, which is fine here, since you’ll have it anyway.