Installing UniFi Controller 5 on pine64

It so appears that Ubiquiti UAPs rely on a UniFi Controller for smoother WiFi roaming. I ended up building one on the least expensive 64-bit system I could get: Pine A64. €42 for 1Gb RAM board + 32Gb Samsung EVO+ microSD card is quite a bargain imho :-)

Pine A64+ employed as a UniFi controller. 3D-printed yellow case courtesy of @vovakurz
Pine A64+ employed as a UniFi controller. 3D-printed yellow case courtesy of @vovakurz.

I’m a Mac user, so all the memory card manipulations are shown from a MacOS perspective. Though finding instructions for other popular OS’s wouldn’t be a problem. Here comes my (quite extensive) installation log. Enjoy! :-)
 
Installing Ubuntu 16.04

  1. Preparing microSD
    1. Finding the memory card on a Mac
      Assuming the microSD is /dev/disk2, and it has a single partition mounted on /Volumes/UNTITLED
    2. diskutil list
    3. Checking the microSD card
      1. Installing the F3 utility
        brew install f3
      2. Running the test
        f3write /Volumes/UNTITLED
        f3read /Volumes/UNTITLED
    4. Flashing the microSD card
      1. Downloading and expanding the disk image
        I used the Ubuntu Base 16.04 image found on semi-official pine64.pro forum

        xz -d < pine64-image-ubuntubase-31065bsp-longsleep.img.xz > pine64-image-ubuntubase-31065bsp-longsleep.img
      2. Unmounting all volumes from the memory card
        diskutil unmountDisk /dev/disk2
      3. Flashing the image to the card
        sudo dd if=pine64-image-ubuntubase-31065bsp-longsleep.img of=/dev/disk2 bs=1048576
      4. Setting the permanent MAC address
        The NIC on a pine64 does not have a set MAC address out of the box. So it should be set in the bootscript.

        1. A MAC address assigned to a particular pine64 can be found on a sticker on the back of the PCB. It is generally a good idea to write it down and save it for the future.
          Assuming the MAC address is 00:06:DC:8B:AB:CD
        2. Take the microSD out.
          diskutil eject /dev/disk2
        3. Insert the microSD again
          The /boot partition of the is mounted automatically on /Volumes/BOOT
        4. Editing the bootscript file uEnv.txt
          echo 'ethaddr=00:06:DC:8B:AB:CD' | tee -a /Volumes/BOOT/uEnv.txt
      5. The microSD is ready. Take it out.
        diskutil eject /dev/disk2
    5. Preparing the system
      1. Setting a static IP address for the new system on the router.
        It’s a good idea to call the new system “unifi” so that UAPs and other equipment will be able to locate the controller on the LAN.
      2. Install the microSD card, plug in the Ethernet and power up the system
      3. Logging into the system
        ssh ubuntu@unifi

        Password: ubuntu

      4. Running the image init scripts
        sudo -i
        /usr/local/sbin/pine64_update_uboot.sh
        /usr/local/sbin/pine64_update_kernel.sh
        /usr/local/sbin/resize_rootfs.sh
        reboot
      5. Setting up the locale
        This can be skipped but generally speaking a properly set locale might help avoid some rare / unpredictable errors.

        1. Update packages, just in case
          sudo apt-get update
        2. Install American English and any other locale you might need. For me it is the Russian locale.
          sudo apt-get install language-pack-ru-base language-pack-en-base
          sudo reboot
        3. Setting up the default locale to American English
          sudo update-locale LANG=en_US.UTF-8 LANGUAGE='en_US:en'
          sudo reboot
        4. Configuring the ssh server to ignore client-side locale settings.
          NB: This one can be skipped but the side effects, though unlikely, are hard to predict
          Remove LANG and LC_* from the AcceptEnv directive in /etc/ssh/sshd_config. Since those two by default are the only ones present the whole directive can be commented out:

          # AcceptEnv LANG LC_*

          And reboot again

          sudo reboot
      6. Upgrading the packages
        sudo apt-get update
        sudo apt-get upgrade
        sudo reboot
      7. Setting hostname
        1. Checking current host name
          hostname
        2. Edit /etc/hosts replacing all occurrences of the current host name with the new one: unifi
        3. Setting /etc/hostname
          echo 'unifi' | sudo tee /etc/hostname
        4. Reboot
          sudo reboot
      8. Creating a “proper” user instead of the default ubuntu user
        Assuming the desired user name is jack. New user should be assigned specific uid and gid to access the NFS exports (see below). Usually the gid is either 100 for the users group or equals the uid. Assuming the required uid is 1024 and the gid is 100.

        1. NB: Only if you intend to use NFS with a server that uses one gid for all users, otherwise just skip this one
          Configuring the system to assign all new users to the “users” group.
          Edit /etc/adduser.conf setting USERGROUPS to yes instead of no . Also make sure that USERS_GID is configured to use the desired gid.

          USERGROUPS=no
          USERS_GID=100
        2. Creating new user
          NB: Don’t use the –uid parameter if you don’t intent to use NFS

          sudo adduser --uid 1024 jack
        3. Enable sudo for the new user
          sudo adduser jack sudo
        4. Trying to log in with the new user name
          exit
          …
          ssh jack@unifi
        5. Checking sudo
          sudo ls -l /root/
        6. Disable the default user ubuntu
          sudo usermod --expiredate 1 ubuntu

