Using Raspberry Pi as a UniFi controller

Despite having had relatively high end network products, I’ve had numerous problems getting maximum performance from the network. Because of this, I’ve recently converted my home network from various consumer products to running mostly Ubiquity products, including EdgeMax Routers and UniFi AP.

Part of the UniFi product line is the UniFi Controller, which is an application that sits on your network, and actively monitors your access points. Running it is optional except for various enterprise functions, like guest network hotspot.

I was initially going to run it on my Synology DS1511, or my Mac Mini media server, but i ran across a nice tutorial on how to setup a Raspberry Pi for this specific purpose, and since i had a spare RPi lying around, i couldn’t resist trying it.

I followed the tutorial, and added a startup script

#!/bin/sh
### BEGIN INIT INFO
# Provides: unifi
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $network
# Should-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts the UniFi admin interface
# Description: Starts the UniFi admin interface.
### END INIT INFO

DAEMON=/usr/bin/java
DAEMON_ARGS="-jar /opt/UniFi/lib/ace.jar start"

start() {
    echo "Starting unifi"
    start-stop-daemon -b -o -c unifi -S -u unifi -x $DAEMON -- $DAEMON_ARGS
}

stop() {
    dbpid=`pgrep -fu unifi $DAEMON`
    if [ ! -z "$dbpid" ]; then
        echo "Stopping unifi"
        start-stop-daemon -o -c unifi -K -u unifi -x $DAEMON -- $DAEMON_ARGS
    fi
}

status() {
    dbpid=`pgrep -fu unifi $DAEMON`
    if [ -z "$dbpid" ]; then
        echo "unifi: not running."
    else
        echo "unifi: running (pid $dbpid)"
    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart|reload|force-reload)
        stop
        start
        ;;
    status)
        status
        ;;
    *)
        echo "Usage: /etc/init.d/unifi {start|stop|reload|force-reload|restart|status}"
        exit 1
esac

exit 0

Copy the script to /etc/init.d and set execute permissions on it

$ sudo cp unifi /etc/init.d
$ sudo chmod +x /etc/init.d/unifi

The create the unifi user

$ sudo adduser unifi

Set permissions on the UniFi controller software for the unifi user

$ cd /opt/UniFi
$ sudo chown -R unifi work data logs

We also need to setup log rotating to avoid filling up the SD Card. I couldn’t find any documentation on how to tell UniFi to reopen its logfiles, and instead of stopping/starting the controller, i chose to simply truncate the existing logs. According to the logrotate documentation this can cause log statements to get lost, but since this is a setup for my home WiFi I’m willing to accept the risk.

To setup logrotate edit the file /etc/logrotate.d/unifi and paste the following contents into it

/opt/UniFi/logs/*.log {
        rotate 7
        daily
        missingok
        notifempty
        delaycompress
        compress
        copytruncate
}

logrotate is invoked via cron, so there’s nothing to restart, it will pickup the changes when it is next run.

Now enable the service

$ sudo update-rc.d unifi defaults

And start it

$ sudo service unifi start

My Raspberry Pi is now running as a controller for my UniFi AP’s, and it seems to be handling the load quite nice

top - 19:54:06 up 56 min,  2 users,  load average: 0,00, 0,09, 0,16
Tasks:  75 total,   1 running,  74 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5,5 us,  5,5 sy,  0,0 ni, 89,1 id,  0,0 wa,  0,0 hi,  0,0 si,  0,0 st
KiB Mem:    496948 total,   305616 used,   191332 free,    19424 buffers
KiB Swap:   102396 total,        0 used,   102396 free,   186428 cached

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 4018 unifi     20   0  260m  52m 7984 S   1,8 10,8   1:04.22 java
 4039 unifi     20   0  117m  34m  20m S   1,8  7,0   0:11.95 mongod

Still waiting for my Axis.APU to run PFSense, but that’s a story for another day


See also