NGINX Proxy Manager – How-To Installation and Configuration

If you’re searching for a small and easy-to-set-up 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 simple and easy to manage containers with 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'
    image: 'jc21/nginx-proxy-manager:latest'
      - '80:80'
      - '81:81'
      - '443:443'
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    image: 'jc21/mariadb-aria:latest'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
      - ./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 protected]” 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 “” 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 “*”, 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 “”.

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 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.

50 thoughts on “NGINX Proxy Manager – How-To Installation and Configuration”

  1. Hi Christian,
    DB initalisation in Docker failed:
    2020-12-08 8:08:30 0 [Note] InnoDB: Starting shutdown…

    2020-12-08 8:08:30 0 [ERROR] Plugin ‘InnoDB’ init function returned error.

    2020-12-08 8:08:30 0 [ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.

    2020-12-08 8:08:30 0 [Note] Plugin ‘FEEDBACK’ is disabled.

    2020-12-08 8:08:30 0 [ERROR] Could not open mysql.plugin table. Some plugins may be not loaded

    2020-12-08 8:08:30 0 [ERROR] Unknown/unsupported storage engine: InnoDB

    2020-12-08 8:08:30 0 [ERROR] Aborting

    ich benutze dein docker-compose.yml ohne Änderung
    Hast du eine Idee ?

  2. CentOS 7 on a Virual Server. httpd is down.
    I used this docker-compose.yml

    [version: ‘3’
    image: ‘jc21/nginx-proxy-manager:latest’
    – ’80:80′
    – ’81:81′
    – ‘443:443’
    DB_MYSQL_HOST: “db”
    DB_MYSQL_PORT: 3306
    DB_MYSQL_USER: “npm”
    DB_MYSQL_NAME: “npm”
    – ./data:/data
    – ./letsencrypt:/etc/letsencrypt
    image: ‘jc21/mariadb-aria:10.4.12’
    MYSQL_USER: ‘npm’
    – ./data/mysql:/var/lib/mysql
    When I start docker-compose.yml without -d to see all errors. I get this error

    app_1 | ❯ Enabling IPV6 in hosts: /data/nginx
    app_1 | [1/2/2021] [3:50:42 PM] [Global ] › ℹ info Generating MySQL db configuration from environment variables
    app_1 | [1/2/2021] [3:50:42 PM] [Global ] › ℹ info Wrote db configuration to config file: ./config/production.json
    db_1 | 2021-01-02 15:50:43 3 [Warning] Access denied for user ‘npm’@’’ (using password: YES)
    app_1 | [1/2/2021] [3:50:43 PM] [Global ] › ✖ error ER_ACCESS_DENIED_ERROR: Access denied for user ‘npm’@’’ (using password: YES)
    db_1 | 2021-01-02 15:50:44 4 [Warning] Access denied for user ‘npm’@’’ (using password: YES)

  3. I need your help to analyze an error that is happening to me when I try to install NGINX proxy manager.

    When I follow the steps according to your tutorial it throws me a port error in which it says : and are already assigned…

    Note: I have installed mailcow and within the pack is Nginx alpine with that range of ports assigned … for that reason the NGINX proxy manager only works by port 81.

    What do I do?

    • Make sure that you have no other web servers or apps listening on Port 80 and 443 – It sounds like you have another Apache or nginx or docker containers that are already listening on those ports.

  4. I need your help to analyze an error that is happening to me when I try to install NGINX proxy manager.

    When I follow the steps according to your tutorial it throws me a port error in which it says : and are already assigned…

    Note: I have installed mailcow and within the pack is Nginx alpine with that range of ports assigned … for that reason the NGINX proxy manager only works by port 81.

    What do I do?

  5. Hallo wie kann man Webseiten einbinden die lokal auf den host System liegen?

    Da Nginx Proxy Manager ja im Container lauft und zb. nur mit den Gateway kommuniziert.

    Was müsste man bei ADD Host eintragen um eine lokale Webseite zb. Nextcloud einzubinden welche auf den Gastgebersystem installiert ist?

    • Dazu müsstest du den netwerkmodus auf “host” modus in der docker-compose datei vom Nginx proxy Manager umschalten und die lokale IP addresse und den Port ansprechen.

  6. Thank you for the excellent guide, is there a way in nginx proxy manager to map to a directory instead of a subdomain? for example how to turn: ==> container1:8080 ==> container2:753 ==> container3:59880
    into: ==> container1:8080 ==> container2:753 ==> container3:59880

  7. Hello
    Thank you for the great instructions
    I am struggling with Nextcloud.
    Is there a way to show me step by step how to configure Nextcloud to be accessed remotely using NPM?

    Here is what I have done so far
    1-I am able to get nextcloud to work internally
    2-I have NPM working and functioning with home assistant so I know it is working
    3-I need instructions on how to set up NPM host proxy for nextcloud
    4-I need instructions on how to modify the config.php of nextcloud to work with NPM

    Thank you in advance

  8. Thank you for the awesome guide, is there a way in NGINX Proxy Manager to reverse proxy to folder? Instead of mapping to internal host:port it’s to internal host:port?

    Thank you

  9. Thank you for the awesome article, is there a way to reverse proxy to a subfolder instead of a sub domain?
    For example: maps to internal_IP1:port maps to internal_IP2:port

    Thank you for creating all these informative guides.

  10. Hola @Christian

    I was having some trouble in order to enable UFW and NPM container in order to access to other containers outside of their docker network
    I tried to use the flag network_mode: “host” for “app” service, but, obviously, the “db” get inaccesible,
    so, after several trial/fails, I decide to mount NPM without any database, well, in fact with sqlite3, but without any other “service” in the docker-compose:
    After that, I add the flag (network host) now I am able to reach to another containers using

    Is ther a better way to do this?

    • What I do is, connect all containers to the NPM network, OR I connect NPM to all networks of the containers. You can easily connect them to more than one network, so that’s working for me very well.

      • hi
        I am just trying npm on my home serve and have same problem.

        as you are saying, connecting other containers to same docker network will work but I have some servervices running not in docker container and thats bit complicated

        I am trying to replace nginx from distro with this npm docker container because it could simplified, anyway, I am running some services on unix socket which is much faster the tcp and looks that npm is not able to do that

  11. Hallo!
    Ich bekomme immer einen internen Error, wenn ich ein SSL Zertifikat erzeugen lassen will.
    Woran kann das liegen? NPM Version ist 2.8.0

  12. Hallo Christian,

    vielen Dank für diese Anleitung und den zugehörigen Video. Ich habe es mit festem IPv4 Anschluss ausprobiert und es hat wunderbar funktioniert. Leider bekomme ich nun einen DSlite Anschluss mit fester IPv6 Adresse. Deshalb würde ich gerne wissen, wie NPM mit IPv6 arbeitet. Leider findet sich darüber arg wenig bis nichts im Internet. Hast Du dazu eventuell Informationen oder könntest Du die Voraussetzungen für diesen Fall beschreiben – IPv6 Konfiguration von Docker, Docker Compose und NPM? Könnte mir vorstellen, dass mit IPv6 sich auch viele andere jetzt und zukünftig beschäftigen müssen.

    Viele Grüße


    • Since MySQL was taken over by Oracle, senior engineers created mariaDB as a fork of MySQL. Since then a lot of things have been changed, newer versions of MySQL are a bit different than the older MySQL versions or mariadb. It’s hard to do a 1 by 1 comparison, however, I like using mariadb most of the time 🙂

  13. Hallo Christian,
    I have installed successfully and using with no problem at all.
    Only thing annoying is renewing certificates. the expiration date on the SSL certificates from Let’s Encrypt comes with 180 days expiration time as default. is there a way to change the default to 1,800 day for example?


  14. This is a very cool solution I am using only a raspberry pi with rasbian os – it works fine.
    Only problem is when i reboot the computer the the docker-compose stuff is not running but I not sure if this need some create command to know how to start the docker-compose.yml file.
    I can cd to my /opt directory and run docker-compose start but I am new to this docker compose solution.

  15. Hallo Christain! cooler Beitrag – leider scheitere ich schon im 3. Schritt – “Create a DNS A record for your domain that points to your server” … in welchen der 4 Menüpunkte (Proxy Host etc.) muss ich diesen Schritt ausführen?

    Danke und VG!

  16. I installed it on my Windows computer and everything worked perfectly right from the start. Since I do not want that computer running 24/7, I deleted the container and installed this on my Ubuntu computer. Changed ports 80 and 443 in the router to the Ubuntu computer. It works, but as soon as I use SSL for one of my domains, I get Bad Gateway 502. Without SSL, everything works. Any ideas what might be wrong?

  17. I get this error when trying to deploy the nginx stack:

    Deployment error
    Pulling db (jc21/mariadb-aria:10.4)… manifest for jc21/mariadb-aria:10.4 not found: manifest unknown: manifest unknown

    Do you know why it may be?

  18. Hallo,

    ich habe auf meinem Rasperry Pi 4 Docker und Docker-Compose mit dem Nginx Proxy Manager und Portainer installiert.

    Meine Docker-Compose Datei vom nginx-proxy-manager lautet:

    version: ‘3’
    image: ‘jc21/nginx-proxy-manager:latest’
    – ’80:80′ #HTTP Traffic
    – ’81:81′ #Dashboard Port
    – ‘443:443’ #HTTPS Traffic
    – ./config.json:/app/config/production.json
    – ./data:/data
    – ./letsencrypt:/etc/letsencrypt
    image: ‘jc21/mariadb-aria:latest’
    MYSQL_ROOT_PASSWORD: ‘Ichwillnachkuba1.’
    MYSQL_USER: ‘martin’
    MYSQL_PASSWORD: ‘Ichwillnachnamibia1.’
    – ./data/mysql:/var/lib/mysql

    Das Netzwerk vom NPM lautet “root_default”.

    Mein Portainer Container läuft in einem anderen Netzwerk, unter “bridge”. Ich habe Portainer mit dem Netzwerk vom NPM verbunden. Dies habe ich mit “docker inspect root_default” bereits kontrolliert. Darin werden die Netzwerke miteinander verbunden.

    Meine Einstellungen zu den Proxy Hosts: Domain, http,, Port 9002 (Portainer)

    Wenn ich dann die Duckdns Domain aufrufen möchte, öffnet sich ein neues Browserfenster mit dem Hinweis, dass die Verbindung fehlgeschlagen sei und man keine Verbindung zum Server unter aufbauen könne.

    Im Router ist die Portweiterleitung mit den Ports 80,443 und 9002 beim RaspberryPi erfolgt.

    Ich weiss nicht mehr weiter. Es klappt einfach nicht und ich weiss nicht warum!

    Bitte helft mir!

  19. I allready have nginx proxy manager running on my rp4 – very nice.
    But getting the nextcloud to run give me som problems

    Status: Downloaded newer image for nextcloud:latest
    Pulling nextcloud-db (mariadb:)…
    latest: Pulling from library/mariadb
    ERROR: no matching manifest for linux/arm/v7 in the manifest list entries

  20. Hi! Firstly, thanks for all the great information!

    This is slightly off topic but say I wanted to expose the /stub_status page of Nginx Proxy Manager itself, is there a proper way to go about doing this aside from manually copying or mounting a custom nginx.conf into the npm container under /etc/nginx/conf.d/ ?

  21. Hi, thanks much for the tutorials.
    I have Nginxproxymanager setup well.
    At times i will add proxy hosts and it works successfully.
    After sometime it fails to work.
    All instances are in the same server

  22. I am having trouble getting the true IP address from visitors. It reports my NGINX Proxy Manager IP address. I should mention that I am not running this in docker. I am using LXC (Container) on Proxmox.

    Under Advanced Settings, I have tried this

    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    Any ideas? Suggestions?

  23. Hi Christian,

    I used docker-compose files from your great video tutorials for nginx and other services. I run portainer (following your instructions) and ngix like in this video.
    Everything is running just well. Now I want to create backups of all data generated by my containers. For portainer and nextcloud there are volumes (can see them in portainer) and I can back them up, not problem. But for nginx there is no volume, but folder mounting:
    – ./data/mysql:/var/lib/mysql
    I can’t understand where is ./data/mysql located. where ./ points to?

    Thanks for great videos!!! You are the best!

  24. Hi,
    Great work with these tutorials! They’re easy to follow..
    Manually setting up the Nginx reverse proxy… took some effort…

  25. Hallo Christian,

    Vielen Dank für das tolle Video.
    Kann ich Nginx auch verwenden um für meinen lokalen IMAP server mir einem SSL Zertifikat zu versorgen.
    Seit Apple die Sicherheits Einstellung am iPhone verschärft hat, kann ich keine Mails mehr empfangen, weil der Dovecot IMAP Server kein gültiges Zertifikat hat.
    Muss ich in der Docker Compose Konfiguration Port 993 hinzufügen?
    Vielen Dank,

  26. Deployment error
    failed to deploy a stack: Creating network “nginxproxymanager_default” with the default driver Creating nginxproxymanager_app_1 … Creating nginxproxymanager_db_1 … [1A[2K Creating nginxproxymanager_db_1 … [31merror[0m [1B ERROR: for nginxproxymanager_db_1 Cannot start service db: error while creating mount source path ‘/data/compose/4/data/mysql’: mkdir /data: read-only file system [2A[2K Creating nginxproxymanager_app_1 … [31merror[0m [2B ERROR: for nginxproxymanager_app_1 Cannot start service app: error while creating mount source path ‘/data/compose/4/data’: mkdir /data: read-only file system ERROR: for db Cannot start service db: error while creating mount source path ‘/data/compose/4/data/mysql’: mkdir /data: read-only file system ERROR: for app Cannot start service app: error while creating mount source path ‘/data/compose/4/data’: mkdir /data: read-only file system Encountered errors while bringing up the project. : exit status 1

  27. Hello,

    I followed your tutorial and I’m really impressed with the result. Thank you so much!
    I still have a question about the access to the servers from the LAN. If I try to reach nextcloud from the internet, I have the let’s encrypt certificate, but from the LAN, it is not the case. Should I point the DNS to the Nginx proxy manager address?

  28. Is there a possibility to add non-docker web applications to this for example a different physical server which runs a web service through this proxy manager


Leave a Comment

I accept the Privacy Policy