Installing the NFS client
I am mounting NFS-exported directories where the UniFi Controller keeps its data and logs so that they are stored on a local file server instead of the pine64’s microSD card. This whole NFS thing can be skipped if you’re ok with the microSD card. Also I am not covering the NFS server configuration since it is too big a topic and I am not really an expert.

  1. Installing NFS client
    sudo apt-get install nfs-common
  2. Creating a directory for mounting the NFS export
    sudo mkdir /mnt/nfsexport
  3. Setting up automatic mounting by adding NFS export to the /etc/fstab
    Assuming the server name is fileserver and it exports /nfsexports/pine64unifi folder

    echo 'fileserver:/nfsexports/pine64unifi /mnt/nfsexport nfs rw 0 0' | sudo tee -a /etc/fstab
  4. Mounting NFS manually for the first time
    sudo mount -a -t nfs

Installing Java
There’s openjdk and there’s Oracle Java. I believe either could be used. I am installing both and using Oracle Java.

  1. Installing openjdk:
    sudo apt-get install openjdk-8-jdk-headless
    sudo reboot
  2. Installing Oracle Java
    sudo add-apt-repository ppa:webupd8team/java
    sudo apt-get update
    sudo apt-get install oracle-java8-installer
    sudo reboot
  3. Checking if Oracle Java is set to be used by default by the OS
    java -version
    update-alternatives --get-selections | grep java

Installing MongoDB
UniFi controller uses MongoDB version 2.*. Newer builds might cause backup issues according to UniFi – How to Install & Update via APT on Debian or Ubuntu (see 4).

  1. Prevent the OS from automatically starting newly installed services
    NB: this setting can be reversed once everything is up and running

    sudo tee /usr/sbin/policy-rc.d << EOF
    #!/bin/sh
    echo "All runlevel operations denied by policy" >&2
    exit 101
    EOF
    sudo chmod +x /usr/sbin/policy-rc.d
  2. Installing from Ubuntu repository:
    sudo apt-get install mongodb
  3. Checking if the mongodb is indeed not running
    UniFi Controller doesn’t use this system-run service but starts its own instance of mongodb instead

    sudo systemctl status mongodb.service
  4. Turning off mongodb auto-start on boot
    sudo systemctl disable mongodb.service

