Overview and Goal
I want to set up a reverse proxy to serve my LAN for 3 main reasons:
- Get proper TLS/SSL certificates so I can go to my selfhosted services without any warning from my browser
- Use a proper domain so I feel like a real sysadmin and I can remember those better than IP addresses (yes, I know I can do local hostname and domain, see point 1)
- I need proper certificates for running open source MDMs @ home for a longer term than the 2 hour ngrok tunnels that are used in the nano quickstart.
Environment
Couple of things to note about my environment.
I use Ubiquiti Unifi gear so DNS and DCHP are handled by my Unifi Gateway Ultra.
Nothing is getting exposed to the external web.

My domain is with Cloudflare and we use Cloudflare’s api token to get certificates from Let’s Encrypt.
Reverse proxy is Nginx using the Nginx Proxy Manager project.
I set my reverse proxy up on an Intel NUC I have running 24/7 cause it is also a Tailscale exit node for so I can access my services remotely but a VM on something should work just the same.
Simplified Process of How It Will All Work

How I did it. YMMV.
- Install docker-compose on your proxy server
I have SSH setup (if you don’t, do that first). So connect and run the installation commands on Docker’s website: https://docs.docker.com/desktop/setup/install/linux/. Yes, I know compose is for running multiple containers and technically you can just run Nginx Proxy Manager (referred to as NPM from now on) with docker, but you can run the database container as well (I don’t bother). Also compose is cooler and I like it more.
Create a directory for the compose file like
reverse-proxyornpm.mkdir reverse-proxyCreate your
docker-compose.ymland paste in:
version: "3.9"
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
restart: unless-stopped
volumes:
npm_data:
npm_letsencrypt:
Start ’er up!
docker compose up -d
Check out more info about the NPM project here: https://nginxproxymanager.com/guide/
- Go to the web UI, at http://proxy.yourlocal.domain:81 or by ip (configure static IPs, hostnames, and DNS records!)
In my case it was http://nuc.local.lan:81/login

Default creds are admin@example.com and changeme so change those when you are in.
You want to go to ‘SSL Certificates’ > ‘Add SSL Certificate’ > ‘Let’s Encrypt’.
a. In ‘Domain Names’, put
*.yourdomain.comso you can just use the same certificate for all your services. This is called a wildcard certificate.b. Put an email in
Check the ‘Use DNS Challenge’ (read more about DNS challenges here: https://letsencrypt.org/docs/challenge-types/).
a. Choose your DNS provider (probably your domain registar as well). Mine is Cloudflare so I chose that and all I have to do is log into Cloudflare and generate an API token.
In Cloudflare’s dash search for ‘API token’, click the first result. Make a new custom API token. Name it ‘NPM API token’. Permissions: Zone, DNS, Edit. Zone Resources: Include, Specified zone, yourdomain.com. Save that. You should get a pop up that shows the API token and a
curlcommand to test it. Copy all of that.Agree to the TOS

Now you have an SSL Certificate to use!
The flow now for every service you want to setup is
- Create a local DNS record in your router or unifi dash that has the
service.yourdomain.com->proxy.local.domainor the NPM server’s IP
(Your choice on A records or CNAME records. I like to have 1 A record for the host.local.domain -> server static IP, then everything else is pointed to that with a CNAME record incase I ever need to change the server’s IP, I only change it in one location.)
- In NPM > ‘Hosts’ > ‘Proxy Hosts’, create a host with the domain name as
service.yourdomain.com->service.local.domain+ port or IP + port and apply the SSL certificate.

Some things to note:
- some services might require websockets so if
service.yourdomain.comdoesn’t work the first time mess with the NPM Proxy Host settings. - when testing, clear your DNS cache on your machine often so your machine and browser don’t make you think nothing is working after making changes.
Summary
Now enjoy some encrypted comms!
Hope this was a good enough guide to get you started on setting this up in your homelab.