Ubiquiti Unifi embedded server using an HP t5570e

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

UniFiI 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:

  1. 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.
  2. 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

HP t5570e thin clientThis 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.

  1. Download the Voyage live CD image from http://linux.voyage.hk/download. The Nano is an x86-64 CPU so grab the amd64 version.

  2. 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
  3. 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
  4. 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.

  1. First set a new root password:

    passwd
  2. Set a hostname:
    echo unifi > /etc/hostname
  3. 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
  4. Update the repository cache and install security patches:

    apt-get update
    apt-get upgrade
  5. Fix locales:

    apt-get install locales
    dpkg-reconfigure locales
  6. Install required locales (e.g. 131) and select as system default.

  7. 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
  8. Install default Java runtime environment (OpenJDK 6):

    apt-get install default-jre-headless
  9. 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
  10. 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
  11. 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
  12. Update the APT repository cache:

    apt-get update
  13. Install UniFi:

    apt-get install unifi
  14. 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
  15. 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.