Installing the UniFi Controller

  1. Creating the symlinks to the NFS export for the data and log directories
    NB: Skip this step if you do not intend to use NFS
    On Ubuntu systems the UniFi Controller is by default installed in /usr/lib/unifi . This directory has symlinks to the data and log directories:
    /usr/lib/unifi/data → /var/lib/unifi
    /usr/lib/unifi/logs → /var/log/unifi
    /usr/lib/unifi/run → /var/run/unifi
    Assuming the directories where we really need them are:
    /nfsexports/pine64unifi/data
    /nfsexports/pine64unifi/logs
    /nfsexports/pine64unifi/run
    Creating the destination directories and symlinks to them:

    sudo mkdir /mnt/nfsexport/data
    sudo mkdir /mnt/nfsexport/logs
    sudo mkdir /mnt/nfsexport/run
     
    sudo ln -s /mnt/nfsexport/data /var/lib/unifi
    sudo ln -s /mnt/nfsexport/logs /var/log/unifi
    sudo ln -s /mnt/nfsexport/run /var/run/unifi
  2. Installing some requirements
    sudo apt-get install haveged libsnappy-java
  3. Installing UniFi Controller from a .deb file.
    If you are transferring the controller from another installation you have a better chance for success if you initially install the same version on pine64, restore the data from original installation and then upgrade UniFi Controller on pine64 to the latest version.

    1. The .deb files are available on the Ubiquiti site
    2. Installing
      sudo dpkg -i unifi_sysvinit_all.deb

      It’s ok if there are some errors

      sudo apt-get -f install
      sudo dpkg -i unifi_sysvinit_all.deb
  4. Setting up Java options
    1. Editing the /lib/systemd/system/unifi.service unit file.
      JAVA_HOME и _JAVA_OPTIONS Environment directives need to be added to the “Service” section of the unit file. First one instructs the UniFi Controller to run on Oracle Java, the second one takes care of the snappy-java library.

      [Service]
      …
      Environment=JAVA_HOME=/usr/lib/jvm/java-8-oracle
      Environment=_JAVA_OPTIONS=-Dorg.xerial.snappy.lib.path=/usr/lib/aarch64-linux-gnu/jni
    2. Instructing systemd to re-read the unit files
      sudo systemctl daemon-reload
  5. Running
    sudo systemctl start unifi.service
  6. Making sure the controller is up and running
    Give it a couple of minutes. Then check logs for errors

    sudo systemctl status unifi.service
    tail -f /var/log/unifi/server.log
  7. Transferring the data from previous installation
    NB: Make sure you shut down the old installation of the UniFi Controller before you start the new one
    Use the web interface to restore the data from a backup.

    https://unifi:8443/
  8. Upgrading the controller
    Skip if you are already running the latest version.

    1. Backing up using the web-interface.
      https://unifi:8443/
    2. stopping the controller
      sudo systemctl stop unifi.service
    3. Creating an extra backup of controller data and logs
      sudo tar chvzf ~/unifi-pre-upgrade-$(date -I).tar.gz /var/lib/unifi /var/log/unifi /var/run/unifi /lib/systemd/system/unifi.service
    4. Installing latest version of the controller from a .deb file
      dpkg -i unifi_sysvinit_all.deb
    5. Running the controller
      sudo systemctl start unifi.service
    6. Checking
      sudo systemctl status unifi.service
      tail -f /var/log/unifi/server.log
      https://unifi:8443/
  9. Reconfiguring the system to start the newly installed / upgraded packages automatically
    NB: Skip if you want to keep the system from automatically running services after installation or upgrade.

    sudo rm /usr/sbin/policy-rc.d

