This is a follow up to Cross-compiling ZeroTier for arm64 Ubiquiti Devices. There was some interest in the comments to generate the Ubiquiti binaries and distribute; but I didn’t want to share the binaries without the source. Since I had all the steps outlined from the previous blog post and just needed it to get it in the GitHub Actions format, I decided to take the opportunity to try out AI to help automate the process. I settled with using ChatGPT, which was using the GPT-5 model.
The final output is below, and hopefully self explanatory. It’s also on GitHub, but on a temporary branch. Please feel free to amend and use in your own fork:
# Injabie3 - 2025-10-23
# Ubiquiti build script for ZeroTier
#
# This GitHub Action is based on the steps from the following blog post:
# https://blog.injabie3.moe/2024/02/23/cross-compiling-zerotier-for-ubiquiti-devices
#
name: Cross-compile ZeroTier for Ubiquiti (arm64)
on:
push:
branches: [dev]
workflow_dispatch:
jobs:
build-arm64:
name: Build and package ZeroTier (arm64)
runs-on: ubuntu-latest
env:
CC: aarch64-linux-gnu-gcc
CXX: aarch64-linux-gnu-g++
ZT_UBIQUITI: '1'
steps:
- name: π Checkout source
uses: actions/checkout@v3
- name: π¦ Install dependencies
run: |
sudo dpkg --add-architecture arm64
# Add Ubuntu Ports repository for ARM64 only
sudo tee /etc/apt/sources.list.d/arm64.list <<'EOF'
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
EOF
# Update ignoring missing arm64 indices from default mirrors
sudo apt-get update -o Acquire::Retries=3 || true
sudo apt-get install -y \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
make \
dpkg-dev fakeroot \
devscripts build-essential lintian debhelper \
libstdc++6 \
libstdc++6-arm64-cross \
libstdc++6-amd64-cross \
libc6-arm64-cross \
libc6-amd64-cross \
libgcc-s1 \
libgcc-s1-arm64-cross \
libgcc-s1-amd64-cross \
libc6:arm64 \
libstdc++6:arm64 \
libgcc-s1:arm64
- name: π§ Patch make-linux.mk to disable SSO
run: |
sed -i 's/^\(.*ZT_SSO_SUPPORTED=\)1/\10/' make-linux.mk
- name: π§± Build and package (.deb) using Makefile
run: |
CC=${CC} CXX=${CXX} ZT_UBIQUITI=${ZT_UBIQUITI} ZT_STATIC=1 make debian
- name: π Move generated artifacts into workspace
run: |
find .. -maxdepth 1 -name "*arm64.*" -exec mv {} . \;
- name: π§© Recompress .deb to xz
run: |
set -e
DEB_FILE=$(ls ./*.deb | head -n1)
mkdir repack && cd repack
# Extract components
ar x "../$DEB_FILE"
# Recompress zstd β xz
if [ -f control.tar.zst ]; then
zstd -d < control.tar.zst | xz > control.tar.xz
fi
if [ -f data.tar.zst ]; then
zstd -d < data.tar.zst | xz > data.tar.xz
fi
# Recreate the package
ar -m -c -a sdsd "../${DEB_FILE%.deb}-xz.deb" debian-binary control.tar.xz data.tar.xz
# Cleanup
cd ..
rm -rf repack
- name: π· Set metadata for artifact
id: vars
run: |
echo "short_sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
echo "date_tag=$(date +'%Y%m%d')" >> "$GITHUB_OUTPUT"
- name: π€ Upload .deb package
uses: actions/upload-artifact@v4
with:
name: zerotier-arm64-${{ steps.vars.outputs.date_tag }}-${{ steps.vars.outputs.short_sha }}-deb
path: '*-xz.deb'
- name: π€ Upload debug artifacts
uses: actions/upload-artifact@v4
with:
name: zerotier-arm64-${{ steps.vars.outputs.date_tag }}-${{ steps.vars.outputs.short_sha }}-debug
path: '*arm64.*'
I basically gave it the link to my blog post, and it almost got all the way there. Getting the build to actually work took some time, because the environment was slightly different than my actual laptop. I had to figure out the missing dependencies to install in the Actions build environment, and that took a bunch of back and forth to massage within ChatGPT. Honestly, I’m pretty impressed at how AI can be used a tool to execute on things. I may explore this area a bit more since we’re also exploring how we can use AI tools at work to help automate or augment our existing workflows.

There’s still quite a lot to improve on, but it does generate the artifacts: I did get it loaded and running on my Ubiquiti Dream Router, and it’s working fine.
Anyways, that’s all I got this time around.
Until next time!
~Lui

Incase it helps anyone the Debian arm64 build for bullseye installs and works perfectly for me on my Unifi Dream Machine on latest updates. No need to compile.
https://download.zerotier.com/dist/debian/bullseye/zerotier-one_1.16.0-2_arm64.deb
With the help of Gemini I made a script to run at boot to install zerotier if needed, move it’s config folder to persistent storage and start zerotier (it should hopefully survive upgrades).
***Please note I am not an experienced coder, just a willing tinkerer so please check the code and use at your own risk***
***I would really appreciate any feedback on improving my logic***
Script located here: https://pastebin.com/Zm6KU2yV
To update zerotier with this script you need to change the variable PACKAGE_URL to the new build and run the script with the -u or –update argument
The script is to be located at: “/data/on_boot.d/10-zerotier.sh” which uses boostchickens on-boot-scripts from here:
https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script
Have been following your progress on getting zerotier running on unifi devices.
Incase it helps anyone the Debian arm64 build for bullseye installs and works perfectly for me on my Unifi Dream Machine on latest updates. No need to compile.
https://download.zerotier.com/dist/debian/bullseye/zerotier-one_1.16.0-2_arm64.deb
With the help of Gemini I made a script to run at boot to install zerotier if needed, move it’s config folder to persistent storage and start zerotier (it should hopefully survive upgrades).
***Please note I am not an experienced coder, just a willing tinkerer so please check the code and use at your own risk***
***I would really appreciate any feedback on improving my logic***
Script located here: https://pastebin.com/Zm6KU2yV
To update zerotier with this script you need to change the variable PACKAGE_URL to the new build and run the script with the -u or –update argument
The script is to be located at: “/data/on_boot.d/10-zerotier.sh” which uses boostchickens on-boot-scripts from here:
https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script
Thanks for sharing your experience, yeah I noticed the Debian arm64 builds last time after I decided to tinker as well!