Due to how macvlan networking works, the Firewalla host cannot directly communicate with containers on the macvlan network. This is a Linux kernel limitation, not a Docker issue.
If you need to access the UniFi Controller from Firewalla itself (for health checks, API calls, or direct access), you can create a "shim" interface.
We create a secondary macvlan interface on the host and assign it an IP on the same subnet. This gives Firewalla a "side door" to communicate with the containers.
-
Choose an IP for the shim interface (e.g., 192.168.240.254)
-
Create the shim interface manually (for testing):
sudo ip link add unifi-shim link br0 type macvlan mode bridge
sudo ip addr add 192.168.240.254/32 dev unifi-shim
sudo ip link set unifi-shim up
sudo ip route add 192.168.240.2/32 dev unifi-shimNote: MongoDB runs on an internal Docker network and doesn't need a route.
- Test connectivity:
ping -c 3 192.168.240.2
curl -k https://192.168.240.2:8443Add the shim setup to your startup script. Edit /home/pi/.firewalla/config/post_main.d/start_unifi.sh:
#!/bin/bash
sudo systemctl start docker
sleep 5
cd /home/pi/.firewalla/run/docker/unifi
sudo docker-compose up -d
# Create shim interface for host access to UniFi Controller
sleep 10
sudo ip link add unifi-shim link br0 type macvlan mode bridge 2>/dev/null || true
sudo ip addr add 192.168.240.254/32 dev unifi-shim 2>/dev/null || true
sudo ip link set unifi-shim up 2>/dev/null || true
sudo ip route add 192.168.240.2/32 dev unifi-shim 2>/dev/null || trueOnce the shim is in place, you can create health checks. Save as /home/pi/.firewalla/run/docker/unifi/healthcheck.sh:
#!/bin/bash
# UniFi Controller Health Check
# Returns 0 if healthy, 1 if unhealthy
CONTROLLER_IP="192.168.240.2"
# Check if containers are running
UNIFI_RUNNING=$(docker inspect -f '{{.State.Running}}' unifi 2>/dev/null)
MONGO_RUNNING=$(docker inspect -f '{{.State.Running}}' unifi-db 2>/dev/null)
if [ "$UNIFI_RUNNING" != "true" ]; then
echo "CRITICAL: UniFi container not running"
exit 1
fi
if [ "$MONGO_RUNNING" != "true" ]; then
echo "CRITICAL: MongoDB container not running"
exit 1
fi
# Check if controller responds (requires shim interface)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -k --max-time 10 "https://${CONTROLLER_IP}:8443" 2>/dev/null)
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 400 ]; then
echo "OK: UniFi Controller healthy (HTTP $HTTP_CODE)"
exit 0
else
echo "WARNING: UniFi Controller returned HTTP $HTTP_CODE"
exit 1
fiMake it executable:
chmod +x /home/pi/.firewalla/run/docker/unifi/healthcheck.shTo run health checks periodically and log results:
# Add to crontab (crontab -e)
*/5 * * * * /home/pi/.firewalla/run/docker/unifi/healthcheck.sh >> /data/unifi/healthcheck.log 2>&1If you need to remove the shim interface:
sudo ip link delete unifi-shimAnd remove the shim-related lines from start_unifi.sh.
With the shim in place, you can access the UniFi API from Firewalla:
# Get a login cookie
curl -k -c /tmp/unifi-cookie -b /tmp/unifi-cookie \
-d '{"username":"admin","password":"yourpassword"}' \
-H "Content-Type: application/json" \
https://192.168.240.2:8443/api/login
# Query devices
curl -k -c /tmp/unifi-cookie -b /tmp/unifi-cookie \
https://192.168.240.2:8443/api/s/default/stat/deviceEnsure the shim commands are in /home/pi/.firewalla/config/post_main.d/start_unifi.sh and the script is executable.
This is normal — it means the interface/route already exists. The 2>/dev/null || true suppresses these.
Verify the shim is up:
ip addr show unifi-shim
ip route | grep unifi-shim