UniFi Controller

From Alpine Linux
Revision as of 06:41, 4 July 2023 by Jdusablon (talk | contribs) (Add warning about the effective deprecation of MongoDB on Alpine Linux >v.3.9)

Notice

The Ubiquiti Unifi controller linux self-contained java image relies on MongoDB, and MongoDB has been removed from alpine linux packages after version 3.9 due to SPL license changes. MongoDB can technically be installed by adding Alpine Linux 3.9 repositories and installing mongodb and yaml-cpp=0.6.2-r2, however this solution requires pinning yaml-cpp to version 0.6.2, which is likely to cause issues with any other packages relying on yaml parsing using yaml-cpp.

Introduction

This guide explains how to install the generic Unix UniFi Controller, as available from Ubiquiti Networks. At the time of writing this, a native Alpine Linux package is not available.

Furthermore, this guide uses the incredibly reliable and efficient s6 supervision suite to start and control the UniFi Controller.

A summarized schematic of what will be installed on the filesystem.

The choice of /srv for the UniFi Controller's root directory is based on the fact that it contains both run-time and configuration data, so installing to /usr/local, /opt or /home didn't seem appropriate. Feel free to adjust the steps below, replacing /srv/unifi with wherever you would prefer to install the UniFi Controller software.

/
`--etc
   |-- unifi
   |   `-- log
   |-- srv
   |   `-- unifi
   |       |-- bin
   |       |-- conf
   |       |-- data
   |       |-- dl
   |       |-- lib
   |       |-- logs
   |       |-- run
   |       `-- webapps
   |-- run
   |   `-- openrc
   |          `-- s6-scan
   |              `-- unifi --> /etc/unifi
    `-- var
        `-- log
            `-- unifi

Prerequisite Packages

OpenJDK 8 JRE

Install openjdk8-jre from the community repository.

Edit /etc/apk/repositories and uncomment the appropriate community repository for your Alpine version:

http://host.name/alpine_version/community

Update the package cache.

apk update

Install the package.

apk add openjdk8-jre

MongoDB

Install MongoDB

apk add mongodb

s6

Install s6

apk add s6 which is a service supervision suite, for reliably and efficiently starting, stopping and keeping services running.

The below shows a schematic process tree of how the UniFi Controller will be started and supervised by s6. The controller is written in Java, hence the Java process and it in turn, launches a dedicated instance of MongoDB to store its configuration and run-time data.

init
`-- s6-svscan
    `-- s6-supervise
        |-- s6-log
        `-- java
            `-- mongod

Install UniFi Controller

Create the unifi user and group.

adduser -D -H -h /srv/unifi unifi

Change to the parent folder within which you wish to install the UniFi Controller.

cd /srv

Download the generic unix archive of the VERSION you wish to install.

wget http://www.ubnt.com/downloads/unifi/VERSION/UniFi.unix.zip

Unpack the archive.

unzip UniFi.unix.zip

Rename the unpacked directory.

mv UniFi unifi

Change ownership.

chown -R unifi:unifi unifi

Lock down permissions.

chmod o-rwx unifi

Change into the UniFi bin directory.

cd /srv/unifi/bin

Remove the existing file.

rm mongod

Create a symlink to /usr/bin/mongod

ln -s /usr/bin/mongod

Configure Service Management

Create UniFi Service Directory and Files

Create an s6 service directory for UniFi.

mkdir -p /etc/unifi/log

Add the run script, using your favourite editor.

vim /etc/unifi/run

Copy and paste the following into it.

#!/bin/ash

user='unifi'
group='unifi'

exec 2>&1

base='/srv/unifi'

if [ -d $base ]; then
    cd $base
    chown -R $user:$group .
    version=`head -1 webapps/ROOT/app-unifi/.version`
    echo "Starting UniFi Controller $version"
    exec s6-setuidgid $user java -jar lib/ace.jar start
else
    echo "Missing $base ... aborting"
    touch down
fi

Ensure that the run script is executable:

chmod 755 /etc/unifi/run

Add the log/run script, using your favourite editor.

vim /etc/unifi/log/run

Copy and paste the following into it.

#!/bin/ash

log_user='log'

exec s6-setuidgid $log_user s6-log -b n20 s1000000 t /var/log/unifi

Ensure that the log/run script is executable:

chmod 755 /etc/unifi/log/run

Create log User and Directory

Create the log user and group.

adduser -D -H -h /var/log log

Create the /var/log/unifi directory

mkdir -p /var/log/unifi

Update the directory ownership.

chown log:log /var/log/unifi

Lock down the permissions.

chmod 750 /var/log/unifi

Create the OpenRC Service Script

Open the script file using your favourite editor.

vim /etc/init.d/unifi

Paste the following into it.

#!/sbin/openrc-run

name="unifi"
supervisor=s6
s6_service_path="${RC_SVCDIR}/s6-scan/${name}"

depend() {
	need net s6-svscan
	after firewall
}

start_pre() {
        if [ ! -L "${RC_SVCDIR}/s6-scan/${name}" ]; then
	        ln -s "/etc/${name}" "${RC_SVCDIR}/s6-scan/${name}"
	fi
}

Ensure that the script is executable.

chmod 755 /etc/init.d/unifi

Start the UniFi Controller Service

rc-service unifi start

Configure the UniFi Controller Service to start on boot

rc-update add unifi boot

Simple Backup Script

Create /usr/local/bin/unifi-backup using your favourite editor.

Note: This script assumes the use of s6-svc to control unifi. I will modify it in time, to use rc-service instead.

Paste the following into the file.

#!/bin/ash

conf_dir='/etc/unifi'
backup_dir='/srv/backup/unifi'
service_dir='/run/openrc/s6-scan/unifi'

start_state='down'

if s6-svok $service_dir; then
    if s6-svstat -o up,ready $service_dir | grep -q true; then
        echo 'Stopping the UniFi Controller'
        start_state='up'
        s6-svc -d $service_dir
        sleep 3
    fi
else
    echo 'Warning: The UniFi Controller is not supervised'
    exit 1
fi

if s6-svstat -o up $service_dir | grep -q false; then
    echo 'Success: The UniFi Controller was stopped'
else
    echo 'Error: The UniFi Controller is still running'
    exit 1
fi

stamp=`date +%Y-%m-%d_%H%M%S`

mkdir -p $backup_dir
cd $backup_dir
mkdir "data-$stamp"

echo "Backing up to /srv/backup/unifi/data-$stamp.tar.gz"

if rsync -az /srv/unifi/data/ "data-$stamp"; then
    echo '* rsync succeeded'
    if tar czf "data-$stamp.tar.gz" "data-$stamp"; then
        echo '* tar succeeded'
        rm -rf "data-$stamp"
        echo 'Backup succeeded'
    else
        echo 'Backup failed: tar failed'
	exit 1
    fi
fi

if [ "$start_state" == 'up' ]; then
    echo 'Starting the UniFi Controller'
    s6-svc -u $service_dir
    sleep 5
    s6-svstat $service_dir
fi