Unifi Controller Set Up

This is the Definitive Guide to Hosted UniFi.  In this guide, we will set up a hosted server using Vultr (I have confirmed that all of these steps work fine on Digital Ocean as well, but Vultr will be our example in this guide), going through some best practice security settings such as enabling secure certificate authentication, installing UniFi, and finally setting up Let’s Encrypt.

The first thing you need for this guide is an account set up with Vultr (or Digital Ocean).

Click the link below for a limited time offer, users I refer receive $100 to test out the Vultr platform.

https://www.vultr.com/?ref=8613215-6G

*** NOTE:  As I said, the rest of this document will be focused on a Vultr install.  I will be keeping this guide up to date periodically as things change with the setup – check back if you ever find that something isn’t working, and comment below if you have any trouble with any of the steps!

Part 1 – Install Vultr Virtual Server

Log into Vultr and get to the main dashboard.  Click on ‘Servers’ from the left hand menu followed by the blue circled ‘+’ symbol in the upper right.  This will bring you to the new server setup page.

The first step of the server creation is to select your location.  Pick whichever data center you want – I however, tend to choose the data center closest to my (or my client’s) geographic location.  In this case, I’m going to pick Seattle.

The next step is where we select our server type.  Click on Ubuntu and choose ‘16.04 x64’ from the drop-down.

*** Tech note:  You may be asking “Why not the latest and greatest Ubuntu 18.04??”  Well, as of the writing of this blog post, UniFi still does not install properly on Ubuntu 18.04 without downgrading the default version of MongoDB.  So, until Ubiquiti standardizes on the latest version of Mongo, I prefer to stick with the OS I know works great right out of the box.  That being said though – this same process should work fine on Ubuntu 18.04 given the extra step of downgrading the database.

Next, select your server size.  UniFi will run on anything in the $3.50/month size or higher.  For testing purposes, the $3.50/month tier is fine.  For a production system with only a few sites, the $5.00/month tier would be the best option, and then scale up from there.

Finally, you can select any options (Auto Backups are highly recommended for a production server), and then give your server a hostname.  Hostname should be something like unifi.company.com.  For our demo, we’re going to use vultrunifi.computersnstuffwaco.com.com.  This step is NOT optional – using an FQDN to inform your UniFi equipment is best practice to ensure that you can migrate later on down the road without much issue.  In addition, Let’s Encrypt is going to depend on this DNS name as well.  Startup script and SSH Keys can be left blank.

Click ‘Deploy Now’ and you’re off to the races!  You are taken back to the server summary screen.  It will take 1-2 minutes for the server to spin up, so be patient.  Once the ‘Status’ changes from ‘Installing’ to ‘Running,’ you should wait about another 30 seconds, and then you’re good to go.  Click on the name of your server to see its detail screen.

Once the server is in a ‘Running’ state, you’ll see your IP address.  Copy or make note of that IP address – we’re going to use it to create our DNS A record in the next step.  You’ll also want to make note of or copy your default root password.  (We will change that password immediately upon logging in).  You can show the password by clicking the ‘eye’ icon, or simply copy it to your clipboard by clicking the copy icon.

Part 2 – Create DNS A Record

Since you now know your IP address, you should log into your DNS hosting provider or DNS server and create a new A record that points the hostname that you created in Step 1 to the IP address of your Vultr server. This will be needed in the future when we create the secure SSL certificate for the UniFi Controller, as well as for Let’s Encrypt.

Part 3 – Log into your new server

At this point, you should have your Vultr username (root) and password from the server details.  Copy the password to your clipboard and then open up PuTTY.

Enter in the IP address or hostname of your server and then click ‘Open.’

PuTTY will open up a terminal window and first ask you if you want to accept the new host (click ‘YES’).  Then you will be given a login prompt.  Use the information from the Vultr server properties:

User:  root
Password:  (the password from the Vultr server properties – you can do SHIFT+INS or right-click to paste it in)

The very first thing that you should do is change your root password.

passwd root

You will be asked to enter your root password twice – make sure it is a STRONG password.  We will be disabling root access to this box later in this guide, but you will still need to know the root password in order to run sudo commands.

Part 4 – Create New User

Most Linux machines in the world have root as the default user.  The first line of defense is to create a separate login account with the same privileges and then disable root.

Start by creating a new user – for simplicity, for this exercise, our username will be ‘unifiadmin‘:

adduser unifiadmin

This command will have you set a password for the new user, and you can also optionally enter in some additional information such as their real name and contact info.

Next give root (sudo group) privileges to the newly created user:

usermod -aG sudo unifiadmin

