Skip to content

UDM Boot Scripts

The UDM root filesystem is an overlay. Writes to /etc survive reboots but are wiped by firmware upgrades, and /run is tmpfs. /data is a real partition that survives both, so anything custom lives there as a boot script, run by the udm-boot service from unifi-utilities/unifi-common (UniFi OS 4.x+).

Installing udm-boot

Warning

Never pipe a remote script directly into your shell. Download it, read it, and only then run it.

curl -fsL "https://raw.githubusercontent.com/unifi-utilities/unifi-common/HEAD/remote_install.sh" -o remote_install.sh
less remote_install.sh
/bin/bash remote_install.sh

After every firmware upgrade

The service unit itself sits on the overlay, so a firmware upgrade can remove it while the scripts in /data/on_boot.d remain. After an upgrade, check systemctl is-enabled udm-boot and rerun the installer if needed.

ECMP flow hashing

Makes the UDM hash on L4 ports as well as IPs, so connections spread across all BGP ECMP next-hops.

/data/on_boot.d/30-ecmp-l4-hash.sh
#!/bin/sh
echo "net.ipv4.fib_multipath_hash_policy = 1" > /etc/sysctl.d/30-ecmp-l4-hash.conf
sysctl -w net.ipv4.fib_multipath_hash_policy=1

The sysctl.d drop-in covers reboots by itself. The boot script recreates it after firmware upgrades.

HTTP/3 HTTPS records

Publishes the HTTPS records described in DNS → HTTP/3 discovery. The main dnsmasq instance loads --conf-dir=/run/dnsmasq.dhcp.conf.d/, which is tmpfs and regenerated by ubios-udapi-server.

/data/on_boot.d/40-dnsmasq-https-rr.sh
#!/bin/sh
CONF_DIR=/run/dnsmasq.dhcp.conf.d
for i in $(seq 1 30); do [ -d "$CONF_DIR" ] && break; sleep 2; done
[ -d "$CONF_DIR" ] || exit 0
cat > "$CONF_DIR/custom.conf" <<RR
dns-rr=external.bykaj.app,65,00010000010006026833026832
dns-rr=internal.bykaj.app,65,00010000010006026833026832
RR
[ -f /run/dnsmasq-main.pid ] && kill "$(cat /run/dnsmasq-main.pid)" 2>/dev/null
exit 0

Killing the main dnsmasq is safe. ubios-udapi-server respawns it with the new config.

Note

A provisioning event in the Network app can regenerate the conf dir and drop custom.conf until the next reboot. Rerunning the script puts it back.