If you’re searching for a small and easy to set up a reverse proxy with a beautiful UI, you’re at the right place. In this tutorial, I will show you how to install the NGINX proxy manager in a docker container on Linux.
For this tutorial, you need a Linux server that has docker and docker-compose installed. Docker-Compose is a simple and easy container management system, that is based on static configuration files. But you could also deploy NGINX proxy manager in other container management systems if you want. If you want to know how to install docker on Linux, just have a look at the official docker documentation and docker-compose documentation.
What is NGINX proxy manager
NGINX proxy manager is a reverse proxy management system, that is based on NGINX with a nice and clean web UI. You can also obtain trusted SSL certificates, manage several proxies with individual configs, customizations, and intrusion protection. It is open-source and maintained GitHub. It’s perfect for small environments like home labs or small server environments. You can easily expose any web service or application with it. It includes a free SSL certificate management by letsencrypt that can also be used to obtain wildcard certs. To deploy the NGINX proxy manager you need a small MySQL database container and the NGINX container. Let’s have a look at how to deploy this easily with docker-compose.
Deploy NGINX proxy manager in docker how-to
Now we need to create our docker-compose file. I will create a new project folder in the /opt directory called “nginxproxymanager”. Then I create a docker-compose.yaml file with the following template.
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" DB_MYSQL_PASSWORD: "npm" DB_MYSQL_NAME: "npm" volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt db: image: 'jc21/mariadb-aria:10.4' environment: MYSQL_ROOT_PASSWORD: 'npm' MYSQL_DATABASE: 'npm' MYSQL_USER: 'npm' MYSQL_PASSWORD: 'npm' volumes: - ./data/mysql:/var/lib/mysql
Start the NGINX proxy manager stack with the following command.
docker-compose up -d
Login to the web UI of NGINX proxy manager
Now we can log in to the web UI. Simply use your browser to connect to your server by using the IP address or an FQDN and connect on port “81”. Log in with the username “email@example.com” and the password “changeme”. Next, you should change your username and password, and that’s it!
You can create proxy hosts, obtain trusted SSL certificates, manage access control lists and much more. First let’s add a new domain on our DNS server, that we’re able to obtain a new SSL certificate.
Create a DNS A record for your domain that points to your server
I create a new A record on my server that is called “research.the-digital-life.com” that points to the public IP of my cloud server. I’m using DigitalOcean as my DNS provider because their DNS management is completely free and very easy. If you want to try out DigitalOcean use this link to get 100$ for 60-days for free!
Obtain trusted SSL certificates for your services
Next, we need to obtain our SSL certs in the NGINX proxy manager UI. Go to “SSL certificates” and enter your details. Note, if you want to use a wildcard cert like “*.the-digital-life.com”, you will need to enable the “Use a DNS Challenge” method. Select your DNS provider and follow the instructions, based on your provider’s documentation. But in this example, I won’t use a DNS challenge, because I want to obtain an SSL cert for the subdomain “research.the-digital-life.com”.
Once you click on “Save”, the NGINX proxy manager tries to obtain your trusted SSL cert. If everything is successful, you should see your cert in the list.
Expose a simple unsecured web application
To expose a simple web application that is running on our server, we will create a new “Proxy Host”. In this example, I will expose a docker container that is running “nextcloud”.
Note, it’s very important to understand how networking works in docker. Because docker networks are isolated from each other, you need to make sure that the app you want to expose is connected to the NGINX proxy manager network “nginxproxymanager_default”. I’m doing this by running the following command. Alternatively, you could also add more services in the docker-compose.yaml file.
docker run --network nginxproxymanager_default --name=nextcloud nextcloud
Create a new proxy host
Now we can create a new “Proxy Host”. Make sure you select the “Scheme” “HTTP” if you want to expose any unsecured application that doesn’t use HTTPS. This is the protocol of the destination. Fill in the “domain names”, which should match all domains in your SSL cert. When you enter the Forward Hostname/IP you can simply enter the name of the docker “service” you want to expose. If your app is not running in a docker container, you could also simply add the IP address.
By enabling “Block Common Exploits” we also add some protection features to our app. Next select the SSL cert we’ve just created and enable force SSL, HTTP/2, and HSTS if you want to.
Now, we will test if everything works fine. Simply connect to the domain and you should see that your app is accessible now. But I know there can be some errors, let’s also talk about what could go wrong.
Common error: Bad Gateway 502
This error happens when the reverse proxy can’t connect to the destination host, or doesn’t get a response. Most likely, in docker setups, the containers are not on the same network, or the destination is not correct. Make sure you’re accessing the correct IP/hostname and the NGINX proxy manager can reach this target.
Also note, that the NGINX proxy manager is running in a docker container, so using the IP address 127.0.0.1 will NOT refer to the host OS IP address, but the container’s internal address.
Another common issue is that the communication between the NGINX proxy manager and the target can’t be established because the protocol version is incorrect. Make sure you’re using the correct Scheme “HTTP” for unsecured destination sites, and “HTTPS” for secured destination sites that use a self-signed cert!
I hope this was helpful, but if you have other problems and you’re searching for help, just have a look at our Discord community.