Guess this article was one long overdue considering how many Docker containers I run and a decent amount of those are running via reverse proxy.

Considering that I run Docker on Synology NAS, I used the built-in reverse proxy feature for years for several reasons. It was built in, it offered enough options out of the box, and I was lazy to run my separate one.

Well as it turns out, there are some solutions out there that require several features inside your reverse proxy to make them run correctly. This was the main reason why I made the switch to NGINX proxy manager.

Let's see how to run your version in parallel to your Synology NAS one.

NPM in Docker

Like any other modern open-source solution out there, NPM runs in Docker. There is a prerequisite to it, and that's a MySQL database that you can run and build in parallel using the following docker-compose file (via Portainer for example):

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:latest'
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - ./data/mysql:/var/lib/mysql

This compose file will allow you to run two services (two containers). app one is the NPM itself, and the DB one is the MySQL container that NPM will use as its database.

NOTE: if you have MySQL set up already up and running you can run only NPM and connect to your DB instance using the following compose
version: "3"

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: npm
    network_mode: "bridge"
    ports:
      - "80:80"
      - "81:81"
      - "443:443"
    environment:
      DB_MYSQL_HOST: "yourMySQLIPaddress"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm_user"
      DB_MYSQL_PASSWORD: "npm_pass"
      DB_MYSQL_NAME: "npm_database"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    restart: always

One thing to notice here is the ports. As you can see there are 3 ports in use: 80, 81, and 443.

Most of you guessed that ports 80/443 will be used for actual reverse proxy needs, and port 81 is your NPM web UI access port.

The reason I'm mentioning this is that if you will be running this on your Synology NAS, for example, you will notice that you will not be able to use the port 80/443 combo considering Synology NAS already uses those ports, for its own NGINX.

There is no reason to do any hacking just make sure those are mapped to Docker NPM ports to something else so they don't clash with the reserved ones. Something like this:

8765:80
81:81
8907:443

Of course, this is just an example, but you get the idea, so just change the left-hand side (you can change port 81 as well) values to match your needs and you are off to the races.

This will require one more change. Port forwarding on your router. If up until now you have had your port 80/443 forwarded to 80/443 (the built-in ports/NGINX), now you will have to forward them to these new values. Nothing spectacular but just wanted to make you aware of the needed change.

Logging into the NPM UI

In any case, once you get it up and running you will have access to the UI using your NAS IP address and port 81: http://yournasIP:81.

NPM main logon page

Use the following combination as your login account (you will be prompted to change it all once you log in):

Email:    admin@example.com
Password: changeme
Dashboard overview of NPM

Importing your existing SSL certificates

Using the SSL certificates tab you will have the option to issue your own Let's Encrypt certificate or import your existing one.

If you want to import your exising certificates, use the "Custom" option

Clicking on the SSL certificates tab you will land on the certificates page and in the upper right corner, there is the Add SSL certificate button.

Use the Custom option to import your own, existing certificate:

Add the needed files to import your certificate
NOTE: Certificate and its privkey fill be imported into the /data/custom_ssl folder into subfolders following this pattern for each new certificate, npm-1, npm-2, etc.

Creating a reverse proxy entry

Once you have the certificate ready, you can start to add your reverse proxy entries.

Use the "Hosts" menu to add your proxy hosts
Fill in the needed info for your reverse proxy entry

Domain names: FQDN address of your entry
Scheme: http or https protocol that you want your app to respond
Forward hostname/IP: loca IP address of your app/service
Forward port: LAN port number of your app/service

Notice that you also have the option here to use Websockets support in case your app needs it (like Rocket.Chat, Bitwarden, Commento, etc)

Once you are done, you will need to assign an SSL certificate to that entry, so hop on to the SSL tab in the same dialog box:

Select your SSL certificate and options

Here you will be able to use the dropdown menu to select from your previously imported/created certificates and to select from several SSL features.

Notice that there is an option to Force SSL. This is the HTTP > HTTPS redirect feature that in DSM OS I have done using the following method and then added a reverse proxy entry for each URL. Of course, this HTTP > HTTPS method is still valid if you plan on using the web station to host your web apps.

Once you are done, click Save, and you are done.

Why use NPM and not the built-in version inside DSM?

An excellent question, and for me, there is one reason. The number of features and modules activated.

The built-in version has no modules active and it's running version 1.16.1 of NGINX with TLS SNI support enabled.

NPM version at the time of writing this article is currently on version 1.19.3.1 with loads of modules active (like http_auth_request_module that I was after)

Current NPM version and all the loaded modules

Another thing is the benefit of HTTP > HTTPS redirects, but I would have to say that what surprised me the most, like speed.

Yes, speed is noticeably faster than when using the built-in NGINX (I run this container on the same NAS that was my previous reverse proxy entry point).

So, all in all, win all around.

Conclusion

As I said before, long overdue, but I don't think I will be going back any time soon considering that once again Docker platform has managed to give me a solution for a very important element of my self-hosting, and the fact that I can host it on any Docker-capable host.