Definitive Guide to Hosted UniFi 2023
Part 1 – Install Hetzner Cloud Server
Log into Hetzner and get to the main dashboard (it should say ‘Projects’). Click the grey circled ‘+ New project’ symbol in the middle of the page. This will bring you to the "Add a new project" pop up box.
Give your project a new and click "Add project"
Click the "+ CREATE SERVER" button below your newly created project.
Choose a location that is closest to you, for this demo I will choose "eu-central"
Scroll down and choose the OS image "Ubuntu 22.04"
Scroll down and choose resource type, choose a spec that is relevant to how many devices you intend to connect to your controller. You can scale the size of your VM later on but just note you will have to power it off. For this demo I will choose the smallest size.
Leave all the rest of the options as default and scroll down to "Name" and enter a name for your server
Now you can click "Create & Buy now" on the bottom right of the page and Hetzner will start baking your server in the oven.
Once its complete it will go green.
You can now click on your new created server to go to the dashboard of your server.
Now you need to login to your server. Copy the IP of your server from the dashboard and paste it into putty like below.
Click "open" and then "accept" on the box the comes up next.
Login with user "root" and the password you received vie email from Hetzner. You will be prompted to change the current password. Enter the Hetzner provided password again, then enter a new passoword of your choosing twice.
Now you need to set the hostname of your server.
Enter the following command and press enter.
nano /etc/hostname
Finally, give your server a hostname. Hostname should be something like unifi.company.com. For our demo, we’re going to use unificontroller.andersonit.co.za. 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 as we don’t have any startup scripts, and SSH keys will be created as part of this process.
Now press "CTRL + X + Y + ENTER" this will close and save the hostname file.
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 Hetzner server. This will be needed in the future when we create the secure SSL certificate for the UniFi Controller, as well as for the Let’s Encrypt SSL certificate.
Part 3 – Log into your new server
At this point, you should have your Hetzner 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 Hetzner server properties:
User: root
Password: (the password from the Hetzner 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 Public/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 – Secure 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 Hetzner 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 – Convert 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 typically 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 update sudo apt upgrade -y sudo apt 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 14 – Install NTP
Next we will install NTP (Network Time Protocol). Run the following commands:
sudo apt update && sudo apt install ntp -y
Once installed, make sure the NTP service has started by running:
service ntp status
You should see that NTP is ‘active (running)’ in green text. If you type:
date
Your local time should show correctly.
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
The ‘fallocate’ command creates a file of a specific size – in this case we’re creating a 4GB file called ‘swapfile.’
sudo chmod 600 /swapfile
Sets permissions on the swap file that we just created.
sudo mkswap /swapfile
Formats the /swapfile 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 two 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 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, we’ll install haveged. Haveged is an unpredictable random number generator for Linux. This program has historically helped to speed up launching UniFi.
sudo apt 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 OpenJDK-8 (Java)
Install OpenJDK-8
sudo apt update && sudo apt install openjdk-8-jdk -y
That’s it.4
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 installs the trusted GPG key. Now let’s install UniFi:
sudo apt update && sudo apt install unifi -y
You should now have installed the latest stable version of UniFi, which is version 6.0.43 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.
For Step 1 of the UniFi Setup Wizard, set the name of your controller, and select the box to agree to the terms of service. If you need to restore a UniFi backup file, this is where you can select that option. Click ‘Next’ to move to Step 2.
For Step 2 – this is where you can sign in with your Ubiquiti SSO (Single Sign-on) account. Alternatively, if you would like to run your UniFi Controller locally without connecting out to the UniFi.UI.com cloud services, you can click ‘Switch to Advanced Setup’ to disable remote access and create local authentication credentials. For the purposes of this documentation, we are going to assume that you are using your Ubiquiti SSO account for authentication. Once you have entered your credentials, click ‘Next’ to get to Step 3.
The next step allows you to choose whether you would like the UniFi Controller to automatically optimize your network. It is OK to leave this on – you can always change your settings later. I also recommend enabling ‘Auto Backup’ – but keep in mind that the Auto Backups write to the local hosted machine. You will still need to download these backups in order to save a copy in case the server crashes. Click ‘Next’ to move onto Step 4.
There should be no devices detected in Step 4 since this is a hosted controller – this step is typically used for local controllers where there already may be devices pending adoption on the LAN.
Step 5 allows you to 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). However, if you would like to create your first wireless SSID and password, you can do so here.
Step 6 allows you to verify your previous settings (click ‘Back’ if you want to change anything), and also allows you to set up your time zone which it pulls from the server. Since we set up the server time zone in Part 13, it should be set correctly already. Click ‘Finish’ to complete the setup.
You will see a screen that is ‘Configuring the UniFi Network Controller’ and then you will be dropped into the UniFi dashboard.
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 and Apache connector:
sudo apt update && sudo apt install certbot python3-certbot-apache -y
Now Certbot is installed, so the next step is to generate our SSL certificate.
sudo certbot --apache -d unifi2021.crosstalksolutions.com
Substitute your own FQDN instead of unifi2021.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=unifi2021.crosstalksolutions.com
Next, since we are on a Ubuntu Hetzner 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=unifi2021.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.
Conclusion
Well, that’s it – the Definitive Guide to Hosted UniFi. If you have any questions, comments, updates, or suggestions on how this process can be made even more definitive, put those in the comments below. A ton of work went into the creation of this document – please subscribe to the Crosstalk Solutions YouTube page, and use our referral links for Hetzner and/or Digital Ocean if you appreciate the effort! Also, we do full network deployment projects for businesses if you are interested in those services – be sure to click ‘Contact’ above to get in touch with us – thanks!
-Craig Anderson