UniFi on FreeBSD

Tired of consumer level wifi? Don’t want to afford Ruckus or Aerohive?

UniFi isn’t a bad compromise. Features like multiple SSID, VLANs.

UniFi doesn’t offer a package or installer for FreeBSD. They do have a zip file. There are certain dependencies that should be installed before firing it up.

FreeBSD install

Standard install. Nothing fancy.

Packages to install

Things you need to have installed

archivers/snappy
archivers/snappy-java
audio/alsa-lib
databases/mongodb
devel/libpthread-stubs
devel/pcre
graphics/giflib
java/java-zoneinfo
java/javavmwrapper
java/openjdk8
java/openjdk8-jre
lang/python2
lang/python27
lang/v8
print/freetype2
x11-fonts/dejavu
x11-fonts/fontconfig
x11-fonts/libfontenc
x11-fonts/mkfontdir
x11-fonts/mkfontscale
x11-toolkits/libXt
x11/dmxproto
x11/fixesproto
x11/inputproto
x11/kbproto
x11/libICE
x11/libSM
x11/libX11
x11/libXau
x11/libXdmcp
x11/libXext
x11/libXfixes
x11/libXi
x11/libXinerama
x11/libXrender
x11/libXtst
x11/libxcb
x11/recordproto
x11/renderproto
x11/xextproto
x11/xproto

pkg install ${pkg}

Don’t forget to read the readme.txt in case things have changed.

UniFi install script

#!/bin/sh

# pkg found at https://www.ubnt.com/downloads/unifi/5.2.9/UniFi.unix.zip
set -e

PATH="/bin:/usr/bin:/usr/local/bin"

while getopts "v:t" COMMAND_LINE_ARGUMENT ; do
        case "${COMMAND_LINE_ARGUMENT}" in
                v) version=${OPTARG}
                        ;;
                t) test_mode="YES"
                        ;;
                \?) echo "-v <version> is required, -t is optional"
                        exit 1
                        ;;
        esac
done

cmd_pfx=""
if [ "${test_mode}" = "YES" ]; then
        echo "Test Mode"
        cmd_pfx="echo Would issue"
fi
rm=`which rm`
mv=`which mv`
ln=`which ln`
tar=`which tar`
fetch=`which fetch`
unzip=`which unzip`
mongod=`which mongod`

base_dir=`/usr/local`

echo "creating data tarball"
cd ${base_dir}/UniFi
${cmd_pfx} ${tar} -cf ../data.tgz data
cd ${base_dir}
echo "deleting snappy"
${cmd_pfx} ${rm} -f UniFi/lib/snappy-java-1.0.5.jar
echo "deleting unifi"
${cmd_pfx} ${rm} -rf UniFi
echo "fetching new unifi"
${cmd_pfx} ${fetch} https://www.ubnt.com/downloads/unifi/${version}/UniFi.unix.zip
echo "renaming unifi to include version"
${cmd_pfx} ${mv} UniFi.unix.zip UniFi-${version}.unix.zip
echo "unzipping"
${cmd_pfx} ${unzip} UniFi-${version}.unix.zip
echo "deleting any pre-existing directory of the same name"
${cmd_pfx} ${rm} -rf UniFi-${version}
echo "moving unifi to unifi-${version}"
${cmd_pfx} ${mv} UniFi UniFi-${version}
echo "linking to unifi"
${cmd_pfx} ${ln} -s UniFi-${version} UniFi
echo "linking mongod"
cd ${base_dir}/UniFi/bin
${cmd_pfx} ${ln} -sf ${mongod} mongod
echo "linking snappy"
cd ${base_dir}/UniFi/lib
snappy=`ls snappy-java*.jar`
echo ${snappy}
${cmd_pfx} ${ln} -sf /usr/local/share/java/classes/snappy-java.jar ${snappy}
echo "extracting data tarball"
cd ${base_dir}/UniFi
tar -xf ../data.tgz
echo "done"
# EoF

UniFi rc script

Enable unifi in rc.conf

sysrc unifi_enable=YES

Copy this to /usr/local/etc/rc.d/ and make it executable

#!/bin/sh

# REQUIRE: FILESYSTEMS
# REQUIRE: NETWORKING
# PROVIDE: unifi

. /etc/rc.subr

name="unifi"
rcvar="unifi_enable"
start_cmd="unifi_start"
stop_cmd="unifi_stop"

pidfile="/var/run/${name}.pid"

load_rc_config ${name}

unifi_start() {
  if checkyesno ${rcvar}; then
    echo "Starting UniFi controller. "

    # Open up netcat to listen on port 8080, and then close the connection immediately, then quit.
    # This works around the long startup delay. Thanks to gcohen55.
    echo "" | nc -l 127.0.0.1 8080 >/dev/null &

    # The process will run until it is terminated and does not fork on its own.
    # So we start it in the background and stash the pid:
    /usr/local/bin/java -jar /usr/local/UniFi/lib/ace.jar start &
    echo $! > $pidfile

  fi
}

unifi_stop() {

  if [ -f $pidfile ]; then
    echo -n "Signaling the UniFi controller to stop..."

    # This process does take a while, but the stop command finishes before
    # the service is actually stopped. So we start it in the background:
    /usr/local/bin/java -jar /usr/local/UniFi/lib/ace.jar stop &

    # Get the pid of the stopper:
    stopper=$!

    # Wait until the stopper finishes:
    while [ `pgrep $stopper` ]; do
      echo -n "."
      sleep 5
    done

    echo " acknowledged."
    echo -n "Waiting for the UniFi controller to stop (this can take a long time)..."

    # ...then we wait until the service identified by the pid file goes away:
    while [ `pgrep -F $pidfile` ]; do
      echo -n "."
      sleep 5
    done

    # Remove the pid file:
    rm $pidfile

    echo " stopped.";
  else
    echo "There is no pid file. The controller may not be running."
  fi
}

run_rc_command "$1"

Results