The previous article taught you how to install Nginx Proxy Manager using Docker Compose in Ubuntu 22.04.
Cloudflare provides a DNS proxy service which will hide your server IP address, adding an additional security layer to your website.
This article will teach you how to combine Nginx Proxy Manager with Cloudflare in order to access your internal web services via the Internet.
You have set up Nginx Proxy Manager on your system. Look at my previous article if you haven’t set it up.
You have created a Cloudflare account.
You have changed your DNS from your registrar to Cloudflare.
You have a domain parked in the Active Zone on Cloudflare. You may visit Freenom to get a free domain if you don’t have a paid one.
Step 1: Move to Original Server under your domain’s SSL/TLS section.
Click the Create Certificate button.
Step 2: Change the expiration time of your certificate. I recommend you to choose a duration longer than 1 year; otherwise, you may need to replace your SSL certificate on Nginx Proxy Manager frequently.
Step 3: Copy the text under Origin Certificate and create a file called cert.pem on your computer.
-----BEGIN CERTIFICATE----- ... ... -----END CERTIFICATE-----
Also, create a file called key.pem on your computer. Copy the text under Private Key and paste it to key.pem. However, a modification needs to be made in order to make Nginx Proxy Manager recognise the Private Key correctly. Change the
-----BEGIN PRIVATE KEY----- ... ... -----END PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY----- ... ... -----END RSA PRIVATE KEY-----
on your key.pem.
Step 4: Go back to Nginx Proxy Manager and go to the SSL Certificates section. Click the Add SSL Certificate button. Select “Custom”.
Enter the name as your domain. Upload key.pem as Certificate Key and cert.pem as the certificate.
Step 5: Go to the Access Lists section on Nginx Proxy Manager. Click the Add Access List button.
Enter Cloudflare as Name.
Click the Add button around 30 times.
Add Cloudflare IPs under the Access Section. You may visit this page for the IP Ranges used by Cloudflare.
After entering any IP on the Access section, DO NOT CLICK the Add button again; otherwise, everything you input will be erased.
Press the Save button when everything is done.
IPv4 18.104.22.168/22 22.214.171.124/22 126.96.36.199/22 188.8.131.52/13 184.108.40.206/14 220.127.116.11/18 18.104.22.168/22 22.214.171.124/18 126.96.36.199/15 188.8.131.52/13 184.108.40.206/20 220.127.116.11/20 18.104.22.168/20 22.214.171.124/22 126.96.36.199/17 IPv6 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32
Step 6: Move to the Proxy Hosts section on the Nginx Proxy Manager. Click the Add Proxy Host button.
Step 7: Enter your domain name and press Tab to save.
Select HTTP or HTTPS as your Scheme.
Enter your Forward Hostname / IP and Forward Port.
Change the Access List to Cloudflare.
Do not click the block common exploits button at this moment. You must ensure you can access your website before turning it on.
For some web services, such as code-server, you may need to turn on Websockets Support. By default, it is turned off.
Step 8: Add your domain’s SSL certificate to the SSL section. It is optional to enable HTTP/2 Support.
Step 9: Go back to your Cloudflare dashboard.
Add an A record to your domain if you are using a static IP.
Instead, if you are using a dynamic IP address and you want to use a DDNS. Create a CName record.
Remember to turn on the Proxied option. Click the save button to take effect. It may take at most 1 day to update your DNS record worldwide.
Step 10: Ensure you have forwarded port 80/443 to Nginx Proxy Manager on your router/ switch. Since different brands will have different configurations, you may need to Google it and set it up yourself.
If you are using Oracle Cloud, remember to configure your firewall to allow incoming traffic by
sudo iptables -I INPUT -j ACCEPT sudo su iptables-save > /etc/iptables/rules.v4 exit
If you can access your domain after a few hours, congratulations, you successfully combined Nginx Proxy Manager with Cloudflare!
Check out this article on self-hosting a WordPress and reverse proxy it with Nginx Proxy Manager.
Have a look of this article for how to hide your HTTP/HTTPS on the public Internet using Cloudflare Tunnel with Nginx Proxy Manager.
If you want more advanced techniques, try to configure Nginx Proxy Manager for load balancing or configure Nginx Proxy Manager to create a failover WordPress server on cPanel.
6 thoughts on “How to combine Nginx Proxy Manager with Cloudflare to access your websites/ web services securely”
Excellent document! Thank you very much for putting this together for us, it worked perfectly on the first try for me 🙂
One minor comment is that after you create the SSL cert using the key downloaded from Cloudflare, you need to specify that certificate as the SSL certificate in the proxy host that is created in steps 7 & 8, otherwise Cloudflare will give you an Invalid Certificate error when you try to hit your domain.
Thanks again for this information, it was excellent and as you say, very quick to get up and running.
Thanks for your comment. 🙂
It seems that I missed 1 image in this post. I will update it later.
Btw, I found an issue with Nginx Proxy Manager after version 2.9.19. You may have issues when you try to handshake with a website involved in TLSv1.3 (You can confirm it by curl -k “https://your_internal_service_ip:443” -H ‘Host: your_service_public_domain_name’ –http1.1). I have not found a workaround yet. You may need to downgrade to NPM v2.9.19 if you have similar issues.
Did you ever figure out a workaround to the handshake problem with tls1.3?
Thanks for your comment.
Are you trying to combine Headscale with Cloudflared (Cloudflare Tunnel) and Nginx Proxy Manager? If that is the case, I think the issue is on the Cloudflare side. They claim they have enabled WebSockets for Cloudflare Tunnel, but even though I tried the same configuration with Apache / Nginx, Headscale still could not work. I could not register any devices through Headscale. Eventually, I gave Cloudflare Tunnel up. I exposed my 443 port and proxied the WebSockets through Cloudflare (combing with NPM). Everything works properly now.
However, be careful to not violate the ToS of Cloudflare. If you have high traffic proxied by Cloudflare through WebSockets with non-HTML contents, they may temporarily suspend your domain until you change it back to non-Proxied.
2.8 Limitation on Serving Non-HTML Content
The Service is offered primarily as a platform to cache and serve web pages and websites. Unless explicitly included as a part of a Paid Service purchased by you, you agree to use the Service solely for the purpose of serving web pages as viewed through a web browser or other functionally equivalent applications and rendering Hypertext Markup Language (HTML) or other functional equivalents. Use of the Service for serving video (unless purchased separately as a Paid Service) or a disproportionate percentage of pictures, audio files, or other non-HTML content, is prohibited.
If that is not the case, you may give v2.9.18 or v2.9.19 a try. It seems everything is fine on that version. Or you may have a look at this link:
https://github.com/NginxProxyManager/nginx-proxy-manager/issues/2822. It seems Jebabin solved that issue on v2.10.2.
Appreciate the reply. I’m actually not trying to use Cloudflare Tunnels in this case. I followed the guide you presented, plus the comment about setting the CF Origin Cert as the Cert for the Proxy Host. When I activate the Proxy Host with all the settings I get a 403 Forbidden (Openresty) Error. If I switch back to the default Public Access List it works fine. I’m struggling to figure out what is causing the error. If you happen to have any ideas it would be greatly appreciated. Thanks again for the reply!
It may be related to your internal firewall settings.
Try to add your public IP/32 to the whitelist first.
Then give your internal IP /24 (let’s say 192.168.1.0/24) a try.
If you use Docker to host your web service, add 172.17. 0.0/16 to the whitelist.
Let me know if the above IP ranges solve your issue. 🙂
By the way, I have created other tutorials related to Nginx Proxy Manager starting from scratch. I could not find any issue with the Cloudflare filter.
The only time I encountered a 403 issue was when I used the wrong scheme (using HTTP on an HTTPS site).