Access services in your Homelab from the “outside Internet” may be hardly needed but it is fun and therefore, why not do it? I will show you, what you need to set up to get your (multiple) services accessible from the internet using your DYNDNS service of choice and Nginx Proxy Manager.
As always, there are some prerequisites, that need to be fulfilled before getting started with a Reverse Proxy.
- You need a DYNDNS service configured. Ideally one, that will allow you to add multiple DNS prefixes to your DNS name or, even better, a wildcard DNS. (e.G.
*.someurl.com) If you use Hetzner as your DNS Provider, you may want to have a look here for an Ansible Playbook to automate the whole DYNDNS configuration.
- You need docker and docker-compose setup on a Server or VM.
- I assume, that you have the services you want to get behind the Proxy Manager are already up and running.
A few quick words for the reason and benefits of a Reverse Proxy. A Reverse Proxy will handle traffic that comes from the “outside” with a given DNS Name in the header and forwards this traffic to the actual service on a given IP or DNS Name on a configureable port. So we can use one entry gate to our network using one set of ports. One additional benefit is, that Nginx Proxy Manager in special, will handle SSL encryption and certificates for us. He will “terminate” SSL connections using a signed certificate from Let’s Encrypt and will “speak” to the service either encrypted or unencrypted in the local network using maybe a self signed certificate from the service itself. So no more quirky messages regarding untrusted certificates and unsafe connections.
First step is to setup the Nginx Proxy Manager as our Reverse Proxy on our Docker host. You can find a detailed installation instruction for Nginx Proxy Manager here. We keep the setup minimal, you can find the docker-compose.yaml also in my Github repository here. In this compose, I’m doing a bind mount of two directories of my docker host. Adapt these to your needs.
version: '3' services: app: image: 'jc21/nginx-proxy-manager:latest' container_name: nginx-proxy-manager restart: unless-stopped ports: - '80:80' - '81:81' - '443:443' volumes: - /docker/nginx-reverse/data:/data - /docker/nginx-reverse/certs:/etc/letsencrypt
You can see, that we map three ports to the container. Port
443 for the
https traffic. Port
81 is for accessing the WebUI of Nxing Proxy Manager. If one of the ports is already in use on your Docker host, feel free to change them as you need (you will have to consider this when doing the port forwarding later 🙂 ). Start the container setup by issueing
docker-compose up -d.
You may check the logs of the created container by doing
docker logs nginx-proxy-manager. But if you have created the directories and the ports you’ve selected are available, the container should come up without issues. You now can access the WebUI of Nginx Proxy Manager using your browser and the URL like
http://mydockerhost:81. The first time logon credentials for Nginx Proxy Manager are the following:
Email: email@example.com Password: changeme
You will then get asked to change the password and provide a new username for the admin user.
So, Proxy Manager is set up and running. Time to get out Internet Router ready to do a “Port forward” to our new Proxy Manager instance. This works a little bit different for every Router, but Google is your friend here. What you want to configure is, forwarding all
443) traffic that reaches your router, will get forwarded to your Docker host on the ports you’ve configured for your container before (see the
A quick side note here. In my case, I couldn’t do a direct port forward from my Internet router to my Docker host. The reason is, that my Homelab is located in a different subnet that is not managed by my router. I’ve a second router in between (Mikrotik). In this case, you may need to configure your Internet router, to forward all traffic on the named ports to your second router (using the gateway address). On the second router, you then also have to do a port forward for every request on the respective ports to your Docker host.
So it’s time to configure our webservices. Head back to the WebUI of the Proxy Manager and click on “Proxy Hosts”, then “Add Proxy Host”.
Under “Domain Names” enter you external DNS Name (the DYNDNS Name, which points to your external IP address). As “Forward Hostname / IP” you enter the local IP address or servername, where your Webservice is reachable. Also configure the according port as “Forward Port”. I recommend to enable “Block Common Exploits”. If you want, you can also add another layer of security, by configure an “Access List” (see below). Under the SSL register, you may also configure a signed Let’s Encrypt certificate. But we leave this for now. Hit “Save” and try to connect to your Webservice using the external (DYNDNS) URL. In this example
http://webservice1.mydomain.com. If your Webservice only “speaks”
https, you need to specify this under “Scheme” and also provide the according Port (
443 in default).
This should already work. So let’s try out to add a SSL certificate to our service. Open the “Proxy Host” again, head to the SSL register and select “Request a new SSL Certificate” from the drop down menu. I recommend here to select “Force SSL” and “HTTP/2 Support”. Provide your valid email address and check the “I agree…” checkbox. By clicking on “Save”, Proxy Manager will try to request a signed certificate using the HTTP challenge (if you haven’t selected DNS challenge though). If all works without an error, you now can access your Webservice using https://webservice1.mydomain.com and you should see now more certificate warning in your browser.
I mentioned the “Access List” above. Using this feature, you can add another authentication level as well as a list of IP addresses that are allowed to access your webservice. If you want all possible IP addresses as a source, you may select “Satisfy Any”. After creating the Access List, you can specify it in your “Proxy Host” and hit “Save” again.
Do you have any Idea how to secure all The requests agains XSS and SQL injections. I Would Need an IPS, or pfsense in Front of nginx?
NPM can’t help you with that AFAIK. You would need something, that either protects you from both scenarios behind or in front of NPM (I would go to behind)