In this tutorial, I’m going to show you how to install Nginx Proxy Manager in Docker on a Ubuntu 20.04 VM. This guide was created in January of 2021, so all of the info here should be up to date.

The main goal of this post is install Nginx Proxy Manager so my Plex users can access my Overseerr instance remotely.


What is Nginx Proxy Manager?

Nginx Proxy Manager is a Docker application that lets you quickly and easily expose your selfhosted services to the outside world. NPM includes a free Letsencrypt SSL certificate as well, which is an absolute must if you are opening up anything to the entire internet.


When to use Nginx Proxy Manager?

You should setup Nginx Proxy Manager if there are any sites and services located within your home network that you’d like to be able to access remotely without the use of a VPN.

Keep in mind, while you can add all your services to NPM, you probably don’t want to for security purposes. Sonarr and Radarr, for example, don’t require a username and password to log into. You wouldn’t want to add these to NPM, as anyone in the world can start downloading media to your server, changing settings, or viewing your log files.

However, if you’d like to access Bitwarden_rs, Overseerr, Bookstack, Homer dashboard, or a WordPress site you have hosted at home from anywhere – then it might make sense to add those to Nginx Proxy Manager.


Prerequisites:

This guide assumes you already have Docker and Docker-Compose installed. If you don’t have those setup yet, you can follow these step by step guides I’ve created. I have Docker and Docker-Compose running a Ubuntu 20.04 VM.

Setup Time: 30 minutes


Step 1: Register a Domain Name

The first thing you’ll need to do is register a domain name. If you already have a domain name, you can skip this step.

The domain I’m using dannyhosted.com and was purchased from Namecheap for less than $8/year.


Step 2: Set Up DNS

The next thing we need to do is set up your DNS for your domain. You can either use Namecheap’s built-in DNS or Cloudflare. For this guide, I’ll be using using Cloudflare.

Head over to Cloudflare.com and register or sign in. Click Add A Site.

Add the site you just purchased or the domain you already own. You can stick with the Free Cloudflare plan for this.

After a few moments, it’ll pull in the existing DNS information from Namecheap. Click Continue.

The next screen will show you what nameservers you’ll enter into Namecheap.

Navigate to the DNS settings in your registrar. For Namecheap, go to your Account Dashboard. Click the dropdown arrow > Manage.

Under Nameservers, change from Namecheap Basic DNS to Custom DNS. Then add the two nameservers given to you from Cloudflare. After pasting those in, click the green checkmark.

A message will pop up stating that it may take 48 hours for DNS to replicate across the internet. In my experience, it’s usually less than 5 minutes, but keep in mind that it can sometimes take a while.

Navigate back to the Cloudflare page and click Done, check nameservers.

Once Active in Cloudflare, you’ll receive an email letting you know.


Step 3: Create Nginx Proxy Manager directory

Open Putty to SSH into your docker server.

The first thing we need to do is make a directory for Nginx Proxy Manager. I keep all of my containers in /srv/config/, so I’ll creating a nginxproxymanager directory there.

First, navigate to the directory.

cd /srv/config/

Then make a new folder.

mkdir nginxproxymanager

Then navigate to the newly created directory.

cd /nginxproxymanager

Step 4: Create Docker-Compose.yml file

Enter this command to create a new docker-compose file inside the directory.

touch docker-compose.yml

To verify the file was created successfully, type ls.

Next, we need to edit the docker-compose.yml file. To do this, we are using the nano file editor.

nano docker-compose.yml

Paste in the file below. Since we are opening Nginx Proxy Manager to the world, you will definitely want to change the default user and password as well as the paths. If you already have something running on port 81, you should change that as well.

version: '3'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm" # Change mysql user
      DB_MYSQL_PASSWORD: "npm" # Change mysql password
      DB_MYSQL_NAME: "npm"
    volumes:
      - /srv/config/nginxproxymanager:/data
      - /srv/config/nginxproxymanager/letsencrypt:/etc/letsencrypt
  db:
    image: 'jc21/mariadb-aria:10.4'
    environment:
      MYSQL_ROOT_PASSWORD: 'npm' # Change mysql user
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm' # Change mysql user
      MYSQL_PASSWORD: 'npm' # Change mysql user
    volumes:
      - /srv/config/nginxproxymanager/db:/var/lib/mysql

Then, click CTRL+X > Y for yes > and Enter to save.

Then start the containers with this command.

