Turning a Raspberry Pi into a UniFi controller appliance 
Last updated: 25 september 2014
A few months ago, a hard-float version of the Oracle Java 7 JDK for Raspbian has been released, opening up lots of new opportunities for the Raspberry Pi platform. This blog post will show you how to turn the Pi into a wifi controller appliance for the - almost equally affordable - UniFi access points from Ubquiti, which are becoming increasingly popular.
I'll be using a Raspberry Pi, model B, revision 2.0 which has 512 megabytes of RAM available. Keep in mind that this is just a proof of concept. I have not tested the setup very thoroughly and running the UniFi controller software on Linux is not officially supported, as far as I know. That being said, I haven't ran into any problems yet.
Update 25 september 2014: I'm using the Raspberry Pi to control three UniFi access points for over half a year now and it seems to be rock-solid.

Screenshot of the UniFi controller web interface.
Raspbian setup
The first step in the process will be getting your Pi up and running with Raspbian. You can download an image on the Raspberry Pi downloads page. If you don't know how to write the image to your SD card, I'd recommend you to take a look at the wiki page on this topic. After you've flashed Raspbian to the card, it's time to boot up your Pi and log in with username pi and password raspberry.Raspbian configuration
Now we still need to expand the filesystem to the size of the SD card, so we'll be able to use all the space provided by the card. To do so, run:sudo raspi-config
Choose Expand Filesystem to adjust the filesystem size. While we're in this neat little configuration tool, you might also want to adjust the amount of RAM assigned to the graphics adapter. You can do so by choosing Advanced Options > Memory split As we're running headless, 4MB would be more than enough. Reboot the device for the changes to take effect.
sudo reboot
Installing the UniFi software and its dependencies
The UniFi software package has two dependencies: Oracle Java, as stated earlier, and MongoDB. The Oracle Java 7 JDK is provided by the 'oracle-java7-jdk' package, which is installed by default on new versions of Raspbian. If you are not sure Java is installed on your device, just tell your package manager to deal with it.sudo apt-get update && sudo apt-get install oracle-java7-jdk
Now it's time to fulfill the second requirement, MongoDB. Normally, this would be quite a pain since the ARM platform is not supported by it. Fortunately, Per Ola Ingvarsson created a non-x86 version and put it online. Using this guide, you could compile it and move on. But it will take hours and hours on your Raspberry, so I'll be using the lazy approach and just fetch some precompiled binaries from GitHub, thanks to Brice Morin. If you're not experienced with compiling software, I'd recommend you to the same. Create the directory '/opt/mongodb', download the binaries (found in 'mongo/bin' in the GitHub repository) to it and make them executable.
sudo mkdir /opt/mongodb cd /opt/mongodb sudo wget https://github.com/brice-morin/ArduPi/blob/master/mongodb-rpi/mongo/bin/bsondump?raw=true -O bsondump sudo wget https://github.com/brice-morin/ArduPi/blob/master/mongodb-rpi/mongo/bin/mongo?raw=true -O mongo sudo wget https://github.com/brice-morin/ArduPi/blob/master/mongodb-rpi/mongo/bin/mongod?raw=true -O mongod sudo wget https://github.com/brice-morin/ArduPi/blob/master/mongodb-rpi/mongo/bin/mongodump?raw=true -O mongodump sudo chmod +x *
Finally, it's time to download the UniFi software. I'll be using version 2.4.6, which is available from this UniFi update announcement. You'll need to accept a license agreement, so I can't provide you with a direct download link. I downloaded the package on my desktop machine and transferred it to the home directory of the pi user using SFTP. Unzip the package and move the extracted directory into /opt.
unzip UniFi.unix.zip sudo mv UniFi /opt/UniFi
Next, we'll need to tell the controller software where it can find MongoDB. This is an easy one, as we'll only need to replace a symlink.
cd /opt/UniFi/bin sudo ln -fs /opt/mongodb/mongod mongod
At last, we're ready to fire up the controller!
sudo java -jar /opt/UniFi/lib/ace.jar start
Or start it in the background by running:
sudo java -jar /opt/UniFi/lib/ace.jar start &
If all went well, you should now be able admire the web interface of your super-awesome UniFi controller appliance through HTTPS on port 8443. To observe the log while the controller is running in the background, use:
sudo tail -f /opt/UniFi/logs/server.log
To stop the controller again:
sudo java -jar /opt/UniFi/lib/ace.jar stop
P.S. You're running server as 'root'. This won't be a good idea for production use, but using a Raspberry Pi for production will probably never be a good idea anyway. However, if you'd set permissions on the 'data' and 'log' subdirs of the UniFi directory, nothing would stop you from running the server as a different user.
Update March 15th, 2014: Running the controller on startup
To run the UniFi controller when the Raspberry boots, we'll need a startup script. Fortunately, there's a Debian package mentioned in the release announcement and this package contains such a script.By default, the script would assign a memory limit of 1024M to the controller, which I adjusted to 384M. I don't know yet if this would suffice, but it'll be easy to change anyway. I also changed the base dir path and the Java home.
So, create the file /etc/init.d/unifi with the following contents:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
| #!/bin/bash # # /etc/init.d/UniFi -- startup script for Ubiquiti UniFi # # ### BEGIN INIT INFO # Provides: unifi # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs $remote_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Ubiquiti UniFi # Description: Ubiquiti UniFi Controller ### END INIT INFO NAME="unifi" DESC="Ubiquiti UniFi Controller" BASEDIR="/opt/UniFi" MAINCLASS="com.ubnt.ace.Launcher" PIDFILE="/var/run/${NAME}/${NAME}.pid" PATH=/bin:/usr/bin:/sbin:/usr/sbin JAVA_HOME=/usr/lib/jvm/jdk-7-oracle-armhf # JSVC - for running java apps as services JSVC=`which jsvc` #JSVC_OPTS="-debug" JSVC_OPTS="${JSVC_OPTS}\ -home ${JAVA_HOME} \ -cp /usr/share/java/commons-daemon.jar:${BASEDIR}/lib/ace.jar \ -pidfile ${PIDFILE} \ -procname ${NAME} \ -outfile SYSLOG \ -errfile SYSLOG \ -Djava.awt.headless=true -Xmx384M" [ -f /etc/default/rcS ] && . /etc/default/rcS . /lib/lsb/init-functions [ -d /var/run/${NAME} ] || mkdir -p /var/run/${NAME} cd ${BASEDIR} is_not_running() { start-stop-daemon --test --start --pidfile "${PIDFILE}" \ --startas "${JAVA_HOME}/bin/java" >/dev/null RC=$? return ${RC} } case "$1" in start) log_daemon_msg "Starting ${DESC}" "${NAME}" if is_not_running; then ${JSVC} ${JSVC_OPTS} ${MAINCLASS} start sleep 1 if is_not_running; then log_end_msg 1 else log_end_msg 0 fi else log_progress_msg "(already running)" log_end_msg 1 fi ;; stop) log_daemon_msg "Stopping ${DESC}" "${NAME}" if is_not_running; then log_progress_msg "(not running)" else ${JSVC} ${JSVC_OPTS} -stop ${MAINCLASS} stop fi log_end_msg 0 ;; status) status_of_proc -p ${PIDFILE} unifi unifi && exit 0 || exit $? ;; restart|reload|force-reload) if ! is_not_running ; then if which invoke-rc.d >/dev/null 2>&1; then invoke-rc.d ${NAME} stop else /etc/init.d/${NAME} stop fi fi if which invoke-rc.d >/dev/null 2>&1; then invoke-rc.d ${NAME} start else /etc/init.d/${NAME} start fi ;; *) log_success_msg "Usage: $0 {start|stop|restart|reload|force-reload}" exit 1 ;; esac exit 0 |
This script uses jsvc, which we'll need to install. Run:
sudo apt-get update && sudo apt-get install jsvc
Enable execution of the script and make it run at boot time:
sudo chmod +x /etc/init.d/unifi sudo update-rc.d unifi defaults
You can now start your controller using your new script, or just reboot your Pi.
sudo /etc/init.d/unifi start
Follow-up
Jimmy Selgen Nielsen wrote an excellent follow-up tutorial about running the controller under it's own user. It's really worth reading. You can find it here. (Update 28 april 2015: Link has been restored.)Setting up log rotation should not be necessary, as the UniFi controller has log rotation built in.
You might also want to hang onto this topic in the Ubiquiti forums.