Setting up a UniFi Controller behind an nginx reverse proxy allows more control over who has access to your web gui, as well as allowing you to not have to specify a port when connecting to your UniFi Controller.

This guide is assuming y0u've already installed UniFi. You don't need to have UniFi already using a Let's Encrypt certificate if you want to use this.

First of all, install nginx:

sudo apt install nginx

Switch to the root user and install acme.sh:

sudo -i
curl https://get.acme.sh | sh

Open bash again to be able to use the acme.sh command:

bash

Import your DNS API keys (note: If you're not using Cloudflare, you can read about other DNS integrations here)

export CF_Key="YOUR_API_KEY"
export CF_Email="YOUR_EMAIL"

Next, issue the certificate:

acme.sh --issue --dns dns_cf -d unifi.yourdomain.com

Next, you're going to install the certificate. Create the folder, then install the certificate:

mkdir -p /etc/nginx/ssl/unifi.yourdomain.com

acme.sh --install-cert -d unifi.yourdomain.com \
--key-file /etc/nginx/ssl/unifi.yourdomain.com/key.pem \
--fullchain-file /etc/nginx/ssl/unifi.yourdomain.com/fullchain.pem \
--reloadcmd "systemctl reload nginx"

Next, you're going to remove the default nginx config:

rm /etc/nginx/sites-enabled/default

Next, open a text editor for your UniFi configuration file:

nano /etc/nginx/sites-available/unifi

Paste the following in:

server {
	listen 80;
	server_name unifi.yourdomain.com;
	return 301 https://$server_name$request_uri;
	}

server {
	listen 443 ssl http2;
	server_name unifi.yourdomain.com;
	ssl_certificate /etc/nginx/ssl/unifi.yourdomain.com/fullchain.pem;
	ssl_certificate_key /etc/nginx/ssl/unifi.yourdomain.com/key.pem;
	include /etc/nginx/snippets/ssl-params.conf;

	location / {
		proxy_pass https://localhost:8443;
		proxy_http_version 1.1;
		proxy_buffering off;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "Upgrade";
		proxy_read_timeout 86400;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
	}
}

Change unifi.yourdomain.com to your domain under server_name,  ssl_certificate, and ssl_certificate_key.

Once you're done, you can save and exit by pressing ctrl + x, press "y" and hit enter, then hit enter again to confirm the file name.

Next, set up a ssl-params file. If you know what you're doing, you can set up your own, or use mine.

Open a text editor at /etc/nginx/snippets/ssl-params.conf:

nano /etc/nginx/snippets/ssl-params.conf

And paste this in:

# SSL ciphers from https://mozilla.github.io/server-side-tls/ssl-config-generator/
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers   on;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
resolver 1.1.1.1 1.0.0.1; # change this to your dns resolver's IP if necessary
ssl_stapling on;
ssl_stapling_verify on;

# uncomment this for HSTS
#add_header Strict-Transport-Security 'max-age=63072000';

add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

Now you're almost ready to deploy your new nginx configuration. Symlink your unifi configuration to sites-enabled:

ln -s /etc/nginx/sites-available/unifi /etc/nginx/sites-enabled/

Restart nginx:

systemctl restart nginx

Assuming you followed every step in this guide, you should now be able to access your UniFi controller at your hostname, using a Let's Encrypt certificate, and no port specification required, as it's running on the default https port!