sudo docker-compose up -d

You should see two Done messages once complete.


Step 5: Add DNS A Record to Cloudflare

Next, go back to Cloudflare.com > DNS. Click + Add record.

Add a new A record, enter your subdomain, and your home’s external IP address. If you don’t know what yours is, just type “what’s my IP” into Google and paste it here.

Tip: You can also just add a * instead of a subdomain if you want any unspecified domains to go directly to your server IP. Then you can simply add subdomains in Nginx Proxy Manager.


Step 6: Port Forward ports 80 and 443 in your router

I can’t show you exactly how to do this step as each router has a different interface and menu items.

Basically, you need to log into your router and port forward two ports: 80 and 443. I’m using a TP Link Deco m5 so I have to access this from the mobile app. The port forwarding option is usually located under the Advanced settings of your router.

If you can’t find the port forwarding option, you can Google search you router model + port forwarding to find where it’s located.

Port #1: 443

Add 443 to both the internal and external port. Add the internal IP of your docker server.

Port #2: 80

Add 80 to both the internal and external port fields. Add the internal IP of your docker server.


Step 7: Open Nginx Proxy Manager WebUI

In the docker-compose file above, I used port 81. Enter your docker server IP and use port 81 to open the webpage. Mine would be 192.168.68.141:81.

The default login credentials are admin@example.com and the password is changeme. After signing in you’ll be prompted to create a user account.

Click the hosts tab, then click Proxy Hosts.

Add a Proxy Host. For the domain name, choose the subdomain you want to use. For this example, I am going to be proxying Overseerr, which is an application that lets my Plex users request new TV shows and movies to automatically get downloaded to my Plex server. The subdomain I’m going to use requests.

  • Domain Names: requests.dannyhosted.com. Make sure to click Add.
  • Scheme: http
  • Forward Hostname/IP: The internal IP of your Docker server (192.168.68.141)
  • Forward Port: The internal port number for your your service. Overseerr is using 5055.
  • Turn on cache assets and block common exploits

Then switch to the SSL tab.

  • Request a new SSL Certificate
  • Force SSL: enabled
  • HTTP/2 Support: Enabled
  • Agree to the ToS

In Nginx Proxy Manager, your proxy host should now up Online:


Step 8: Test it out!

The final step is to simply go to https://requests.dannyhosted.com in a web browser.

If everything worked correctly, the webpage should load both on your internal network as well as a remote network. The easiest way to check if it works externally is by turning off the wifi on your phone and using your mobile data.

Note: During testing, you may have cached webpages causing it to look like it’s not working correctly. I recommend using different browsers or an incognito browser to test.

Now that you have it working with 1 application, the same steps apply for each selfhosted application you want to add. Just create a new DNS A record in Cloudflare and then add the proxy host in Nginx Proxy Manager.

Wrapping Up

Hopefully this guide helps you get Nginx Proxy Manager setup quickly and easily! I scoured the internet looking for a step-by-step guide or video tutorial, but ultimately ended up documenting everything myself as most of what I found was slightly out of date or was geared towards OMV.

Let me know in the comments section if this guide worked for you or if there’s anything I need to edit or change.


My Homelab Equipment

Here is some of the gear I use in my Homelab. I highly recommend each of them.

The full list of server components I use can be found on my Equipment List page.

Similar Posts

