Setting Up a Native ARM64 GitHub Actions Runner on Tachyon
Complete guide to deploying a self-hosted GitHub Actions runner on a Particle Tachyon SBC for native ARM64 builds. Eliminates QEMU emulation overhead, dramatically improves Docker build performance, and enables fast multi-arch CI/CD pipelines with full control over caching and storage.
Running native ARM64 builds using GitHub Actions can dramatically improve build performance and reliability compared to QEMU-emulated environments. This guide documents how to set up a self-hosted GitHub Actions runner on a Particle Tachyon SBC for fast, native ARM64 Docker image builds.
By offloading ARM64 builds to dedicated ARM hardware, you eliminate emulation overhead, reduce CI build times, and gain full control over caching, storage, and performance characteristics.
đWhy Use a Self-Hosted ARM64 Runner?
- Avoids QEMU emulation entirely for ARM builds.
- Massively faster
npm ciand layer extraction. - Predictable performance and no GitHub runner throttling.
- Ideal for multi-arch Docker builds using
buildx. - Perfect fit for ARM SBCs like Particle Tachyon.
â Prerequisites
- Particle Tachyon SBC running Linux (ARM64).
- Docker installed and working.
- Outbound internet access to GitHub on port 443 (HTTPS).
- Repository admin access to register self-hosted runners.
đSecurity Considerations for Home Lab Runners
Self-hosted runners on internal networks introduce security risks that differ significantly from GitHub-hosted runners. Workflows execute arbitrary code with network access to your LAN and can persist state between runs.
Key Attack Vectors:
- Malicious PRs executing arbitrary code with LAN access.
- Compromised workflows exfiltrating repository secrets.
- Lateral movement to other devices on your network.
- Supply chain attacks via malicious npm/pip packages during builds.
- Persistent state allowing backdoors to survive across workflow runs.
Mitigation Strategies:
- Disable workflows from forks: Settings â Actions â Fork pull request workflows â Require approval for all outside collaborators.
- Use network segmentation: Place runners on an isolated VLAN with restricted egress.
- Implement firewall rules limiting runner access to only GitHub IPs and required services.
- Minimize secrets: Only grant runners access to secrets they absolutely need.
- Monitor runner activity: Log and alert on unexpected network connections.
- Regular audits: Review workflow files for suspicious commands or unexpected network calls.
Network Isolation Example (UFW):
# Allow only GitHub and DNS
sudo ufw default deny outgoing
sudo ufw allow out 443/tcp
sudo ufw allow out 53
sudo ufw enable
# Block lateral movement to common internal services
sudo ufw deny out to 192.168.0.0/16
sudo ufw deny out to 10.0.0.0/8đ¤Create a Dedicated Runner User
It is strongly recommended to run the GitHub Actions runner under a dedicated non-root system user.
sudo useradd -m -s /bin/bash gha-runner
sudo usermod -aG docker gha-runner
sudo passwd gha-runnerThe passwd command will prompt you to set a password for the new user, which is required to switch to this account using su - gha-runner.
docker group, otherwise Docker builds will fail at runtime. Alternatively, you can use sudo -u gha-runner -i to switch users without requiring a password.đŗInstall Docker & Buildx
curl -fsSL https://get.docker.com | sh
docker buildx installVerify that Docker is functional and running natively on ARM64:
docker version
docker buildx version
uname -mđRegister the GitHub Actions Runner
In your GitHub repository, navigate to:
Settings â Actions â Runners â New self-hosted runner
Select Linux and ARM64, then follow the registration instructions.
su - gha-runner
mkdir actions-runner && cd actions-runner
curl -L -o actions-runner.tar.gz https://github.com/actions/runner/releases/latest/download/actions-runner-linux-arm64.tar.gz
tar xzf actions-runner.tar.gz./config.sh \
--url https://github.com/<org>/<repo> \
--token <TOKEN> \
--name tachyon-arm64 \
--labels arm64,tachyon,self-hostedâī¸Install Runner as a System Service
Running the runner as a service ensures it survives reboots, SSH disconnects, and runs unattended.
sudo ./svc.sh install gha-runner
sudo ./svc.sh startsudo ./svc.sh statusđ§ŠUsing the Runner in GitHub Actions
Reference the Tachyon runner using labels in your workflow:
runs-on: [self-hosted, arm64, tachyon]This allows ARM64 jobs to run natively, while amd64 jobs can remain on GitHub-hosted runners.
đRunning Multiple Runners for Different Repositories
A single Tachyon can host multiple GitHub Actions runners for different repositories, enabling centralized ARM64 build infrastructure for multiple projects.
Each runner requires its own directory and systemd service. The process is identical to the initial setup, with directory and label variations:
su - gha-runner
mkdir actions-runner-repo2 && cd actions-runner-repo2
curl -L -o actions-runner.tar.gz https://github.com/actions/runner/releases/latest/download/actions-runner-linux-arm64.tar.gz
tar xzf actions-runner.tar.gz
./config.sh \
--url https://github.com/<org>/<repo2> \
--token <TOKEN> \
--name tachyon-arm64-repo2 \
--labels arm64,tachyon,self-hosted,repo2
sudo ./svc.sh install gha-runner
sudo ./svc.sh start- Each runner gets its own directory:
actions-runner-repo2,actions-runner-repo3, etc. - Use distinct runner names and labels to identify which runner serves which repository.
- Each runner installs as a separate systemd service automatically.
- Runners share the same Docker daemon and layer cache, improving efficiency.
- No port conflicts â runners only use outbound HTTPS connections.
systemctl list-units | grep actions.runner. Each runner appears as a separate service (e.g., actions.runner.repo1.service, actions.runner.repo2.service).Resource Considerations:
- Monitor CPU and memory usage - concurrent builds can saturate resources.
- Disk space consumption scales with the number of active repositories and images.
- Consider limiting concurrent jobs per repository using GitHub Actions settings.
- Shared Docker layer cache benefits builds across all runners.
âĄPerformance Notes
- First ARM64 builds will be slower due to cold Docker layer pulls.
- Subsequent builds benefit from local layer and npm cache reuse.
- Large
sha256layers represent Docker filesystem layers being extracted. - Storage speed (eMMC vs NVMe) significantly affects extraction time.
- Monitor
/var/lib/dockerdisk usage regularly to prevent space exhaustion.
sha256 extraction during early builds is expected and indicates Docker laying down base image and dependency layers. Use docker system df and docker system prune to manage disk space as images accumulate.đī¸Removing or Unregistering the Runner
If you need to decommission the runner or move it to a different repository, follow these steps:
sudo ./svc.sh stop
sudo ./svc.sh uninstall./config.sh remove --token <REMOVAL_TOKEN>The removal token can be generated from the same GitHub repository settings page where you initially registered the runner.
actions-runner directory and run docker system prune -a to reclaim space if needed.Changelog
Initial release documenting native ARM64 GitHub Actions runner setup on Particle Tachyon SBC.
Filed under: GitHub Actions, CI/CD, ARM64, Docker, Buildx, Self-hosted Runners, Particle Tachyon