MeidokonWiki:

I almost just want to buy a cloud key because I think it'll be easier. -_-

Now hosted on kubernetes

Yeah it used to be a docker container on illustrious, now I've deployed it on the persica cluster instead. In the process I upgraded from v7.4.162 to v8.2.93 using the excellent linuxserver.io containers.

It works well, and thanks to using MetalLB I can forward all the traffic to the node running the workload, will the dozen or so ports that it wants to use.

Via: https://hub.docker.com/r/linuxserver/unifi-network-application

Deployment notes

This new version now uses an external MongoDB instance, so you have to run that yourself. I just made it another pod in the unifi namespace.

  1. Dump a backup of the old config from the old instance, I was able to grab 60 days of history (it'd just hang if I asked for more).
  2. Start the new controller and import that backup dump from the landing page. Give it 5-10min then it'll be up and running.
  3. Unifi controller is now running on a new (MetalLB) IP address, so update the DNS entry for unifi.thighhighs.top to point to that, and wait about 5min for it to propagate.
  4. All the APs and switches should now be talking to the new controller.

And that's about it! Remarkably easy.

TLS cert for unifi

This is one thing we need to do again, by default the controller generates its own self-signed cert, and we want to use a real one. Because this is a Java app, it does everything itself and stores the key and cert in a Java keystore, so we have to deal with that pain in the arse.

Faff with the keystore so you can jam in your publicly signed cert. This is a script that I found and adapted.

The process goes something like this:

  1. Convert your normal PEM-format cert into a PKCS12 container, I don't understand all this but it works. You do this outside the container, on your workstation or whatever.
  2. Copy the resultant .p12 file into the pod. It's not necessary, but we'll leave it on the persistent volume that the Unifi controller uses.

  3. Using the magic Java tools, import the p12 cert into the keystore.
  4. Restart the Unifi controller so it picks up the new cert.

This has been adapted from a previous local docker setup, but it should work fine in k8s.

Convert the cert from PEM to p12

This assumes you're keeping the cert in /etc/ssl/ or similar, we'll put the p12 in there as well.

# Hacked together by Barney Desmond on 2022-11-03
# Updated again on 2024-06-29
#
# Convert cert to PKCS12 format
# Ignore warnings
# Turns out we need to enable legacy mode, because Unifi's keytool can't read
# the new OpenSSL 3.0.2 encryption.
# https://community.ui.com/questions/New-Openssl-v3-may-break-your-controller-network-application-keystore/2e4133d9-d6dd-4a22-acfe-e5d671ffaee4
openssl pkcs12 -export -legacy \
        -inkey /etc/ssl/STAR_thighhighs_top.key \
        -in    /etc/ssl/STAR_thighhighs_top.crt \
        -out   /etc/ssl/STAR_thighhighs_top.p12 \
        -name unifi -password pass:unifi

cat <<EOF
Now go copy the p12 file into the Unifi controller container/PVC. Then we'll
import the cert into the keystore, from inside the running container.
EOF

Copy the p12 cert into the k8s pod

I'm sure there's sensible ways to do this, I personally think it's just easiest to copypasta the thing in via base64.

base64 STAR_thighhighs_top.p12

# get a shell into the container
kubectl -n unifi exec deployment.apps/network -it -- /bin/bash

# you'll be dropped in /usr/lib/unifi but your persistent volume is mapped to /config
# `data` is a symlink to /config/data so we can cd to that
cd /config/data/

# pump the cert into a file
cat <<EOF | base64 -d > STAR_thighhighs_top.p12
  ... paste the base64 encoded .p12 cert here ...
EOF

Your cert is now sitting in the pod at /config/data/STAR_thighhighs_top.p12

Import the p12 cert into the Java keystore

Create this script inside the same directory, you only need to do this once as it'll stick around for future certificate renewals. You can pipe it into a file with the shell, or install an editor with apt update ; apt install -y vim-tiny

# This is unifi-import-cert.sh

# From https://util.wifi.gl/unifi-import-cert.sh which is now dead
# Modified by Barney Desmond on 2021-04-20 to just use a normal static paid-for cert.

# Author: Frank Gabriel, 01.01.2019
# Credits Kalle Lilja, @SprockTech and others
# Script location: /etc/letsencrypt/renewal-hooks/post/unifi-import-cert.sh (important for auto renewal)
# Tested with Debian 9 and UniFi 5.8.28, 5.9.22 and 5.9.32 - should work with any recent Unifi and Ubuntu/Debian releases

# This is where the keystore lives inside the container
UNIFI_DATADIR=/config/data

# Backup previous keystore
cp -av "${UNIFI_DATADIR}/keystore" "${UNIFI_DATADIR}/keystore.backup.$(date +%F_%R)"

# Install certificate
# Ignore warnings
keytool -importkeystore \
        -deststorepass aircontrolenterprise \
        -destkeypass aircontrolenterprise \
        -destkeystore "${UNIFI_DATADIR}/keystore" \
        -srckeystore STAR_thighhighs_top.p12 \
        -srcstoretype PKCS12 \
        -srcstorepass unifi \
        -alias unifi \
        -noprompt

Now run the script to do the import:

root@network-6d6b5b85f6-qp4k8:/config/data# ./unifi-import-cert.sh
'/config/data/keystore' -> '/config/data/keystore.backup.2024-06-29_02:29'
Importing keystore STAR_thighhighs_top.p12 to /config/data/keystore...
Warning: Overwriting existing alias unifi in destination keystore

Exit the shell from the pod, you're done.

Restart the pod

The cert is imported but not yet active. Restart the service to pick it up, deleting the pod is usually the easiest way.

kubectl -n unifi delete pod -l app=unifi-network-application,tier=web

MeidokonWiki: UnifiController (last edited 2024-06-28 16:40:41 by furinkan)