Install UniFi Controller On Ubuntu 20.04 Linode
In this tutorial you will be shown how to install the UniFi Controller software with SSL on Ubuntu 20.04 using a Linode VPS.
The current version of UniFi SDN Controller that we will be installing is 6.2.23 Of course new packages will be released and they can be found on there UniFi Software Download Page. The script we will be using will install the latest version.
Lets Get Started!
Prerequisites
- Create a VPS server on Linode. The $10 plan meats minimum specifications and should be just fine up to 250 devices. You can even enable the option to create VPS backups witch is ideal.
- To access the UniFi controller with a domain you will need to create an A record pointing to VPS server’s public IP address.
Getting Started With Linode
- Sign Up and Log into your Linode account and click the blue [Create Linode] button.
- The Distribution we will be selecting is Ubuntu 20.04 LTS.
- Select the best Region of yourself.
- Select the VPS plan you would like to use.
- Give your server a Label. I will be giving it a FQDN label of unifi.patrickdomingues.com.
- Give it a secure root password. Click here to generate a password.
- Everything else you can skip but if you want to have backups check mark their backup box.
- Click the blue [Create Linode] button on the right to finish
- You should now see a page with details of your new Linode VPS.
- Now that you have your server IP address , create a name \ A record pointing to your server IP.
Lets SSH into Ubuntu 20.04 and perform some updates.
- To SSH into the server we will be using Putty. Download and install Putty.
- Open up putty and type in the IPv4 address of your server and click open.
- Log into your Ubuntu 20.04 server with the username and password.
- started with making sure we have the latest updates installed.
sudo apt update sudo apt upgrade sudo apt-get install ca-certificates wget -y
5. Give it a few minutes for the updates to install and afterwards run the following command to reboot.
reboot
Lets Install UniFi SDN Control Panel on Ubuntu 20.04
- Once the server is rebooted and your reconnected into the server using SSH we will now get started with running the following command. This script was created by Glenn and its very useful.
rm unifi-latest.sh &> /dev/null; wget https://get.glennr.nl/unifi/install/install_latest/unifi-latest.sh && bash unifi-latest.sh
2. You will be prompted to keep the script which here I type in: Y
3. You will be prompted to apply some updates to the system, type in: Y
4. Now just wait while the installation proceeds to install some required software.
5. Next prompt will be to install script to be able to update Unifi Network Controller via APT, type in: Y
6. You should now be complete with the installation.
7. Lets make sure that the Unifi Controller service auto starts with the following command.
sudo systemctl enable unifi
8. We will now configure a proper firewall with rules for your Ubuntu 20.04 Server. We will be using the simple ot use ufw firewall. Before we turn on the firewall lets add some ports to the firewall rules.
sudo ufw allow 22 sudo ufw allow 8080 sudo ufw allow 8880 sudo ufw allow 8443 sudo ufw allow 80 sudo ufw allow 443 sudo ufw allow 3478/udp sudo ufw allow 10001/udp sudo ufw allow 6666/udp sudo ufw allow 47763/udp
9. Now that we have the rules in place we can enable the ufw firewall and set it to auto start.
sudo systemctl enable ufw sudo ufw enable
At this point the controller is up and running and properly configured on the firewall and server. Lets move forward with configuring SSL certificate for your domain!
Install SSL Certificate For Your Domain To Access Unifi Controller
- To start we will need to install LetsEncrypt
sudo apt-get update sudo apt-get install letsencrypt
2. Run the following command to generate a SSL Certificate for your domain. Please change the domain so it reflects your domain.
sudo letsencrypt certonly
3. Now lets download a script that will do the majority of the work for you to import the SSL Certificate into the Unifi Controller.
sudo wget https://raw.githubusercontent.com/stevejenkins/unifi-linux-utils/master/unifi_ssl_import.sh -O /usr/local/bin/unifi_ssl_import.sh
4. Lets change the Permission of the script using the following command
sudo chmod +x /usr/local/bin/unifi_ssl_import.sh
6. With these following steps we will be editing the script to use your domain.
sudo nano -w /usr/local/bin/unifi_ssl_import.sh
Within this text view locate and change the following.
Add your domain
UNIFI_HOSTNAME=unifi.yourdomain.com
Comment the three lines for Fedora/RedHat/Centos by placing a # for it:
#Uncomment following three lines for Fedora/RedHat/CentOS
#UNIFI_DIR=/opt/UniFi
#JAVA_DIR=${UNIFI_DIR}
#KEYSTORE=${UNIFI_DIR}/data/keystoreUncomment the three lines for Debian/Ubuntu
# Uncomment following three lines for Debian/Ubuntu
UNIFI_DIR=/var/lib/unifi
JAVA_DIR=/usr/lib/unifi
KEYSTORE=${UNIFI_DIR}/keystore
Set the Let’s Encrypt mode to yes:
If you only enable the line, by removing the #, and you will have to set the value to yes.LE_MODE=yes
Save and close the file
Press Ctrl +X followed by Y and Enter to save and close the file.
7. Now lets run the script to import the SSL cert info the Unifi Controller.
sudo /usr/local/bin/unifi_ssl_import.sh
8. We will now create a script to auto renew the SSL cert for you. Run the following command to create a new file.
sudo nano -w /etc/crontab
And add the following content into it
0 */12 * * * root letsencrypt renew
5 */12 * * * root unifi_ssl_import.sh
Press Ctrl +X followed by Y and Enter to save and close the file.
Installing Fail2ban
Fail2ban will protect your cloud hosted Unifi Controller from brute force attacks. This script will ban people after 4 failed attempts for 10 minutes.
rm unifi-fail2ban.sh &> /dev/null; wget https://get.glennr.nl/unifi/extra/unifi-fail2ban.sh && bash unifi-fail2ban.sh
All Done! You should now have a 100% working SSL protected Unifi Controller installed on Ubuntu 20.04 hosted on a Linode VPS.
I hope this article was helpful, if you have any questions, please feel free to contact me. If you would like to be notified of when I create a new post, you can subscribe to my blog alert.
Discover more from Patrick Domingues
Subscribe to get the latest posts sent to your email.
Hi Patrick, thanks for sharing your work, I wanted to ask, after setup the controller following your guide, how do you add devices in the different location you may have? Need to create vpn to sites, or how do I manage to point the devices to the fqdn address. Thanks in advance for your answer.
There are a few things that we will need and the only firewalls that can be adopted into a Unifi cloud controller at the moment are USG https://www.ui.com/unifi-routing/usg/ and the USG-Pro-4 https://www.ui.com/unifi-routing/unifi-security-gateway-pro-4/ . The UDM-PRO cannot be adopted onto a cloud controller you would have to use the onboard controller and access this devices from the unifi.ui.com portal. Now this being said if you are using the USG or USG-Pro within the cloud hosted controller you will have to create two sites each site will have 1 firewall adopted into each. Now this being said log into your Cloud hosted controller and on the top right you will see current site. If you click on that you will get a drop down, select add new site. Once that’s created adopt a firewall in there and one firewall in the default unless you want to create a named site for both locations. Unfortunately you can only use ip-addresses for site to site vpns. However Client (computer) vpn to firewall vpn you can use FQDN. Providing this video will be easier to follow than me explaining it https://www.youtube.com/watch?v=g2wXjV6xjMg . Its a great idea for me to have a write up and a video tutorial so I will have one done shortly. I hope this helps, if you have more questions let me know and thank you for the visit!
Patrick,
Thanks for the information you have posted here. I am on the final step of deploying a new ubuntu 20.04 server for my home automation: configuring wifi. My client machine works fine when I am connected via Ethernet. When I move from the cable to my wap, a UAP-AC-HC firmware 5.43.52, I am no longer able to get out to the internet. I have applied the firewall rules you mention in this post.
Here are my firewall rules and iptable entries
To Action From
— —— —-
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
19999/tcp ALLOW Anywhere
8443/tcp ALLOW Anywhere
8123/tcp ALLOW Anywhere
1880/tcp ALLOW Anywhere
OpenSSH ALLOW Anywhere
22/udp ALLOW Anywhere
53/tcp ALLOW Anywhere
53/udp ALLOW Anywhere
22 ALLOW Anywhere
8080 ALLOW Anywhere
8880 ALLOW Anywhere
8443 ALLOW Anywhere
80 ALLOW Anywhere
443 ALLOW Anywhere
3478/udp ALLOW Anywhere
10001/udp ALLOW Anywhere
6666/udp ALLOW Anywhere
47763/udp ALLOW Anywhere
Anywhere ALLOW 192.168.15.0/24
8880/udp ALLOW Anywhere
8843/udp ALLOW Anywhere
6789/tcp ALLOW Anywhere
1900/udp ALLOW Anywhere
5514/udp ALLOW Anywhere
9080/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
19999/tcp (v6) ALLOW Anywhere (v6)
8443/tcp (v6) ALLOW Anywhere (v6)
8123/tcp (v6) ALLOW Anywhere (v6)
1880/tcp (v6) ALLOW Anywhere (v6)
OpenSSH (v6) ALLOW Anywhere (v6)
22/udp (v6) ALLOW Anywhere (v6)
53/tcp (v6) ALLOW Anywhere (v6)
53/udp (v6) ALLOW Anywhere (v6)
22 (v6) ALLOW Anywhere (v6)
8080 (v6) ALLOW Anywhere (v6)
8880 (v6) ALLOW Anywhere (v6)
8443 (v6) ALLOW Anywhere (v6)
80 (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
3478/udp (v6) ALLOW Anywhere (v6)
10001/udp (v6) ALLOW Anywhere (v6)
6666/udp (v6) ALLOW Anywhere (v6)
47763/udp (v6) ALLOW Anywhere (v6)
8880/udp (v6) ALLOW Anywhere (v6)
8843/udp (v6) ALLOW Anywhere (v6)
6789/tcp (v6) ALLOW Anywhere (v6)
1900/udp (v6) ALLOW Anywhere (v6)
5514/udp (v6) ALLOW Anywhere (v6)
9080/tcp (v6) ALLOW Anywhere (v6)
# Generated by iptables-save v1.8.4 on Thu Dec 23 20:07:24 2021
*nat
:PREROUTING ACCEPT [1295:112217]
:INPUT ACCEPT [739:57570]
:OUTPUT ACCEPT [126:8077]
:POSTROUTING ACCEPT [75:4620]
-A POSTROUTING -o enp1s0 -j MASQUERADE
COMMIT
# Completed on Thu Dec 23 20:07:24 2021
# Generated by iptables-save v1.8.4 on Thu Dec 23 20:07:24 2021
*filter
:INPUT DROP [153:9095]
:FORWARD DROP [1:344]
:OUTPUT ACCEPT [4:168]
:ufw-after-forward – [0:0]
:ufw-after-input – [0:0]
:ufw-after-logging-forward – [0:0]
:ufw-after-logging-input – [0:0]
:ufw-after-logging-output – [0:0]
:ufw-after-output – [0:0]
:ufw-before-forward – [0:0]
:ufw-before-input – [0:0]
:ufw-before-logging-forward – [0:0]
:ufw-before-logging-input – [0:0]
:ufw-before-logging-output – [0:0]
:ufw-before-output – [0:0]
:ufw-logging-allow – [0:0]
:ufw-logging-deny – [0:0]
:ufw-not-local – [0:0]
:ufw-reject-forward – [0:0]
:ufw-reject-input – [0:0]
:ufw-reject-output – [0:0]
:ufw-skip-to-policy-forward – [0:0]
:ufw-skip-to-policy-input – [0:0]
:ufw-skip-to-policy-output – [0:0]
:ufw-track-forward – [0:0]
:ufw-track-input – [0:0]
:ufw-track-output – [0:0]
:ufw-user-forward – [0:0]
:ufw-user-input – [0:0]
:ufw-user-limit – [0:0]
:ufw-user-limit-accept – [0:0]
:ufw-user-logging-forward – [0:0]
:ufw-user-logging-input – [0:0]
:ufw-user-logging-output – [0:0]
:ufw-user-output – [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -i enp2s0 -j ACCEPT
-A INPUT -i enp1s0 -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j ufw-before-logging-input
-A INPUT -j ufw-before-input
-A INPUT -j ufw-after-input
-A INPUT -j ufw-after-logging-input
-A INPUT -j ufw-reject-input
-A INPUT -j ufw-track-input
-A FORWARD -i enp2s0 -o enp1s0 -j ACCEPT
-A FORWARD -i enp1s0 -o enp2s0 -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
-A OUTPUT -j ufw-before-logging-output
-A OUTPUT -j ufw-before-output
-A OUTPUT -j ufw-after-output
-A OUTPUT -j ufw-after-logging-output
-A OUTPUT -j ufw-reject-output
-A OUTPUT -j ufw-track-output
-A ufw-after-input -p udp -m udp –dport 137 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp –dport 138 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp –dport 139 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp –dport 445 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp –dport 67 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp –dport 68 -j ufw-skip-to-policy-input
-A ufw-after-input -m addrtype –dst-type BROADCAST -j ufw-skip-to-policy-input
-A ufw-after-logging-forward -m limit –limit 3/min –limit-burst 10 -j LOG –log-prefix “[UFW BLOCK] ”
-A ufw-after-logging-input -m limit –limit 3/min –limit-burst 10 -j LOG –log-prefix “[UFW BLOCK] ”
-A ufw-before-forward -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -p icmp -m icmp –icmp-type 3 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp –icmp-type 11 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp –icmp-type 12 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp –icmp-type 8 -j ACCEPT
-A ufw-before-forward -j ufw-user-forward
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-input -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack –ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack –ctstate INVALID -j DROP
-A ufw-before-input -p icmp -m icmp –icmp-type 3 -j ACCEPT
-A ufw-before-input -p icmp -m icmp –icmp-type 11 -j ACCEPT
-A ufw-before-input -p icmp -m icmp –icmp-type 12 -j ACCEPT
-A ufw-before-input -p icmp -m icmp –icmp-type 8 -j ACCEPT
-A ufw-before-input -p udp -m udp –sport 67 –dport 68 -j ACCEPT
-A ufw-before-input -j ufw-not-local
-A ufw-before-input -d 224.0.0.251/32 -p udp -m udp –dport 5353 -j ACCEPT
-A ufw-before-input -d 239.255.255.250/32 -p udp -m udp –dport 1900 -j ACCEPT
-A ufw-before-input -j ufw-user-input
-A ufw-before-output -o lo -j ACCEPT
-A ufw-before-output -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -j ufw-user-output
-A ufw-logging-allow -m limit –limit 3/min –limit-burst 10 -j LOG –log-prefix “[UFW ALLOW] ”
-A ufw-logging-deny -m conntrack –ctstate INVALID -m limit –limit 3/min –limit-burst 10 -j RETURN
-A ufw-logging-deny -m limit –limit 3/min –limit-burst 10 -j LOG –log-prefix “[UFW BLOCK] ”
-A ufw-not-local -m addrtype –dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype –dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype –dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit –limit 3/min –limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
-A ufw-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-track-output -p tcp -m conntrack –ctstate NEW -j ACCEPT
-A ufw-track-output -p udp -m conntrack –ctstate NEW -j ACCEPT
-A ufw-user-input -p tcp -m tcp –dport 19999 -j ACCEPT
-A ufw-user-limit -m limit –limit 3/min -j LOG –log-prefix “[UFW LIMIT BLOCK] ”
-A ufw-user-limit -j REJECT –reject-with icmp-port-unreachable
-A ufw-user-limit-accept -j ACCEPT
COMMIT
# Completed on Thu Dec 23 20:07:24 2021
Any debugging tips that you might be able to offer would be most helpful,
Thanks in advance,
Frederick
Hello Frederick,
Thank you for the visit. All those ports look correct. Are you hosting this controller internally or on Linode? Have you adopted the access point to the controller, you may have to factory reset the unit first. https://patrickdomingues.com/2020/07/17/unifi-cloud-controller-adoption-using-ssh
Another thing I noticed is that your using iptables instead of ufw, if this was configure on ubuntu use ufw.
Patrick,
I have the unifi controller installed locally. I am not using the cloud controller.
Hello Federick,
Have the previous steps provided help you get it to work or are you having a problem still? Does your controller see the access point?
Dear Patrick,
Thank you for your great tutorial! Sadly enough I end up with a “http status 404 not found” error. I followed your tutorial to the letter. Installed everything on a new Ubuntu 20.04 LTS VPS and only had to install nano and ufw which wasn’t active. Didn’t get any errors during the installation of everything that is mentioned in this tutorial. I rebooted but the result stays the same.
Do you have any tips for me to check?
Thanks,
Stef
Hello Stef,
Did you happen to install this on Linode or somewhere else? Is the Unifi service running? Are you behind another firewall? Have you double checked all ports are open?
Hi Patrick,
Thanks for responding. No I used a different VPS service. The Unifi service is active. The only firewall is the one I installed with ufw in the tutorial. All ports are open. I am suspecting that something is wrong with Java. The Network Controller application fails to start somehow. Could it be that the latest Unifi release needs a newer Java release?
Regards,
Stef
Hello,
I followed your tutorial, and the controller works fine, but I can only access it by Linode’s public IP address without SSL. I address A record for my domain after creating a subdomain. What do you think the issue is?
Hello Nazwan,
In this tutorial https://patrickdomingues.com/2021/05/12/install-ssl-certificate-onto-a-fqdn-unifi-controller/ will assist you with adding ssl. It would be best to change your ubuntu server hostname to reflect the complete subdomain FQDN.
Thank you,
Patrick Domingues
what is the procedure for upgrading the unifi controller to a newer version if its already installed?
Start with the following and follow the wizard. Made sure to download a backup config just in case.
rm unifi-latest.sh &> /dev/null; wget https://get.glennr.nl/unifi/install/install_latest/unifi-latest.sh && bash unifi-latest.sh