I have registered an account to provide solution to this problem.
This solution allowed the usage of mDNS to remain enabled without the need to set Homebridge app to be on host network, while allow it to be registered with Home app
The problem with Homebridge being inaccessible is due to two issues:
1. Homebridge cannot broadcast itself to the outside
container is not allowed to advertise its own HAP mDNS record to the host.
TrueNAS SCALE uses Avahi as its mDNS stack.
if container is not allowed to advertise itself, then we just have to add the mDNS entry into it.
2. Homebridge cannot respond to the incoming verification Homekit request
container broadcast port is not exposed outside of the container. To fix this, we simply create a k8s nodeport service to remedy this situation.
This bring us to the following script below:
Code:
#!/bin/bash
set -euo pipefail
APP_NAME=$1
NAMESPACE=ix-${APP_NAME}
POD_NAME=$(k3s kubectl get po -n ix-${APP_NAME} -n ${NAMESPACE} -o name | grep "pod/${APP_NAME}" | cut -d '/' -f 2)
MAIN_CONFIG=$(k3s kubectl exec -it -n ${NAMESPACE} ${POD_NAME} -c ${APP_NAME} -- cat /homebridge/config.json)
BRIDGE_NAME=$(echo "${MAIN_CONFIG}" | jq -r .bridge.name)
BRIDGE_MAC=$(echo "${MAIN_CONFIG}" | jq -r .bridge.username)
BRIDGE_BROADCAST_PORT=$(echo "${MAIN_CONFIG}" | jq -r .bridge.port)
OCCUPIED_PORT=$(k3s kubectl get svc --all-namespaces -o go-template='{{range .items}}{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\n"}}{{end}}{{end}}{{end}}' | grep ${BRIDGE_BROADCAST_PORT})
if [ "${OCCUPIED_PORT}" != "" ]; then
echo "port ${OCCUPIED_PORT} is already occupied, please change port specified before retrying.."
exit 1
fi
ACCESSORY_CONFIG=$(k3s kubectl exec -it -n ${NAMESPACE} ${POD_NAME} -c ${APP_NAME} -- cat /homebridge/persist/AccessoryInfo.${BRIDGE_MAC//:/}.json)
BRIDGE_SETUP_ID=$(echo "${ACCESSORY_CONFIG}" | jq -r .setupID)
BRIDGE_CATEGORY=$(echo "${ACCESSORY_CONFIG}" | jq -r .category)
# creating avahi servicec entry to allow pod to react to mDNS request
cat <<EOF > "/etc/avahi/services/${APP_NAME}.service"
<service-group>
<name>${BRIDGE_NAME}</name>
<service>
<type>_hap._tcp</type>
<port>${BRIDGE_BROADCAST_PORT}</port>
<txt-record>md=${BRIDGE_NAME}</txt-record>
<txt-record>pv=1.0</txt-record>
<txt-record>id=${BRIDGE_MAC}</txt-record>
<!-- Current configuration number -->
<txt-record>c#=2</txt-record>
<txt-record>ci=${BRIDGE_CATEGORY}</txt-record>
<txt-record>s#=1</txt-record>
<txt-record>ff=0</txt-record>
<txt-record>sf=1</txt-record>
<txt-record>sh=$(echo -n ${BRIDGE_SETUP_ID}${BRIDGE_MAC} | openssl dgst -binary -sha512 | head -c 4 | base64)</txt-record>
</service>
</service-group>
EOF
# creating service to allow outside to reach into the pod
cat <<EOF | k3s kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: ${APP_NAME}-exposed
namespace: ${NAMESPACE}
labels:
app: ${APP_NAME}
spec:
type: NodePort
selector:
app.kubernetes.io/instance: ${APP_NAME}
ports:
- port: ${BRIDGE_BROADCAST_PORT}
nodePort: ${BRIDGE_BROADCAST_PORT}
EOF
save the script to a file called
homebridge-fix.sh
give it execute permission via
Code:
chmod +x homebridge-fix.sh
Execute the script by providing
Homebridge App Name (the name used when you created the Homebridge app) as the only parameter like so
Code:
./homebridge-fix.sh <homebridge_app_name>
use
Code:
service avahi-daemon status
to verify Avahi has picked up the mDNS entry before attempting to register bridge with iOS Home app (shouldn't take more than 1 min)
now you can add any device to your homebridge.