Using Unifi controller on Docker
Spoiler alert… I no longer use Unifi hardware, and I’ll share why in a future post.
I have 2 servers :
- local server at home, which runs the Unifi controller in a Docker swarm setup ;
- remote server online, which runs the NGiNX reverse proxy.
The local server uses firewall rules (via PFSense) in order to filter incoming requests, so that it only accepts request from the remote server.
As explained above, my local server runs the Unifi server in Docker swarm “mode”, here is the config :
As you can see, I expose quite a lot of ports, however they are almost all available only from my local network.
The only exception being the port 8443 that is open to my remote server (via PFSense firewall).
For more information about the Docker image, please check their official page.
For the nginx part, I do not use the jwilder version, because as far as I know, it requires ports to be exposed.
I’ll start by showing my container config. This is a docker-compose.yml file :
Let’s explain a little bit what it does :
- I only expose ports 80 and 443 ;
- The nginx (official) image mounts volumes /etc/letsencrypt directory + DH param file from host as well, into my container and the conf.d directory (which holds my virtual hosts) ;
- I create network aliases and separate networks for my “group of apps”.
The network thing is very important. Remember, when I told you that I do not want to expose too many ports. Creating separate networks allow me to do so.
I have all my “web” apps, on the same network (br0, on this example). Which means, the reverse proxy can reach any other container by using its alias (even when containers’s IP change). This is kind of Docker’s internal DNS system.
I see two main benefits by not exposing the ports when my “backend” containers and my reverse proxy containers are running both on the same host :
- I can use the same “internal” ports on all my backend containers (often 80 or 443);
- I only expose 80 and 443 from my remote server to the rest of the world!
Setting up nginx virtual host
Now, that I have shared the reverse proxy container, let’s see how it is connecting to my local computer.
This is a nginx vhost config which resides in ./conf.d (symlinked from ./conf.d/vhost) :
As you can see, the proxy pass directive uses: https://domain.com:8443. Like I explained previously, domain.com points to my home server and port 8443 is only open from my remote server.
If the Unifi controller were running on the same host, then the proxy pass would point to the the network alias of that container without exposing any port. It would look something like below:
Finally, unifi.domain.com points to my remote server and force redirects to the httpS URL, using wildcard certs from Let’s Encrypt.
Getting it all httpS!
I generated my wildard certificate thanks to Let’s Encrypt Docker image.
Finally SSL certs are automagically renewed via a systemd “job” than runs the official letsencrypt container and renew my cert (wildcard), like below :