Knowledge Base
Infrastructure
2026-01-28
10 min

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.

GitHub Actions
CI/CD
ARM64
Docker
Buildx
Self-hosted Runners
Particle Tachyon
DevOps
Container Builds

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 ci and 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.
â„šī¸
This setup pairs extremely well with split-architecture pipelines where amd64 builds run on GitHub-hosted runners and arm64 builds run natively on 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.

âš ī¸
Critical: By default, workflows triggered by pull requests from forked repositories will execute on your self-hosted runner. Malicious actors can submit PRs containing code designed to compromise your network.

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.
â„šī¸
GitHub strongly recommends using self-hosted runners only with private repositories. Public repositories should use GitHub-hosted runners or dedicated, isolated infrastructure with no internal network access.

Network Isolation Example (UFW):

isolate-runner.sh
# 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
âš ī¸
This example is illustrative only. Proper network isolation requires VLAN segmentation, router ACLs, and careful consideration of your specific network topology and requirements.

👤Create a Dedicated Runner User

It is strongly recommended to run the GitHub Actions runner under a dedicated non-root system user.

create-runner-user.sh
sudo useradd -m -s /bin/bash gha-runner
sudo usermod -aG docker gha-runner
sudo passwd gha-runner

The 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.

âš ī¸
Ensure the user is added to the 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

install-docker.sh
curl -fsSL https://get.docker.com | sh
docker buildx install

Verify that Docker is functional and running natively on ARM64:

verify-docker.sh
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.

download-runner.sh
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
configure-runner.sh
./config.sh \
  --url https://github.com/<org>/<repo> \
  --token <TOKEN> \
  --name tachyon-arm64 \
  --labels arm64,tachyon,self-hosted
âš ī¸
Registration tokens expire after 1 hour. If configuration fails with an authentication error, generate a new token from the GitHub repository settings. Note that labels are case-sensitive and should match your workflow requirements.

âš™ī¸Install Runner as a System Service

Running the runner as a service ensures it survives reboots, SSH disconnects, and runs unattended.

install-service.sh
sudo ./svc.sh install gha-runner
sudo ./svc.sh start
check-status.sh
sudo ./svc.sh status
✅
Once installed as a service, the runner will automatically reconnect to GitHub and listen for jobs even after system reboots.

🧩Using the Runner in GitHub Actions

Reference the Tachyon runner using labels in your workflow:

arm64-job.yml
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:

setup-second-runner.sh
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.
â„šī¸
Check running services with 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 sha256 layers represent Docker filesystem layers being extracted.
  • Storage speed (eMMC vs NVMe) significantly affects extraction time.
  • Monitor /var/lib/docker disk usage regularly to prevent space exhaustion.
â„šī¸
Slow 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:

stop-service.sh
sudo ./svc.sh stop
sudo ./svc.sh uninstall
remove-runner.sh
./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.

â„šī¸
After removal, the runner directory and Docker images remain on disk. Manually delete the actions-runner directory and run docker system prune -a to reclaim space if needed.

Changelog

2026-01-28v1.0

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

Last updated: 2026-01-28