This new user will now be able to use the ‘sudo’ command to run commands as root.

At this point, we have created our new user, but we haven’t yet disabled root – we will do that in a moment.  First, we will enable private key authentication as a second line of defense.

Part 5 – Create Private Key Pair

Let’s now create our public and private key pair.  The public key lives on the server, and the private key will be used to unlock access from any device that needs it.

ssh-keygen

When asked where to put the file, take the default.  You can choose whether or not to enter in a passphrase – having a passphrase means that you need both the private key and passphrase to gain access.  It provides an additional layer of security.

Once your keys have been created, you will find them in /home/root/.ssh – there should be id_rsa (private key) and id_rsa.pub (public key) files in that directory.

Next, we need to copy that key to the newly created user’s account:

ssh-copy-id unifiadmin@[server IP]

Choose ‘yes’ when asked if you want to continue, and enter unifiadmin’s password when prompted.

This command will copy the public key to the unifiadmin user’s ~/.ssh directory as an authorized_keys file.  You can now use the private key to authenticate with this server as user unifiadmin.

Part 6 – Modify SSH Settings

The next step is to modify the SSH settings so that we will both disable root user access and password authentication.  Start by editing the SSH configuration file:

nano -w /etc/ssh/sshd_config

Now scroll down until you find the line that says:

PermitRootLogin yes

And change ‘yes’ to ‘no’:

PermitRootLogin no

This disables root user login.  Next scroll down further and find:

PasswordAuthentication yes

And again change ‘yes’ to ‘no’:

PasswordAuthentication no

This disables password based authentication.  (Private key authentication should already be enabled by default – you can verify this by ensuring that PubkeyAuthentication is set to ‘yes’ in the SSH config file).

Press CTRL+X followed by ‘Y’ and ‘Enter’ to save and exit.

*** NOTE:  This next command commits these changes.  If you lose connectivity because you made any mistakes, you should just destroy the Vultr server and start over.  ALSO – keep this original PuTTY session open as you go through the next few steps…even after we restart SSH, this session will still be connected, so if you can’t connect in with the private key, you still have the opportunity to make changes.

Restart SSH with:

sudo systemctl reload sshd

Part 7 – Download Private Key File

Now we need to download our private key file.  Start by showing the contents of the id_rsa file:

cat ~/.ssh/id_rsa

Select the entire contents of the file with your mouse and press CTRL+INS to copy the text to your clipboard.

Next, open up a text editor such as Notepad and paste the entire block of text into a blank file.  Save this file in a secure location.

Once saved, you can delete the id_rsa file from the server (though, you should probably test connectivity first if this is your first time making these changes):

rm ~/.ssh/id_rsa

Part 8 – Covert Private Key to PuTTY format

Before  you can use your private key with  PuTTY, you need to convert it to .PPK format.  To do this, we’ll use another free program from the creators of PuTTY called PuTTYgen (you can download it from the same link as PuTTY above).

First, run PuTTYgen and click the ‘Load’ button.  Browse to the private key file that you saved in step 7.  When browsing for your private key, change the file type you are searching for from ‘PuTTY Private Key Files (*.ppk)’ to ‘All Files (*.*).’

Open your private key file, and you should receive a notice that the private key was successfully imported.  Click OK to get off of this notification.

Now, click the ‘Save private key’ button and save your private key as a .ppk file (I usually just use the same directory that I used to save the original private key).  You can now close PuTTYgen.

Part 9 – Log in as New User

Start a new PuTTY session – you can do this from the existing window by clicking the PuTTY icon in the upper left-hand corner and choosing ‘New Session.’

In the PuTTY window, enter the hostname of the server in the Host Name field.

Then, in the left-hand menu, expand the ‘SSH’ section underneath ‘Connection.’  Then click on ‘Auth.’  Here you will see a place to browse to your PuTTY .PPK private key file.  Click ‘Browse…’ and find the .PPK file we created in step 8.

Once you have the file loaded, click back on ‘Session’ at the top of the left-hand menu.

If you want to SAVE these connection details, you should now enter in a friendly name into the ‘Saved Sessions’ box and click the ‘Save.’ button.

Now click ‘Open,’ and you should get a ‘Login as:’ prompt.  Enter in the name of the user that you created in Part 4 (in our case, it was unifiadmin) and you should now connect to the server.  If you have a passphrase on your private key pair, you will also be prompted for that passphrase.

Part 10 – Change SSH port

Now that we can log in with our secure key, let’s take our SSH security even further by changing the default SSH port from 22 to something non-standard.

Edit the SSH config file again with:

sudo nano -w /etc/ssh/sshd_config

Find the line that says:

Port 22

And change it to:

Port [different port number]

You can use any port number for your SSH connection, but I typcially use port 2222 when I change to something non-standard.  CTRL+X followed by ‘Y’ and ‘Enter’ to save and exit Nano.

Restart SSH again with:

sudo systemctl reload sshd

Next, let’s start a new PuTTY session using all of the same settings from Part 9, but this time also change the port to whichever port you changed SSH to.  In our case, it was port 2222.  If you previously saved your PuTTY session, you should save it again with the new port number.

Part 11 – Enable UFW Firewall

At this point, we have now secured our SSH connection pretty well.  Now, let’s secure our server even more by using some firewall rules to lock everything down.

Ubuntu uses the UFW firewall, however it is not enabled by default.  First, we are going to add all of the firewall rules that we need to connect to UniFi, and then we will turn it on.

First, let’s allow our new SSH port and lock it down so that connections to this port are only allowed from our IP address:

sudo ufw allow from [IP address] to any port [SSH port number]

In this example, if your IP address is 1.2.3.4, and your SSH port is 2222, the command should be:

sudo ufw allow from 1.2.3.4 to any port 2222

Let’s also add a rule for Cockpit – which is an optional server monitoring GUI (don’t add this rule if you don’t plan on running Cockpit – it is optional…more info on Cockpit in Part 16 below):

sudo ufw allow from 1.2.3.4 to any port 9090

Once again, substitute 1.2.3.4 with your own IP address.

Next, let’s open up access to the UniFi GUI.  Important note here – you don’t actually HAVE to open up this port to the outside world if you are instead using Ubiquiti’s Single Sign On (SSO) account to access your UniFi Controller through https://unifi.ubnt.com.  BUT – you will have to use this port at least once to enable cloud access in UniFi.  You can either wait to do your firewall rules until after cloud access has been enabled, or you can disable this rule afterwards.

sudo ufw allow from 1.2.3.4 to any port 8443

Next, there are a couple of ports that we need open to the whole wide world.  These are the STUN port and the UniFi inform port:

sudo ufw allow 3478/udp
sudo ufw allow 8080

Note that the STUN port running on 3478 is UDP.

If you are going to be using a guest portal with UniFi, you will also want to open these ports:

sudo ufw allow 8880
sudo ufw allow 8843

We’re also going to need to open up ports 80 and 443 for Let’s Encrypt.  If anyone browses directly to those services, they will get a connection refused response.

sudo ufw allow 80
sudo ufw allow 443

At this point, we will now turn on our UFW firewall and take a look at the rules that we created.

sudo ufw enable

When prompted whether or not to proceed, choose yes.

Let’s take a look at our rules:

sudo ufw status

You should see something similar to this (note that I did not add the ports for guest portal access in my example):

The firewall is now running, and if you test your PuTTY connection again, you should still be able to connect.  But – if you test connecting in on the standard SSH port 22, you will not be able to connect.

Part 12 – Update Server

Now that access to the server is secured, let’s run our system updates.

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y

It’s possible that no updates will be needed, but if you are asked whether or not to proceed on any of these steps, just answer Y.

Once the updates are done, let’s give the server a reboot:

sudo reboot

The server should only take about 2 minutes to reboot, and then you can reconnect.

Part 13 – Configure Time Zone

Set up your Time Zone by running:

sudo dpkg-reconfigure tzdata

A pink bordered window will appear – select your geographic area (use America for United States) and then select your city/time zone from the list.  You can press TAB, arrow keys, and SPACE to move around these screens and make selections.

Once your time zone has been selected, press OK, and you’re done with Step 6.

Part 15 – Configure NTP

NTP (Network Time Protocol) should already be installed to keep everything in sync, but to double-check, run:

service ntp status