20 Comments

  1. Thank you for this. I tried several articles on your blog and they are all great..please step away from HA and go the Openhab route 😉 just kidding. Thanks for the hard work of writing stuff down in your blog

    1. You’re welcome, I’m glad my guides could help you out!

  2. I’m having some trouble with this one – I followed your exact guide, using the same websites. I think I’ve configured nginx properly – I have the proxy host with the certificate online and Cloudflare says I’m good. When I first went to my domain though, I got a ‘too many redirects’. I followed the advice here: https://community.cloudflare.com/t/community-tip-fixing-err-too-many-redirects/42335 and enabled Full SSL and always https. This has changed my error to a cloudflare 502 error. Any ideas where I could have an issue?

    1. In Cloudflare under the SSL settings, I have mine set to Flexible. Have you tried setting it to that already?

  3. Hey Danny, I’ve followed your guide and gotten to the point where I have an online proxy server and an Nginx “Congratulations! You’ve successfully started the Nginx Proxy Manager. If you’re seeing this site then you’re trying to access a host that isn’t set up yet.”.

    Overseerr’s website has some specifics about adding reverse proxy configs to nginx, but it doesn’t seem to line up with nginx proxy manager. https://docs.overseerr.dev/extending-overseerr/reverse-proxy-examples

    Is that something I need to do for this setup?

  4. So turns out that mydomain.com doesn’t work, it had to be http://www.mydomain.com. Doing that and switching it back to flexible got me to the point where I see “Congratulations! You’ve successfully started the Nginx Proxy Manager. If you’re seeing this site then you’re trying to access a host that isn’t set up yet. Log in to the Admin panel to get started.”. I assume that means my issue is now just between Overseerr and NPM. Is there a config file or something else that I need?

    1. Hey Joe,
      You shouldn’t need to upload any kind of config files. It you were using NGINX, non NPM, then you may need a config file.
      In Cloudflare, for the A record, did you setup a subdomain like overseerr.website.com or did you use a * ?

      If you used a *, then you should only need to add a subdomain to Nginx Proxy Manager. If you added a subdomain as an A record to Cloudflare, then add the same subdomain to NPM.

  5. Hey,
    thanks for the guide was really easy and useful to follow. however I ran into a bit of a problem with cloudflare where it gives me either a timed out error (522) or a unreachable error (523) and I don’t seem to be able to fix it. could you please let me know if there is anyway to fix this, thank you!

    1. Do you have ports 80 and 443 open on your firewall/router?

      What happens if you type your external IP into a browser from an external network (just turn off wifi on your phone and enter your external IP)? It should show the NPM “Congratulations!” Page. If it doesn’t, your firewall ports aren’t setup correctly.

      Also, in my Cloudflare settings > SSL, I have it set to Flexible. For Cloudflare DNS, I have the name set to *, ipv4 set to my external IP, and set to DNS only.

      Edit: We messaged on Reddit, and you were able to get it working after double checking your firewall ports and disabling the management port 80 on your Asus router. Just commenting here so if others have the same issue, hopefully this helps them too.

  6. Stephen Fulmer says:

    I am getting a bad gateway after getting to the nginx login page. I put the user name and password and i get Bad Gateway on the login page.

  7. I have been lazily looking for a guide like this for years, thank you for taking the time to make this and being so detailed. Found lots of guides for setting up nginx/let’sencrypt but none that take you though setting up the domain side. You the man!

    1. You’re welcome man! That’s exactly why I wrote it – I was never able to find a literal step-by-step guide so I made one myself 🙂

  8. Internal Error FIXED for me. I do not make use of my Verizon router. Instead I use a set of Netgear Orbi’s. I was port forwarding on the Netgear router, but kept getting the Internal Error for NPM. Then in dawned on me that I need to do a double port forward since I am behind two routers. It goes External IP -> Verizon Router -> Netgear Router -> Computers. So, on the Verizon Router forward the 443 and 80 ports to the IP address of the Netgear Router. Then on the Netgear Router forward the ports to your server that’s running NPM. Obviously you may need to adjust this text to make sense for your configuration, but that fixed the issue for me. I’m still getting a too may requests error when I try to dial in, but I’ve at least go my Proxy Host in NPM working!

  9. Just used this guide and it worked!! Although I used google domains but it was still easy. Just an fyi, maybe the compose file didn’t work for me because I did something wrong but I had to use

    db:
    image: ‘jc21/mariadb-aria:latest” instead of 10.4

    then I was receiving the bad gateway when trying to log in. I followed your link.
    I had to
    -add restart:always
    -change the path of the volumes for my own directory.

  10. Dominique says:

    Hello Danny,
    I scoured the depths of the web and finally came across your tutorial. I live in FRANCE and I have not found such detailed information. A BIG thank you, because from the first cost everything worked. Really, very good job.

    1. That’s awesome! I’m really happy I could help out. That’s exactly why I wrote this article; because I couldn’t find anything that walked me through the process either.

  11. Hehehaha123 says:

    Hey Danny,

    works GREAT has been running for like 6 months now reliability.

    1. great! Mine is still working perfectly as well, glad my guide helped you out!

  12. Hi Danny,
    Thanks for the specific guide. I’m having issues deploying my docker compose. Which fields specifically do I need to change other than paths? I’m getting an error saying “for docker_app_1 Cannot start service app: driver failed programming external connectivity on enedpoint docker_app_1. Any help would be appreciated!

Leave a Reply

Your email address will not be published. Required fields are marked *