NGINX part 1 : Setup a reverse proxy for UNIFI

Setting up a single UniFi controller is very simple, but in production environments, it is often necessary to go a little further than just starting up a VM and installing the appropriate packages. Indeed, it is generally wise to use the magic of failover or load balancing (implementation described in this article), but also reverse-proxy.

What good would a reverse-proxy be, you might say. Not to expose the entire server to the public, at first, but also to take advantage of the cache provided by the reverse proxy. This, in order to speed up requests, for example.
Finally, reverse-proxy can be very useful if you only have one domain name (with or without a sub-domain), and you want to set up several “entry points” (for example: and or or which will point to the same reverse-proxy which will switch to the corresponding machines).

It is this last aspect of reverse-proxy that we will implement in this article.

  • We will start by installing and configuring Nginx to expose our entry point,
  • we will install and configure Certbot (The set of scripts to automate letsencrypt) to install valid TLS certificates,
  • finally we will test everything to make sure that everything works.

Some aspects of the configuration will not be covered by this article and will be considered acquired or already in place. If you want to know more about some of these aspects, I recommend the excellent DigitalOcean tutorials, and of course all the others.

As for the configuration, we will consider here that the machine is installed under Ubuntu 16.04 (LTS), the configured and updated network. In my case, the machine is installed locally only (isolated Labo zone, on a dedicated infra), behind a firewall from which I will configure port forwarding to the reverse-proxy:

80 (http)
443 (https)
8080 (UniFi devices adoption)
– 3478 (STUN for communication between devices and controller)

The list of ports used by Unifi is available on the Ubiquiti website at this address:

We also assume that you already have a domain name that points to the IP address of your infrastructure (Firewall, Machine, etc…) and a UniFi controller, regardless of the version.

In the end, we will have the following architecture:

Installing and configuring nginx

For the installation of Nginx, I direct you to the DigitalOcean tutorial which is very helpful:

Once you have a working Nginx (A “Welcome to Nginx” page appears when you enter the IP address of the machine in a browser), you must go to the browser’s configuration.

The server will be configured to “serve” content to First we go to the configuration directory of Nginx virtual hosts

$ cd /etc/nginx/conf.d/

We will edit our own conf file: unifi.conf. This file is automatically added to the nginx conf (Directive included in the Nginx general conf file)

$ sudo vi unifi.conf

# On sert sur le port 80 pour rediriger vers le 443
server {
        listen 80;
# We listen on all interfaces but only calls to the address below will trigger the processing of our conf file
	return 301 https://$host$request_uri;

server {
        listen 443 ssl;

# Access and errors are logged in their respective logs
        error_log  /var/log/nginx/unifi-443-error.log;
        access_log  /var/log/nginx/unifi-443-access.log;

#  Important part to avoid "Websocket connection error" errors on the UniFi interface. In general, we manage alerts 
# on the UniFi dashboard that will be (Under development and available in future versions of UniFi) conveyed by websockets. 
# More informations :
location /wss/ {
                proxy_pass https://lab-ubnt-uni01.lab:8443;
                proxy_http_version 1.1;
                proxy_buffering off;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_read_timeout 86400;

# This is where it all comes down to this. It is with this block that we pass our requests to the UniFi server (called Upstream) 
 location / {
        proxy_pass_header Authorization;
        proxy_pass https://lab-ubnt-uni01.lab:8443/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

#  This part is also important, it will be used for the renewal of certificates by LetsEncrypt. 
 location /.well-known/acme-challenge/ {

	root /usr/share/nginx/html;


We create the directory /usr/share/nginx/html so that Nginx can expose it if necessary

$ sudo mkdir /usr/share/nginx/html

For the next part, and for Certbot (which we will install just after) to be aware of the existence of our configuration, it must be activated. To do so, it’s very simple, we just have to restart Nginx.

$ service nginx restart

Save and fire up the command

ubntrvs@lab-ubnt-rvs01:/etc/nginx/conf.d$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

We now have our configuration ready. We still need to install LetsEncrypt to request and retrieve valid certificates.

Installing and configuring Certbot (LE)

Certbot is the little robot that will simplify the automation of obtaining your certificates with LetsEncrypt.

As for the installation of Nginx, I suggest you the DigitalOcean tutorial to install LE:

To make it simple, we add the repo, update the repositories, and install Certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx

We retrieve our certificate :

sudo certbot --nginx -d

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to

Answer “A” to accept the terms, then yes or no if you want to provide your email address. You will see Certbot modify the conf file previously written by us just above.

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/unifi.conf

The next question allows Certbot to know if it should, or not, modify our configuration to add an HTTP -> HTTPS redirection. We will answer no (Choice 1) because we have already taken it into account in our configuration.

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/unifi.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled

You should test your configuration at:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2019-05-30. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

Certbot manages the restart of Nginx. Everything must run now and if your upstream (the UniFi server) works well, you must be able to connect to it at the address you have defined (In our case, http(s)://

A nice address with HTTPS and a valid certificate !

5 2 votes
Article Rating
Notify of
1 Comment
Newest Most Voted
Inline Feedbacks
View all comments
6 July 2021 21 h 58 min
location /.well-known/acme-challenge/ {

	root /usr/share/nginx/html;

This was the missing part of my Unfi config. Once I added it back I was able to renew my cert! Thanks!