Useful links

  1. Unifi on Pine64 – aarch64 (Was Proper procedure for switching UniFi controller ??)
    JAVA_HOME and adapter adoption issues
  2. Installing UniFi Controller 5.0.0-alpha.2 on Raspberry Pi 3
    Reference set of instructions on running UniFi Controller on arm-based systems.
  3. UniFi – How to Install & Update via APT on Debian or Ubuntu
    Ubiquiti Debian and Ubuntu repository
  4. Upgrade Your Linux UniFi Controller Version in 5 Minutes
    Upgrading UniFi Controller on a Linux
    NB: based on another Linux flavor, not an Ubuntu, hence slightly different
  5. Install Oracle Java 8 / 9 in Ubuntu 16.04, Linux Mint 18
    Installing Oracle Java on Ubuntu from repository
  6. Install Oracle Java 8 In Ubuntu Or Linux Mint Via PPA Repository [JDK8]
  7. Java Home Directory Fail Issue on Ubuntu – RESOLVED
    JAVA_HOME setting for openjdk
  8. How to Install MongoDB on Ubuntu 16.04/14.04 LTS
    Installing MongoDB on Ubuntu from repository
    NB: The first MongoDB version in this repository that has arm64 support is 3.4 . The installation procedure differs slightly, see below
  9. PINE64 :: Ubuntu Xenial Image (BSP Kernel)
    The microSD image by longsleep
  10. Pine64 Wiki :: Step by Step Instructions
    Flashing a microSD with all kinds of OSes for pine64
  11. Getting Started – Linux
  12. Verify the integrity of a flash/SD card on a Mac
  13. Hands-On Exercse 2: Installing & Configuring NFS
  14. Multiarch HOWTO
  15. Re: Unifi controller running, but cannot access through browser
  16. Install Debian packages without starting daemons
  17. Information about _JAVA_OPTIONS
  18. Using environment variables in systemd units
  19. SystemdForUpstartUsers

Extras

  1. Building snappy-java.jar from source
    1. Installing prerequisites
      sudo apt-get install maven build-essential git autoconf automake libtool libgflags-dev libgtest-dev pkg-config
    2. Downloading the sources
      cd ~/src
      git clone https://github.com/xerial/snappy-java.git
    3. Building
      cd snappy-java
      make
    4. Installing
      sudo mkdir -p /opt/share/java/
      sudo cp target/snappy-java*.jar /opt/share/java/
      cd /opt/share/java/
      sudo chown root:root snappy-java*.jar
      cd /usr/share/java/
      sudo ln -s $(ls -1t /opt/share/java/snappy-java*.jar | head -n 1) snappy-java.jar
  2. Installing latest mongodb-org from developer’s repository:
    echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list
    apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 —recv BC711F9BA15703C6
    sudo apt-get update
    apt-cache show mongodb-org # checking
    sudo apt-get install mongodb-org
  3. Installing latest UniFi Controller from Ubiquiti repository
    The Ubiquiti repository does not support the aarch64/arm64 architecture, which prevents the OS from reading the list of available packages. But the unifi package is arch-independent so once the OS can see the package it can be installed. As a workaround a secondary architecture can be added to the OS, one that is supported by the repository.

    sudo dpkg --add-architecture armhf
    echo 'deb http://www.ubnt.com/downloads/unifi/debian unifi5 ubiquiti' > sudo tee /etc/apt/sources.list.d/100-ubnt.list
    apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv C0A52C50
    sudo apt-get update
    apt-cache show unifi # checking
    sudo apt-get install unifi

Disclaimer
This set of instructions is based on the experiments I personally conducted on my own accord involving neither Ubiquiti Networks nor Pine Microsystems. You are welcome to use these instructions whichever way you like though remember at all times that by using it you agree that you use it at your own risk and neither I nor anybody else except for yourself is to be held responsible in case anything goes wrong as a result of using this set of instructions.

Pardon my French … I mean English
This page is a (rather hasty) translation of the Russian original.

Installing UniFi Controller 5 on pine64

