Using Nginx Proxy Manager to Protect Itself
Docker is awesome,
and a ton of projects can be spun up in just a few minutes using Docker Compose. Many of these primarily use a Web UI, meaning the entire graphical interface exists within the browser. Unfortunately, most of the time these UI use plain HTTP, which is vulnerable to MITM attacks as it is completely unencrypted. Adding SSL certificates can be a pain, since each service/container will have a different method of installation and configuration. The solution to this, is to tunnel everything through a reverse proxy like nginx, but nginx can be a bit cumbersome to configure. Enter Nginx Proxy Manager, a dead simple container that allows you, with an excellent web GUI, to do just that.
The first thing you need to be aware of, is the difference between expose and ports in docker compose.
The ports option essentially allows a container to communicate with the outside world. It will map a port from that specific docker container, to an external port on the machine it is running on. This means any other machine running on the network can also see whatever is on that port, by pointing at the machine's IP instead of the container.
The expose option essentially allows containers to communicate with eachother on a port, but not the outside world.
What we want to do, is have all our containers expose the ports to their web UI internally, but not externally. Next, we map the ports (using the ports option) for http(80, so we can redirect automatically) and https(443) to the nginx Proxy Manager container, so that outside machines can see it.
Now NPM is the only thing that can talk to those other containers, so we configure it to act as a proxy. Our browser talks to NPM on port 443, and NPM talks to the container on whatever port the container uses. Since we'll set NPM to use SSL, and all the non-ssl talk is only inside the docker network, we are secure.
OK, that was a lot of background to get to the one rub...
NPM itself has a web GUI running on port 81, and that web GUI is by default, plain HTTP. The key here, is first to map port 81 using the ports option, then log on to NPM and configure it to point back at itself, only encrypted. Then we hop back in to Docker Compose, and change port 81 to be exposed instead of mapped. Now when we access the web UI for NPM, we speak to it using HTTPS, and it talks to itself internally using plain HTTP. NPM has it's share of security concerns, and doing this takes care of the lion's share of them.
Here's what it all looks like:
Now, and this step is important, you need to pop in to your DNS server and add an entry pointing npm.yourdomain.edu to the correct IP.
And we are all good to go!
NPM's port 81 is closed off to the outside world, but we can still reach and configure NPM via the web GUI!