You should see that NTP is ‘active (running.’  If you type:

date

Your local time should show correctly (in 24-hour format).

Part 15 – Set Up a Swap File

Setting up a swap file is completely optional – I have had some folks tell me that it isn’t necessary, and others tell me that performance is much improved when a swapfile is configured.  The truth probably lies somewhere in the middle, but I tend to set up a swapfile anyway – I have never noticed a decrease in performance by setting this up, so what’s the harm?

Run the following commands to create and use a swap file.

sudo fallocate -l 4G /swapfile

This allocates 4GB as a swapfile in the /swapfile directory.

sudo chmod 600 /swapfile

Sets permissions on the swap file directory.

sudo mkswap /swapfile

Formats the swap file directory for use as a swap file.

sudo swapon /swapfile

Tells the server to use that directory as a swap file.

Finally, we need to make sure that the swap file turns on every time we reboot the server.  Run the following command to add the swap file information to the /etc/fstab file:

sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'

To verify that the command worked, type:

cat /etc/fstab

and look for a line (at the bottom of the file) that says:

/swapfile none swap sw 0 0

If that line exists in the /etc/fstab file, you’re all good.

Part 16 – Install Misc. Programs

Now, we’re going to install a few misc. programs to improve our installation.  All of these are recommended, but completely optional.

The first is Cockpit – Cockpit is a system monitoring software for viewing CPU/RAM/Disk space.  You can read more about Cockpit here:  https://cockpit-project.org/

Install Cockpit by running:

sudo apt-get install cockpit -y

Once installed, you should be able to browse to https://[server IP or FQDN]:9090.  Log in with the credentials you created in Part 4.

Next, let’s install htop – htop is an enhanced version of the ‘top’ command which shows system resources in realtime.  To be clear – top is included by default, and works perfectly fine…but I prefer the colors and layout of htop instead:

sudo apt-get install htop -y

Once installed, you can run:

htop

To see the system resources.  Press Q to exit htop.

Finally, let’s install haveged.  Haveged is an unpredictable random number generator for Linux.  This program has historically helped to speed up launching UniFi.

sudo apt-get install haveged -y

Once finished, we’re all done with the optional programs.

Part 17 – Set up autoremove

As you run updates to your server, older versions of the Linux kernel are no longer needed, and they can potentially fill up your boot volume.  To prevent this from happening, we can run:

sudo apt autoremove -y

(Go ahead and run this now).  This clears out older versions that are no longer necessary, but this command should also be scheduled to run on a regular basis.  To do this,

sudo sh -c 'echo "sudo apt autoremove -y" >> /etc/cron.monthly/autoremove'

This creates a new file called ‘autoremove’ in the /etc/cron.monthly directory which will automatically run once a month – but in order to run, this file must be made executable:

sudo chmod +x /etc/cron.monthly/autoremove

Now we’re good to go.

Part 18 – Install Java 8

*** Updated 4/25/2019 – Oracle’s Java 8 now requires an Oracle login to download, and is no longer free.  So instead, I am changing these instructions to use OpenJDK-8 instead.

Install OpenJDK-8

sudo apt update 

sudo apt install openjdk-8-jdk -y

That’s it (actually, this install is much easier than the Oracle one, and still works great).

Part 19 – Install UniFi

Finally, we’re going to install UniFi.  There are a few different ways to download and install UniFi, but for me, the easiest way to install and maintain the UniFi package is to use apt, so that is what we will do in our example.

First, we need to add an apt source for UniFi.  To do this, run the following commands:

echo 'deb http://www.ubnt.com/downloads/unifi/debian stable ubiquiti' | sudo tee /etc/apt/sources.list.d/100-ubnt-unifi.list
sudo wget -O /etc/apt/trusted.gpg.d/unifi-repo.gpg https://dl.ubnt.com/unifi/unifi-repo.gpg

These commands set up the apt repository for UniFi and install the trusted GPG key.  Now let’s install UniFi:

sudo apt-get update
sudo apt-get install unifi -y

You should now have installed the latest stable version of UniFi, which is version 5.10.19 as of the writing of this article.

Part 20 – UniFi Setup Wizard

Next, we need to go through the UniFi Setup Wizard.

Open a browser and connect to https://[server IP or FQDN]:8443.  Note that this URL should ONLY be available to the WAN IP that you set up in Part 11.

You will be prompted with a warning screen that is warning you the site may be unsafe.  This is because we have not yet installed our secure SSL certificate.  Click through the warning.

Check your timezone and click ‘Next.’  Note that if you are restoring from backup, use the link on this page.

The next step is for configuring devices – at this stage, we don’t have any devices to configure, and since this is a hosted server, any LAN devices you have plugged in would not be discovered anyway.  Click Next to continue.

Here you can add a wireless network.  For our purposes however, we are going to click ‘skip‘ since this post does not deal with actual UniFi setup (see one of my many YouTube videos for that).

The next step is to choose a username and password for the UniFi admin account.  I went with ‘unifiadmin’ as the user in order to match what we are using in SSH.  For the password, note that it will not let you move forward to the next step until your password meets their strength requirements.

Click ‘Next’ when finished followed by ‘Finish’ on the summary screen.  You will then be asked if you want to set up your Ubiquiti Cloud Access:

You can enter in your cloud access account information if you have it, but if you don’t have or don’t know this information, you can always enable it later within UniFi.

Once you proceed or skip the UniFi cloud access setup, you will be redirected to the UniFi login screen.

But we’re not done yet!!

Part 21 – Set Up Let’s Encrypt

We’re going to set up Let’s Encrypt for secure HTTPS communication with the server (and to get rid of those pesky security screens when we browse to UniFi).  We’re going to use Certbot to set up Let’s Encrypt – this well help to automate the entire process.

Install Certbot:

sudo add-apt-repository ppa:certbot/certbot

Press ENTER to continue when prompted.

sudo apt-get update

sudo apt-get install python-certbot-apache -y

Now Certbot is installed, so the next step is to generate our SSL certificate.

sudo certbot --apache -d vultrunifi.crosstalksolutions.com

Substitute your own FQDN instead of vultrunifi.crosstalksolutions.com.  When prompted, enter in an email address for use with the SSL cert.  Then press A to Agree when prompted followed by Y or N to share your email address with the Electronic Frontier Foundation (I said N).  Next you will be asked if you want to redirect all HTTP traffic to HTTPS – choose option 2.  Your Let’s Encrypt certificate has now been installed.

Next, we need to import that SSL certificate into UniFi – or in other words, we have to tell UniFi to use the Let’s Encrypt certificate.

A developer named Steve Jenkins created a really great script that automates the rest of the process, making it super easy.  So, thanks to Steve, and let’s download his script and modify a few settings.

sudo wget https://raw.githubusercontent.com/stevejenkins/unifi-linux-utils/master/unifi_ssl_import.sh -O /usr/local/bin/unifi_ssl_import.sh

sudo chmod +x /usr/local/bin/unifi_ssl_import.sh

Next, edit the /usr/local/bin/unifi_ssl_import.sh file that we imported:

sudo nano -w /usr/local/bin/unifi_ssl_import.sh

Find the line that says ‘UNIFI_HOSTNAME’ and change it to your own FQDN:

UNIFI_HOSTNAME=vultrunifi.crosstalksolutions.com

Next, since we are on a Ubuntu Vultr server instead of a flavor of RedHat (which the script was based on), we need to comment out the RedHat stuff and uncomment the Debian/Ubuntu stuff:

# Uncomment following three lines for Fedora/RedHat/CentOS
#UNIFI_DIR=/opt/UniFi
#JAVA_DIR=${UNIFI_DIR}
#KEYSTORE=${UNIFI_DIR}/data/keystore

# Uncomment following three lines for Debian/Ubuntu
UNIFI_DIR=/var/lib/unifi
JAVA_DIR=/usr/lib/unifi
KEYSTORE=${UNIFI_DIR}/keystore

Next, enable Lets Encrypt mode (change LE_MODE=no to LE_MODE=yes):

LE_MODE=yes
LE_LIVE_DIR=/etc/letsencrypt/live

Save and exit nano by doing CTRL+X followed by Y.

Finally, run the script!

sudo /usr/local/bin/unifi_ssl_import.sh

If you now close your browser and then re-open it to https://[your UniFi FQDN]:8443, you should no longer have the security warnings, and you will have a valid HTTPS certificate installed.  And no more pesky security warnings.

This is excellent – BUT – every time certbot automatically renews your Let’s Encrypt certificate, it has to be re-imported into UniFi.  So we need to run this same command on a regular basis.  To do so, we’re going to create a small script and put it into the /etc/cron.daily folder.

sudo nano -w /etc/cron.daily/unifi_ssl_import

Add these lines to the file:

#!/bin/bash
/usr/local/bin/unifi_ssl_import.sh

CTRL+X followed by Y to save and exit.

Now we need to set the permissions on the file so that it runs as root and as an executable script.

sudo chown root:root /etc/cron.daily/unifi_ssl_import

sudo chmod +x /etc/cron.daily/unifi_ssl_import

Let’s test this certificate further by running it against an SSL Server Test from SSLLabs.com.  Open the following URL in your browser:

https://www.ssllabs.com/ssltest/analyze.html?d=vultrunifi.crosstalksolutions.com&latest

Substitute my FQDN for your own.  This test takes a couple of minutes to run, but when complete, it should verify that everything is A-OK.

Finally, when it comes to Let’s Encrypt certificate renewals, Certbot handles this automatically.  You can verify this by checking out the cron file that Certbot created in /etc/cron.d:

cat /etc/cron.d/certbot

This will give you some info about the renewal process and let you know that it will try to renew the cert twice daily, which is really overkill since the certificate is good for 90 days.

If you want to test the certificate renewal process to make sure everything will renew properly, run the following command:

sudo certbot renew --dry-run

This will simulate the renewal process and you should see a ‘Congratulations all renewals succeeded’ message when complete assuming everything went OK.