19 thoughts on “Installing UniFi Controller 5 on pine64

  1. Leonid's avatar Leonid says:

    Hello,
    i followed your How to. But when i will start unifi i have the following two errors:
    /usr/lib/unifi/bin/unifi.init: line 191: -home: command not found
    …and ….
    /usr/lib/unifi/bin/unifi.init: line 145: [: too many arguments

    then the Unifi Controller stops. Line 191 in unifi.init is: ${JSVC} ${JSVC_OPTS} ${MAINCLASS} start

    Do you know this problem? And if yes how do you fix this?

    Many thanks for help

    Leonid

    Like

    1. Hi!

      I did not see this issue so I’m just guessing here but there seems to be smth wrong with jsvc.

      You might want to check if jsvc is installed by running:
      command -v jsvc

      If everything is ok it should return /usr/bin/jsvc or smth very similar. Otherwise jsvc probably was not installed. In the latter case you might want to (re)install pre-requisites to the unifi package:
      sudo apt-get -f install
      If this goes ok unifi package needs to be installed over again:
      sudo dpkg -i unifi_sysvinit_all.deb

      Hope this helps.

      Please let me know how it works out.

      Like

  2. Leonid's avatar Leonid says:

    Hello,
    absolutely great!!! It works !!!! Yeah!!

    The reason was: the package jsvc libcommons-daemon-java was missing.
    I was not able to install the package with sudo apt-get install jsvc. But the command sudo apt-get -f install checked the dependencies and install this package automatically.
    Then i started unifi service and it starts without any errors or problems. I wait for a few minutes till the website was accessible.

    Thank you very very much for your help!

    Have a nice day!

    Leonid

    Like

    1. Great!

      Glad I was able to help you :-)

      Actually I think I found and hopefully fixed the ambiguous line in my instructions that might have caused the problem. So thanks for the bug report!

      Like

  3. Hi Ishwest,

    Thank you so much for putting this together! I was struggling to get Debian (via the wonderful DietPi distribution) working with Unifi, and have already gotten 90% further with your helpful instructions for Ubuntu.

    Unfortunately, I’ve hit a snag:

    Using Oracle Java 8, Unifi reports that it cannot find the home directory.

    Error:
    ubuntu@unifi:~$ sudo systemctl status unifi.service
    ● unifi.service – unifi
    Loaded: loaded (/lib/systemd/system/unifi.service; enabled; vendor preset: enabled)
    Active: active (exited) since Sun 2017-04-23 05:57:34 UTC; 15h ago

    Apr 23 05:57:33 unifi systemd[1]: Starting unifi…
    Apr 23 05:57:33 unifi unifi.init[4712]: * Starting Ubiquiti UniFi Controller unifi
    Apr 23 05:57:33 unifi unifi.init[4712]: Cannot locate Java Home
    Apr 23 05:57:34 unifi unifi.init[4712]: …fail!
    Apr 23 05:57:34 unifi systemd[1]: Started unifi.

    Confirming Oracle Install Dir:
    ubuntu@unifi:~$ update-alternatives –get-selections | grep java
    [truncated output]
    java manual /usr/lib/jvm/java-8-oracle/jre/bin/java

    Per your instructions:
    File: /lib/systemd/system/unifi.service

    [Service]
    [truncated]
    Environment=JAVA_HOME=/usr/lib/jvm/java-8-oracle
    Environment=_JAVA_OPTIONS=-Dorg.xerial.snappy.lib.path=/usr/lib/aarch64-linux-gnu/jni

    Like

    1. Hi!

      I’m not exactly sure what causes this problem. And since your system is different from mine I don’t think I can replicate it.

      If I’d hit an issue like this one my next move would be to “debug” unifi.init – it’s a rather straightforward bash script. first of I’d figure out if the JAVA_HOME environment variable is indeed set as instructed by the unifi.service unit file. The easy way to accomplish this would be by adding somewhere closer to the beginning of unifi.init a line akin to this one:

      echo ‘111’”$JAVA_HOME”‘222’ > /tmp/dbg123

      If after starting the unifi service the /tmp/dbg123 file consists only of “111222” then JAVA_HOME is not set. Else if it reads “111/usr/lib/jvm/java-8-oracle222” then the variable is set but is ignored / dropped / overridden somewhere further down the unifi.init script. This will hopefully give you some idea where to look further.

      Hope this helps.

      Like

  4. Dirk's avatar Dirk says:

    Hi ISHWEST
    great Job, Thanks a lot. I have a orangepipc2 (H5 also 64bit with armbian). When I install the UniFi controller run all perfect, but when I reboot the server is the Web-side not available. The UniFi service is running. I have no log’s, no errors have you any idea??
    Thank you

    Like

  5. Dirk's avatar Dirk says:

    Hi ISHWEST,
    now a short response to you. I had a little time for search. First, the controller running up with your How to on my SoC no problem Thank you. The error was in the Firefox. I must import the certificate direct in the Browser (safety and certificate), not only safety Add an exception. Then I can login in the controller software. But now the unpleasant, the controller use more as 350MB RAM from the SoC. This is to match for me. On this SoC running my cloud, vdr and… The performance is to bad with this controller soft. The software run on my laptop and all think is good.

    Like

    1. Hi Dirk,

      Thanks for the update! And yes, the controller is quite RAM-hungry. Theoretically I think it is possible to enable swapping with NFS over the Gigabit Ethernet but I do not think it is a reasonable solution :-)

      Like

      1. Dirk's avatar Dirk says:

        Hello,
        a new short update. I had change the SoC to rock64/4GB RAM with armbian (xenial). I add the Ubiquiti repository in the source list, but with this link: http://www.ubnt.com/downloads/unifi/debian stable ubiquiti . Than apt update, the info repository is not arm64 can you forgetting. Now you can install unifi and all dependencies are automatically resolved by apt. You have no “stress” with mongodb, java or so. In the web-interface the ip from the https://iP-SoC:8443 and import the certificate from the Ubiquiti. The rest is UniFi, import backup, set informer ip in the AP/switch…
        Only the controller had ~400MB RAM but with 4GB no Problem. In the Moment I have 16GB MMC for armbian/Linux 8,5GB free. The performance is super and now I have a lot of statistic of my network and every time configuration the AP and switches.
        Have a good time B/R Dirk

        Like

  6. Patrick's avatar Patrick says:

    Hello,
    i’ve been able to install everything, only used a alternative java installation.
    Now the Unifi controller isn’t reachable by the webgui.
    When i perform the Tail commando on the log file i see the error “[2018-02-02 14:21:07,146] ERROR system – [exec] error, rc=141. I tried to google for the error and search the ubuquiti forum but no success sofar.

    I realize that the time wrote this great instruction it was an older version of the unifi contoller i installed.

    Have any idea what can cause this error? i’ve installed the controller on a windows c for the time being but would like to run it on the Pine because of the power usage.

    Thanks in advanced!

    Like

    1. Hi Patrick!

      Unfortunately I’m not aware what this problem is. Which log file has this error? Is the controller running, what does sudo systemctl status unifi.service command return?

      Also, if you think that this is a controller issue, you can try installing an older version, I believe a few are available on the Ubiquiti web site. There were issues reported with controller 5.5 on pine64, you might also want to check out this thread on the pine64 forum: https://forum.pine64.org/showthread.php?tid=3017

      Good luck!

      Like

      1. Patrick's avatar Patrick says:

        I see this error in file: /var/log/unifi/server.log.

        When i check the service the ouput is:

        patrick@localhost:~$ sudo systemctl status unifi.service
        [sudo] password for patrick:
        ● unifi.service – unifi
        Loaded: loaded (/lib/systemd/system/unifi.service; enabled; vendor preset: enabled)
        Active: active (running) since Fri 2018-02-16 11:31:06 UTC; 2min 25s ago
        Process: 561 ExecStart=/usr/lib/unifi/bin/unifi.init start (code=exited, status=0/SUCCESS)
        Main PID: 589 (jsvc)
        CGroup: /system.slice/unifi.service
        ├─589 unifi -cwd /usr/lib/unifi -home /usr/lib/jvm/java-8-openjdk-arm64/ -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -pidfile /var/run/unifi/unifi.pid -proc
        ├─590 unifi -cwd /usr/lib/unifi -home /usr/lib/jvm/java-8-openjdk-arm64/ -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -pidfile /var/run/unifi/unifi.pid -proc
        └─591 unifi -cwd /usr/lib/unifi -home /usr/lib/jvm/java-8-openjdk-arm64/ -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -pidfile /var/run/unifi/unifi.pid -proc

        Feb 16 11:31:05 localhost.localdomain systemd[1]: Starting unifi…
        Feb 16 11:31:05 localhost.localdomain unifi.init[561]: * Starting Ubiquiti UniFi Controller unifi
        Feb 16 11:31:06 localhost.localdomain unifi.init[561]: …done.
        Feb 16 11:31:06 localhost.localdomain systemd[1]: Started unifi.

        In the meantime i’ve been searching but sofar without any luck.

        Like

Leave a comment