How to SSL/TLS on UniFi Controller with bashscript + acme.sh & matrix.sh notifications
Setup acme.sh Cert
Open Port 80 on your NAT firewall first to forward to 2280 on your mashine:
acme.sh --issue --standalone -d my.domain.com --httpport 2280 --reloadcmd "/usr/bin/unifi-contr-ssl.sh" --force --log
# You can find the cmdreload command at: $ssldir/your.domain.com.*.conf
# decode B64 with:
echo "L3Vzci9iaW4vdW5pZmktY29udHItc3NsLnNo" | base64 -d -i -w0; echo
# with Bash
base64 -d <(echo -e "L3Vzci9iaW4vdW5pZmktY29udHItc3NsLnNo");echo
Create, setup and run => unifi-contr-ssl.sh
#!/bin/bash
# (c) 2022 - suuhmer
# setup script unifi controller ssl
#
# just setup first with acme.sh / etc. new cert(s):
# setup Destination NAT 80 > 2280
# acme.sh --issue --standalone -d my.domain.com --httpport 2288 --reloadcmd "/usr/bin/unifi-contr-ssl.sh" --force --log
#
# maybe helpful for cron install:
# ------------------------------------------------------------------------------------------------
# --cert-file <file> Path to copy the cert file to after issue/renew..
# --key-file <file> Path to copy the key file to after issue/renew.
# --ca-file <file> Path to copy the intermediate cert file to after issue/renew.
# --fullchain-file <file> Path to copy the fullchain cert file to after issue/renew.
# --reloadcmd <command> Command to execute after issue/renew to reload the server.
MYDOMAIN="my.domain.com"
NEWCERTS=/etc/ssl/private
PKEY="$NEWCERTS/$MYDOMAIN.key"
echo "Copy certs and rename new Unifi private key"
cp /root/.acme.sh/$MYDOMAIN/* $NEWCERTS
mv $PKEY $NEWCERTS/Unifi.key
echo "Stopping now UniFi Controllers"
service unifi stop
sleep 2; echo "backup original keystore"
mv /var/lib/unifi/keystore /var/lib/unifi/keystore.`date "+%Y%m%d-%H%m%S"`
echo "convert chain to appropriate format"
openssl pkcs12 -export -inkey $NEWCERTS/Unifi.key -in $NEWCERTS/fullchain.cer -out $NEWCERTS/cert.p12 -name unifi -password pass:temppass
echo "import cert chain => to keystore"
keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore /var/lib/unifi/keystore -srckeystore $NEWCERTS/cert.p12 -srcstoretype PKCS12 -srcstorepass temppass -alias unifi -noprompt
echo "cleanup"
#rm $NEWCERTS/root.crt $NEWCERTS/Unifi.crt $NEWCERTS/Unifi.key $NEWCERTS/fullchain.crt $NEWCERTS/cert.p12
echo "Start UniFi Controller"
service unifi start
#echo "del old jks
#rm unifi.keystore.jks
#echo "convert => pkcs12
#openssl pkcs12 -export -in cloudkey.crt -inkey cloudkey.key -out unifi.p12 -name unifi -password pass:aircontrolenterprise
#echo "JKS erstellen
#keytool -importkeystore -srckeystore unifi.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -destkeystore unifi.keystore.jks -storepass aircontrolenterprise
#echo "del old p12"
#rm unifi.p12
exit 0
Setup matrix.sh
Config matrix.sh
Or the easy way via:
# User you want to use as your matrix send bot/user:
matrix-send.sh --login
# Enter the room you're ivited or you want to join:
matrix-send.sh --select-default-room
Setup acme => matrix notifications:
Create: .acme.sh/account.conf
cat << EOF > .acme.sh/account.conf
LOG_FILE='/root/.acme.sh/acme.sh.log'
#LOG_LEVEL=1
#AUTO_UPGRADE="1"
#NO_TIMESTAMP=1
ACCOUNT_EMAIL='info@mymail.com'
USER_PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
#UPGRADE_HASH='xxx'
NOTIFY_HOOK='customscript'
NOTIFY_LEVEL='2'
NOTIFY_MODE='0'
SAVED_CUSTOMSCRIPT_PATH='/usr/local/bin/acme-notification.sh'
EOF
Create: /usr/local/bin/acme-notification.sh
cat << EOF > /usr/local/bin/acme-notification.sh
#!/usr/bin/env bash
subject="$1"
message="$2"
status="$3"
#do-something "$subject ($status): $message"
#echo "$subject ($status): $message" | matrix-send.sh -
matrix-send.sh --html "Hello ACME friend ;)<h3>$subject - <u>Status: ($status):</u></h3><br/><strong>$message</strong><br/><i>bye :)</i>"
#echo -e "Hello ACME $subject \n($status): $message \nbye :)." | matrix-send.sh -pre -
EOF
Using my acme.sh notify script:
#!/usr/bin/env sh
#Support matrix via matrix.sh
#MATRIX_BIN="/usr/bin/matrix-send.sh"
#MATRIX_BIN_ARGS="--html -"
#MATRIX_TO="zzzz@example.com"
matrix_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_subject" "$_subject"
_debug "_content" "$_content"
_debug "_statusCode" "$_statusCode"
MATRIX_BIN="${MATRIX_BIN:-$(_readaccountconf_mutable MATRIX_BIN)}"
if [ -n "$MATRIX_BIN" ] && ! _exists "$MATRIX_BIN"; then
_err "It seems that the command $MATRIX_BIN is not in path."
return 1
fi
_MATRIX_BIN=$(_matrix_bin)
if [ -n "$MATRIX_BIN" ]; then
_saveaccountconf_mutable MATRIX_BIN "$MATRIX_BIN"
else
_clearaccountconf "MATRIX_BIN"
fi
MATRIX_BIN_ARGS="${MATRIX_BIN_ARGS:-$(_readaccountconf_mutable MATRIX_BIN_ARGS)}"
if [ -n "$MATRIX_BIN_ARGS" ]; then
_saveaccountconf_mutable MATRIX_BIN_ARGS "$MATRIX_BIN_ARGS"
else
_clearaccountconf "MATRIX_BIN_ARGS"
fi
result=$({ _matrix_message | eval "$(_matrix_cmnd)"; } 2>&1)
if [ $? -ne 0 ]; then
_debug "matrix send error."
_err "$result"
return 1
fi
_debug "matrix send success."
return 0
}
_matrix_bin() {
if [ -n "$MATRIX_BIN" ]; then
_MATRIX_BIN="$MATRIX_BIN"
elif _exists "matrix-send.sh"; then
_MATRIX_BIN="matrix-send.sh"
else
_err "Please install matrix-send.sh first."
return 1
fi
echo "$_MATRIX_BIN"
}
_matrix_cmnd() {
case $(basename "$_MATRIX_BIN") in
matrix-send.sh)
echo "'$_MATRIX_BIN' $MATRIX_BIN_ARGS"
;;
*)
_err "Command $MATRIX_BIN is not supported, use matrix.sh."
return 1
;;
esac
}
_matrix_message() {
echo "<b>[ACME.SH] $_subject</b><br/><br/>$_contains<br/>Status: ($_statusCode)"
}
_matrix_valid() {
_contains "$1" "@"
}
# Installing matrix hook
acme.sh --set-notify --notify-hook matrix