There is an official FreeBSD port, but there is no official 'supported' configuration or documentation for using a Unifi Controller behind a reverse proxy. This guide will hopefully save you time from researching and digging around for a solution. If you are not familiar with what a Unifi Controller is then you may want to have a look at Ubiquiti's products.
I was able to compile this configuration by scraping through posts on the Ubuquiti community forums[2][3], blogs[4], as well as some trial and error.
Requirements
- A supported version FreeBSD
Install Unifi Controller
Install the port using the pre-built package. This will pull in any dependencies such as a JDK and MongoDB. As of this writing the latest version of the Unifi Controller is 6. If you prefer a more stable release you can install the Unifi LTS version instead.[1]
pkg install -y unifi6
When the port and dependencies are done installing, enable the Unifi service. There is no need to enable MongoDB, it will be started automatically by the Unifi server.
sysrc unifi_enable="YES"
If all you want is a Unifi Controller then you could stop here, but it would not be available on port 80 or 443. The purpose of the reverse proxy is to access it through the browser without having to specify a port number at the end of the URL.
Install & Configure Apache
If you already have Apache installed and running, you can skip this section.
The stock version of the package has everything required to use Apache as a reverse HTTP proxy. Install and enable using pkg.
pkg install -y apache24
sysrc apache24_enable="YES"
Enable the required modules in /usr/local/etc/apache24/httpd.conf:
- proxy_module
- proxy_http_module
- proxy_wstunnel_module
- ssl_module
- rewrite_module
These commands will enable the mentioned modules by un-commenting them from httpd.conf.
sed -i '' 's,#\(LoadModule proxy_module.*$\),\1,g' /usr/local/etc/apache24/httpd.conf
sed -i '' 's,#\(LoadModule proxy_http_module.*$\),\1,g' /usr/local/etc/apache24/httpd.conf
sed -i '' 's,#\(LoadModule proxy_wstunnel_module.*$\),\1,g' /usr/local/etc/apache24/httpd.conf
sed -i '' 's,#\(LoadModule ssl_module.*$\),\1,g' /usr/local/etc/apache24/httpd.conf
sed -i '' 's,#\(LoadModule rewrite_module.*$\),\1,g' /usr/local/etc/apache24/httpd.conf
Enable Apache to listen on port 443 to support TLS connections.
cat << EOF >/usr/local/etc/apache24/modules.d/443_mod_ssl.conf
Listen *:443
EOF
Setup Reverse Proxy
We'll use the V-Host feature to simplify things. If for whatever reason you can't use Apache V-Host's, you'll need to adjust the examples to fit your requirements.
Create a file named unifi.conf in /usr/local/etc/apache24/Includes with the following contents. Each section is commented to explain it's purpose.
# HTTP Virtual Host
<VirtualHost *:80>
ServerName unifi
ServerAlias unifi.domain.tld
# Correctly pass encoded slashes in the URL to the backend
AllowEncodedSlashes NoDecode
# Reverse Proxy setting to allow authentication to work
ProxyPreserveHost On
# Proxy all requests to the backend HTTP and websocket server
ProxyPass "/wss/" "wss://127.0.0.1:8080/wss/"
ProxyPassReverse "/wss/" "wss://127.0.0.1:8080/wss/"
ProxyPass "/" "http://127.0.0.1:8080/"
ProxyPassReverse "/" "http://127.0.0.1:8080/"
# URL Re-writing is required when proxying websockets
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /wss/(.*) wss://127.0.0.1:8080/wss/$1 [P]
# Limit access to internal network clients
<Proxy *>
<RequireAll>
Require ip 192.168.0.0/16
</RequireAll>
</Proxy>
</VirtualHost>
# HTTPS Virtual Host
<VirtualHost *:443>
ServerName unifi
ServerAlias unifi.domain.tld
# Correctly pass encoded slashes in the URL to the backend
AllowEncodedSlashes NoDecode
# Reverse Proxy setting to allow authentication to work
ProxyPreserveHost On
# Proxy all requests to the backend HTTPS and websocket server
ProxyPass "/wss/" "wss://127.0.0.1:8443/wss/"
ProxyPassReverse "/wss/" "wss://127.0.0.1:8443/wss/"
ProxyPass "/" "https://127.0.0.1:8443/"
ProxyPassReverse "/" "https://127.0.0.1:8443/"
# URL Re-writing is required when proxying websockets
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /wss/(.*) wss://127.0.0.1:8443/wss/$1 [P]
# Limit access to internal network clients
<Proxy *>
<RequireAll>
Require ip 192.168.0.0/16
</RequireAll>
</Proxy>
# Needed in order to Proxy TLS sessions
SSLProxyEngine on
SSLProxyVerify none
# Allow self-signed, non-matching name, and expired certificate
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
# Provide a proper TLS certificate.
# Get a free signed certificate from Pacy World. Mention this article. (TDMC/Pacy World, LLC. root CA required on clients)
SSLCertificateFile /usr/local/etc/ssl/certs/unifi.cert.pem
SSLCertificateKeyFile /usr/local/etc/ssl/private/unifi.key.pem
SSLCACertificateFile /usr/local/etc/ssl/certs/morante-ca-bundle.pem
</VirtualHost>
Change the paths to your TLS certificate as needed. Unfortunately HTTPS is required for the Unifi Controller to work properly.
SSLCertificateFile /usr/local/etc/ssl/certs/unifi.cert.pem
SSLCertificateKeyFile /usr/local/etc/ssl/private/unifi.key.pem
SSLCACertificateFile /usr/local/etc/ssl/certs/morante-ca-bundle.pem
Change your subnet if it's not 192.168.0.0/16 or if you want to limit access to a specific IP. The purpose of this is to prevent public access to your Unifi Controller. Remember to do it for both the HTTP and HTTPS virtual hosts.
<Proxy *>
<RequireAll>
Require ip 192.168.0.0/16
</RequireAll>
</Proxy>
Set the server name and and optional alias for the virtual host. Remember to do it for both HTTP and HTTPS.
ServerName unifi
ServerAlias unifi.domain.tld
Create DNS records if needed and save your changes.
Start your Servers
Start the Apache and Unifi Controller servers.
service apache24 start
service unifi start
Open Unifi Controller
Open the URL used for ServerName (or ServerAlias) in your browser. You'll be presented with the Setup Wizard.
If/when you have completed the setup wizard for your controller, You should be automatically redirected to the TLS version of the Unifi Controller login page while keeping the correct URL
Enter in your credentials to sign in. You should see the dashboard and no errors should popup.
[1] These instructions where written for Unifi Controller version 6.0.x. Earlier or later versions may include changes that could break redirection.
[2] community.ui.com: https://community.ui.com/questions/UniFi-behind-apache-reverse-proxy
[3] community.ui.com: https://community.ui.com/questions/Controller-behind-Apache-Reverse-Proxy-greater-login-does-not-work
[4] Warren Argus: https://blog.warbel.net/index.php/2017/10/04/how-to-configure-a-unifi-controller-behind-an-apache-reverse-proxy-with-letsencrypt
- Log in to post comments