Want a nice tidy platform for running Ubiquiti’s UniFi controller as a stand-alone appliance? Here’s a tidy solution using an HP t5570e thin client.
Background
I recently became involved with a local school who had terrible trouble with their wireless infrastructure. The school is quite small and had a number of first-generation Apple Airport Express access points. Someone has also added a Linksys unit of some description and things were generally pretty flakey. Another local firm had replaced some of the access points with some cheap D-Link ones (Realtek-based) and from there things got even worse (surprise!).
After a little research I implemented two fixes and now things are rock solid:
- Replaced a faulty Allied Telesyn Ethernet switch. While it appeared to work at a glance it had a bad habit of randomly dropping frames. Sadly my experience with ATI over the years has not been good and this certainly didn’t help.
- Replaced all of the access points with Ubiquiti’s UniFi series.
Now I have no ties to Ubiquiti – I’ve just had a lot of success with their products over the last eight years or so. The UniFi platform is quite interesting as it requires a controller server in order to manage it, log stats and generally provide additional functionality. The trouble is that the school only had one desktop computer and the server is simply a Synology NAS appliance (these are also very good products I might add).
The desktop ran Windows 7 and was used by the office assistant. I installed UniFi on this as it was the only realistic option available at the time, but after a month or so it was clear that this would not suffice. It didn’t support running as a service without a bit of mucking around, and it had a tendancy to hog enough memory to cause a noticeable performance impact to the staff using it. Not only that, staff often needed reminding not to switch the machine off.
I had a look at various low-cost embedded options including the Raspberry Pi and ALIX boards. Most were slow and in many cases weren’t that cheap particularly once a case, storage and power supply were added.
In the end I found a new HP t5570e thin client going very cheap (NZ$90) and gave it a shot. It’s been running a a few months now and has never skipped a beat. It currently manages a network of about six access points and up to 40 clients, and looks to have enough capacity to grow further. The load average sits less than 0.1, memory typically around 60% usage and only 1.3GB disk space has been used.
HP t5570e thin client
This is just a small form factor PC that includes the following specs (full PDF here):
- VIA Nano u3500 1GHz CPU
- 2GB RAM
- 4GB IDE SSD (upgraded to an 8GB SSD so that Mongo can journal properly)
- Gigabit Ethernet
Best of all there’s no moving bits like fans and hard disks to worry about.
I opted to install Voyage Linux 0.9.6 due to the fact it’s built on Debian Wheezy and has a nice small footprint, optimised for installing on small flash storage.
Voyage Linux Installation
Here’s how to get Voyage onto the thin client.
-
Download the Voyage live CD image from http://linux.voyage.hk/download. The Nano is an x86-64 CPU so grab the amd64 version.
-
Copy the ISO image to a USB stick. In Mac OS X this is done as follows (assuming disk1 is the USB stick device — check with
diskutil list
). If you use Ubuntu jst use the startup disk creator. In Windows, try XBOOT.hdiutil convert -format UDRW -o voyage-0.9.2_amd64.dmg voyage-0.9.2_amd64.iso dd if=voyage-0.9.2_amd64.dmg of=/dev/rdisk1 bs=1m
-
Insert the USB stick into the HP thin terminal, along with a keyboard and display. Power it on and wait for it to boot, then follow the steps below. The default login is root with the password voyage. Note the steps to perform in bold. In most cases the defaults are acceptable.
Linux voyage 3.10.11-voyage #1 SMP Fri Dec 6 17:15:44 HKT 2013 x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. __ __ \ \/ /___ __ __ ___ ___ ___ Useful Commands: \ // _ \\ \/ /,-_ |/ _ |/ -_) remountrw - mount disk as read-write \/ \___/ \ / \___,\_ |\___| remountro - mount disk as read-only _/_/ _'_| remove.docs - remove all docs and manpages { V o y a g e } - L i n u x < http://linux.voyage.hk > Version: 0.9.2 (Build Date 20131219) root@voyage:~# mkdir /tmp/root root@voyage:/tmp/root# mkdir /tmp/ide root@voyage:~# mount -o loop /lib/live/mount/medium/live/filesystem.squashfs /tmp/root root@voyage:~# cd /tmp/root root@voyage:/tmp/root# /usr/local/sbin/voyage.update What would you like to do? 1 - Create new Voyage Linux disk 2 - Update existing Voyage configuration 3 - Exit (default=1 [Create new Voyage Linux disk]): some mandatory options are unset, please enter them interactively Where is the Voyage Linux distribution directory? (default=/tmp/root): What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=2 [Select Target Profile - this overwrites current settings]): Please select Voyage profile: 1 - Keep existing settings 2 - 4501 3 - 4511/4521 4 - 4801 5 - 5501 6 - 6501 7 - ALIX 8 - APU 9 - Generic PC 10 - Notebook (pcmcia) 11 - WRAP (default=7 [ALIX]): 9 What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=3 [Select Target Disk]): Partitions information major minor #blocks name 8 0 2000376 sda 8 1 2000092 sda1 8 16 7816704 sdb 8 17 62432 sdb1 7 0 51244 loop0 7 1 51244 loop1 Which device accesses the target disk [/dev/hde]? /dev/sda Which partition should I use on /dev/sda for the Voyage system [1]? Device information for /dev/sda1 device fs_type label mount point UUID ------------------------------------------------------------------------------- /dev/sda1 ext2 VOYAGE_FS (not mounted) ed3c0453-149d-4a96-a6d9-5f523e21b0ca Where can I mount the target disk [/tmp/ide]? What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=4 [Select Target Bootstrap Loader]): Which loader do you want (grub or lilo) [grub]? Which partition is used for bootstrap [1]? What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=5 [Configure Target Console]): Select terminal type: 1 - Serial Terminal 2 - Console Interface (default=2 [Console Interface]): What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=6 [Partition and Create Filesystem]): What shall I do with your Flash Media? 1 - Partition Flash Media and Create Filesystem 2 - Use Flash Media as-is (default=1 [Partition Flash Media and Create Filesystem]): What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=7 [Copy Distribution to Target]): Configuration details: ---------------------- Distribution directory: /tmp/root Disk/Flash Device: /dev/sda Installation Partition: /dev/sda1 Create Partition and FS: yes Bootstrap Partition: /dev/sda1 Will be mounted on: /tmp/ide Target system profile: Generic PC Target console: standard Bootstrap installer: grub Bootstrap partition: /dev/sda1 OK to continue (y/n)? y Ready to go .... Checking that no-one is using this disk right now ... OK Disk /dev/sda: 249 cylinders, 255 heads, 63 sectors/track Old situation: Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0 Device Boot Start End #cyls #blocks Id System /dev/sda1 * 0+ 248 249- 2000092 83 Linux /dev/sda2 0 - 0 0 0 Empty /dev/sda3 0 - 0 0 0 Empty /dev/sda4 0 - 0 0 0 Empty New situation: Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0 Device Boot Start End #cyls #blocks Id System /dev/sda1 * 0+ 248 249- 2000092 83 Linux /dev/sda2 0 - 0 0 0 Empty /dev/sda3 0 - 0 0 0 Empty /dev/sda4 0 - 0 0 0 Empty Successfully wrote the new partition table Re-reading the partition table ... If you created or changed a DOS partition, /dev/foo7, say, then use dd(1) to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1 (See fdisk(8).) mke2fs 1.42.5 (29-Jul-2012) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 125184 inodes, 500023 blocks 25001 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=515899392 16 block groups 32768 blocks per group, 32768 fragments per group 7824 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912 Allocating group tables: done Writing inode tables: done Writing superblocks and filesystem accounting information: done tune2fs 1.42.5 (29-Jul-2012) Setting maximal mount count to -1 Setting interval between checks to 0 seconds Copying files .... done Removing pcmcia from update-rc.d perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "en_NZ.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). update-rc.d: using dependency based boot sequencing Removing dnsmasq.pxe.conf in /etc/dnsmasq.more.conf Reconfiguring resolvconf perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "en_NZ.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "en_NZ.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). Updating /etc/hosts Installing grub Copy grub files from /tmp/ide to /tmp/ide/boot/grub Setting up grub under chroot /tmp/ide copyfiles.sh script completed What would you like to do? 1 - Specify Distribution Directory 2 - Select Target Profile - this overwrites current settings 3 - Select Target Disk 4 - Select Target Bootstrap Loader 5 - Configure Target Console 6 - Partition and Create Filesystem (default=8 [Exit]): root@voyage:/tmp/root# reboot
-
Remove the Voyage USB stick when prompted.
Post-Installation Tasks and UniFi Installation
Once the thin terminal has booted into Voyage there are a few more installation steps required.
-
First set a new root password:
passwd
- Set a hostname:
echo unifi > /etc/hostname
-
Set APT to use NZ (or your local country) repository mirrors instead of Japanese ones to speed up downloads:
sed -i -e 's/ftp.jp.debian.org/ftp.nz.debian.org/g' /etc/apt/sources.list
-
Update the repository cache and install security patches:
apt-get update apt-get upgrade
-
Fix locales:
apt-get install locales dpkg-reconfigure locales
-
Install required locales (e.g. 131) and select as system default.
-
Uninstall some network services we don’t need to free up disk space and improve security:
apt-get purge dnsmasq-base hostapd hostap-utils nfs-common nfs-kernel-server nocatsplash tftpd-hpa rpcbind ppp pppoe libglib1.2ldbl
-
Install default Java runtime environment (OpenJDK 6):
apt-get install default-jre-headless
-
Symlink the OpenJDK path to where UniFi expects it to be (
/usr/lib/java-6-openjdk
):cd /usr/lib/jvm ln -s java-6-openjdk-amd64 java-6-openjdk
-
Add APT sources for UniFi and MongoDB by saving the following text in
/etc/apt/sources.list.d/unifi.list
:# UniFi deb http://www.ubnt.com/downloads/unifi/distros/deb/debian debian ubiquiti # MongoDB deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen
-
Add GPG keys for the above APT repositories:
apt-key adv --keyserver keyserver.ubuntu.com --recv C0A52C50 apt-key adv --keyserver keyserver.ubuntu.com --recv 9ECBEC467F0CEB10
-
Update the APT repository cache:
apt-get update
-
Install UniFi:
apt-get install unifi
-
If you are using a HDD or SSD smaller than 16GB you will need to disable journaling in the UniFi database to save disk space. Note that this could increase the chances of DB corruption after dirty shutdowns.
service unifi stop service mongodb stop echo "unifi.db.nojournal=true" >> /var/lib/unifi/system.properties service mongodb start service unifi start
-
Add ACPI power button support so that staff can easily shut down the server properly if required. This is optional but recommended:
apt-get install acpid echo -e 'event=button/power (PWR.||PBTN)\naction=/sbin/shutdown -h now "Power button pressed"' > /etc/acpi/events/power service acpid restart
From here you should be able to browse to the UniFi web interface (it should appear at https://unifi:8443) and get started setting up access points.
Some users may wish to assign a static IP address to the UniFi controller too – I felt this unnecessary and in practice it doesn’t seem to matter.