Skip to main content

Custom Runners Setup Guide

Note: The P6M action library is designed to work with standard GitHub-hosted runners out of the box. The instructions in this guide (and the ARM guide) are provided for scenarios where custom runners or ARM64-specific runners are required for enhanced performance, security, or architecture-specific needs.

The P6M platform requires specialized GitHub Actions runners with specific toolchains and configurations that exceed standard GitHub-hosted runner capabilities. Our multi-language workflows demand runners equipped with Docker, .NET, Java, JavaScript, Python, and Rust toolchains, while multi-platform Docker builds require native ARM64 runners for optimal performance. This guide provides the complete setup process for provisioning custom runners that meet these platform requirements, including automated installation scripts and architecture-specific configurations.

Core Dependencies

1. Git

Required by: All actions (version control operations)

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y git

# macOS
brew install git

# Windows
winget install Git.Git

2. GitHub CLI

Required by: repository-release

# Ubuntu/Debian
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh

# macOS
brew install gh

# Windows
winget install GitHub.cli

Technology Stack Requirements

Docker Stack

Required by: docker-buildx-setup, docker-repository-login, dotnet-docker-publish, js-pnpm-docker-build-publish, python-uv-docker-publish

Docker Engine

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y docker.io docker-compose-plugin

# macOS
brew install docker docker-compose

# Windows
winget install Docker.DockerDesktop

Docker Buildx

# Usually included with Docker Desktop
# For manual installation:
docker buildx install

.NET Stack

Required by: dotnet-build, dotnet-cut-tag, dotnet-docker-publish, dotnet-repository-login, dotnet-repository-publish

.NET SDK

# Ubuntu/Debian
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y dotnet-sdk-8.0

# macOS
brew install dotnet

# Windows
winget install Microsoft.DotNet.SDK.8

Java Stack

Required by: java-maven-cut-tag

Java JDK 21

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y openjdk-21-jdk

# macOS
brew install openjdk@21

# Windows
winget install Eclipse.Temurin.21.JDK

Maven

# Ubuntu/Debian
sudo apt-get install -y maven

# macOS
brew install maven

# Windows
winget install Apache.Maven

JavaScript/Node.js Stack

Required by: js-pnpm-build, js-pnpm-cut-tag, js-pnpm-docker-build-publish, js-pnpm-setup

Node.js

# Ubuntu/Debian
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# macOS
brew install node@18

# Windows
winget install OpenJS.NodeJS

pnpm

# After Node.js installation
npm install -g pnpm

# Or via curl
curl -fsSL https://get.pnpm.io/install.sh | sh -

Python Stack

Required by: python-uv-build, python-uv-cut-tag, python-uv-docker-publish, python-uv-setup, python-uv-repository-login, python-uv-repository-publish, python-poetry-login, python-poetry-setup

Python

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-venv

# macOS
brew install python@3.12

# Windows
winget install Python.Python.3.12

UV (Modern Python Package Manager)

# All platforms
curl -LsSf https://astral.sh/uv/install.sh | sh

# Or via pip
pip install uv

Poetry

# Via pipx (recommended)
pipx install poetry

# Or via curl
curl -sSL https://install.python-poetry.org | python3 -

pipx

# Ubuntu/Debian
sudo apt-get install -y pipx

# macOS
brew install pipx

# Windows
python -m pip install pipx

Rust Stack

Required by: rust-registry-login, rust-registry-publish

Rust Toolchain

# All platforms
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# Verify installation
rustc --version
cargo --version

cargo-workspaces

# After Rust installation
cargo install cargo-workspaces

GitHub Actions Dependencies

Standard Actions

These actions are provided by GitHub and don't require manual installation:

  • actions/setup-node@v1 - Node.js setup
  • actions/setup-dotnet@v4 - .NET setup
  • actions/setup-java@v4 - Java setup
  • actions/setup-python@v4 - Python setup
  • actions/cache@v3 - Caching
  • actions/upload-artifact@v4 - Artifact upload
  • docker/setup-buildx-action@v2 - Docker Buildx setup
  • docker/login-action@v2 - Docker registry login
  • docker/build-push-action@v5 - Docker build and push
  • dtolnay/rust-toolchain@stable - Rust toolchain setup
  • baptiste0928/cargo-install@v3 - Cargo package installation

Runner Setup Scripts

Ubuntu/Debian Runner Setup

#!/bin/bash
set -e

# Update system
sudo apt-get update

# Install core dependencies
sudo apt-get install -y git curl wget

# Install Docker
sudo apt-get install -y docker.io docker-compose-plugin
sudo usermod -aG docker $USER

# Install .NET SDK
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y dotnet-sdk-8.0

# Install Java
sudo apt-get install -y openjdk-21-jdk maven

# Install Node.js and pnpm
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
npm install -g pnpm

# Install Python stack
sudo apt-get install -y python3 python3-pip python3-venv pipx
curl -LsSf https://astral.sh/uv/install.sh | sh
pipx install poetry

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
cargo install cargo-workspaces

# Install GitHub CLI
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh

echo "Runner setup completed successfully!"

macOS Runner Setup

#!/bin/bash
set -e

# Install Homebrew if not present
if ! command -v brew &> /dev/null; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi

# Install all dependencies
brew install git docker docker-compose dotnet openjdk@21 maven node@18 python@3.12 pipx gh

# Install pnpm
npm install -g pnpm

# Install Python tools
curl -LsSf https://astral.sh/uv/install.sh | sh
pipx install poetry

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
cargo install cargo-workspaces

echo "Runner setup completed successfully!"

Windows Runner Setup

# PowerShell script for Windows
# Run as Administrator

# Install Chocolatey if not present
if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}

# Install dependencies via winget/choco
winget install Git.Git
winget install Docker.DockerDesktop
winget install Microsoft.DotNet.SDK.8
winget install Eclipse.Temurin.21.JDK
winget install Apache.Maven
winget install OpenJS.NodeJS
winget install Python.Python.3.12
winget install GitHub.cli

# Install pnpm
npm install -g pnpm

# Install Python tools
pip install pipx
curl -LsSf https://astral.sh/uv/install.sh | sh
pipx install poetry

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
refreshenv
cargo install cargo-workspaces

Write-Host "Runner setup completed successfully!"

Verification Script

#!/bin/bash
echo "Verifying GitHub Actions runner dependencies..."

# Check core tools
echo "Checking core tools..."
git --version || echo "❌ Git not found"
gh --version || echo "❌ GitHub CLI not found"

# Check Docker
echo "Checking Docker..."
docker --version || echo "❌ Docker not found"
docker buildx version || echo "❌ Docker Buildx not found"

# Check .NET
echo "Checking .NET..."
dotnet --version || echo "❌ .NET not found"

# Check Java
echo "Checking Java..."
java --version || echo "❌ Java not found"
mvn --version || echo "❌ Maven not found"

# Check Node.js
echo "Checking Node.js..."
node --version || echo "❌ Node.js not found"
pnpm --version || echo "❌ pnpm not found"

# Check Python
echo "Checking Python..."
python3 --version || echo "❌ Python not found"
uv --version || echo "❌ UV not found"
poetry --version || echo "❌ Poetry not found"

# Check Rust
echo "Checking Rust..."
rustc --version || echo "❌ Rust not found"
cargo --version || echo "❌ Cargo not found"
cargo workspaces --version || echo "❌ cargo-workspaces not found"

echo "Verification completed!"

Action-Specific Requirements

Docker Actions

  • docker-buildx-setup: Docker Buildx
  • docker-repository-login: Docker CLI
  • dotnet-docker-publish: Docker + .NET SDK
  • js-pnpm-docker-build-publish: Docker + Node.js + pnpm
  • python-uv-docker-publish: Docker + Python + UV

Build Actions

  • dotnet-build: .NET SDK 8.0+
  • js-pnpm-build: Node.js 18+ + pnpm
  • python-uv-build: Python 3.12+ + UV

Version Management Actions

  • dotnet-cut-tag: .NET SDK + Git
  • java-maven-cut-tag: Java 21 + Maven + Git
  • js-pnpm-cut-tag: Node.js + pnpm + Git
  • python-uv-cut-tag: Python + UV + Git

Repository Actions

  • dotnet-repository-login: .NET SDK
  • dotnet-repository-publish: .NET SDK
  • python-poetry-login: Python + Poetry
  • python-poetry-setup: Python + Poetry + pipx
  • python-uv-repository-login: Python + UV
  • python-uv-repository-publish: Python + UV
  • rust-registry-login: Rust toolchain
  • rust-registry-publish: Rust toolchain + cargo-workspaces

Security Considerations

  1. Runner Isolation: Each runner should be isolated and reset between jobs
  2. Credential Management: Use GitHub Secrets for sensitive information
  3. Package Registry Access: Configure appropriate authentication for private registries
  4. Docker Security: Use secure base images and scan for vulnerabilities
  5. Dependency Updates: Regularly update all tools and dependencies

Troubleshooting

Common Issues

  1. Permission Errors: Ensure runner has appropriate permissions for Docker, file system access
  2. Network Issues: Configure proxy settings if behind corporate firewall
  3. Version Conflicts: Use specific versions in setup actions to avoid conflicts
  4. Cache Issues: Clear caches if builds fail unexpectedly

Debug Commands

# Check environment
env | grep -E "(PATH|PYTHON|NODE|CARGO|DOTNET)"

# Check installed packages
which git docker dotnet java node python3 rustc

# Check service status
systemctl status docker # Linux
brew services list | grep docker # macOS

Custom Runner Requirements

Based on the actions configured in this repository, the following custom runners may be required for optimal performance and native architecture support:

Self-Hosted ARM64 Runners

Required for: Multi-platform Docker builds in js-pnpm-docker-build-publish, dotnet-docker-publish, python-uv-docker-publish

Several actions default to building Docker images for both AMD64 and ARM64 architectures:

  • js-pnpm-docker-build-publish: "linux/amd64,linux/arm64"
  • dotnet-docker-publish: "linux/amd64" (configurable to include ARM64)
  • python-uv-docker-publish: "linux/amd64" (configurable to include ARM64)

While Docker Buildx can cross-compile for ARM64 on AMD64 runners, native ARM64 runners provide:

  • Faster build times - No emulation overhead
  • Better compatibility - Native architecture testing
  • Resource efficiency - Reduced CPU usage for ARM64 builds

Register ARM64 Runner

For Ubuntu ARM64:

# On your ARM64 machine (e.g., AWS Graviton, Oracle Ampere, or Apple Silicon)

# 1. Go to your GitHub repository → Settings → Actions → Runners
# 2. Click "New self-hosted runner"
# 3. Select "Linux" and "ARM64"
# 4. Run the provided commands:

# Download
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-arm64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-arm64-2.311.0.tar.gz
tar xzf ./actions-runner-linux-arm64-2.311.0.tar.gz

# Configure
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token YOUR_TOKEN

# Install as service
sudo ./svc.sh install
sudo ./svc.sh start

For macOS ARM64 (Apple Silicon):

# On your Apple Silicon Mac

# 1. Go to your GitHub repository → Settings → Actions → Runners
# 2. Click "New self-hosted runner"
# 3. Select "macOS" and "ARM64"
# 4. Run the provided commands:

# Download
mkdir actions-runner && cd actions-runner
curl -o actions-runner-osx-arm64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-osx-arm64-2.311.0.tar.gz
tar xzf ./actions-runner-osx-arm64-2.311.0.tar.gz

# Configure
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token YOUR_TOKEN

# Install as service
sudo ./svc.sh install
sudo ./svc.sh start

ARM64 Runner Labels

Configure runners with appropriate labels for workflow targeting:

# Example workflow targeting ARM64 runners
jobs:
build-arm64:
runs-on: [self-hosted, linux, arm64]
# or
runs-on: [self-hosted, macOS, arm64]
steps:
- name: Build ARM64 Docker Image
uses: p6m-actions/js-pnpm-docker-build-publish@v1
with:
platforms: "linux/arm64"
registry: ${{ secrets.REGISTRY_URL }}
# ... other inputs

Docker Buildx Multi-Platform Setup

Required for: All Docker-based actions when building multi-platform images

The docker-buildx-setup action enables multi-platform builds, but performance considerations apply:

Cross-Platform Emulation (AMD64 → ARM64)

jobs:
multi-platform-build:
runs-on: ubuntu-latest # AMD64 GitHub-hosted runner
steps:
- name: Set up Docker Buildx
uses: p6m-actions/docker-buildx-setup@v1

- name: Build Multi-Platform Image
uses: p6m-actions/js-pnpm-docker-build-publish@v1
with:
platforms: "linux/amd64,linux/arm64" # ARM64 via emulation
registry: ${{ secrets.REGISTRY_URL }}

Performance Impact:

  • ARM64 emulation on AMD64 can be 5-10x slower
  • Increased runner time and costs
  • Potential timeout issues for large builds

Native Multi-Platform Strategy

jobs:
build-amd64:
runs-on: ubuntu-latest
steps:
- name: Build AMD64 Image
uses: p6m-actions/js-pnpm-docker-build-publish@v1
with:
platforms: "linux/amd64"
registry: ${{ secrets.REGISTRY_URL }}

build-arm64:
runs-on: [self-hosted, linux, arm64]
steps:
- name: Build ARM64 Image
uses: p6m-actions/js-pnpm-docker-build-publish@v1
with:
platforms: "linux/arm64"
registry: ${{ secrets.REGISTRY_URL }}

multi-manifest:
needs: [build-amd64, build-arm64]
runs-on: ubuntu-latest
steps:
- name: Create Multi-Platform Manifest
run: |
# Combine platform-specific images into single manifest
docker buildx imagetools create \
--tag ${{ env.REGISTRY }}/app:latest \
${{ env.REGISTRY }}/app:latest-amd64 \
${{ env.REGISTRY }}/app:latest-arm64

Architecture-Specific Test Considerations

For local testing (as seen in the test infrastructure):

The repository includes special handling for Apple Silicon in the test suite:

// Auto-detect Apple M-series chips and set container architecture
const isAppleSilicon = process.platform === 'darwin' && process.arch === 'arm64';

this.act = new Act(workingDirectory, {
// Force x86-64 emulation for consistent behavior
...(isAppleSilicon && { containerArchitecture: 'linux/amd64' }),
...options
});

Custom Runner Recommendations

For Production Workloads

Use CaseRecommended RunnerJustification
Multi-platform Docker buildsARM64 + AMD64 runnersNative performance, reduced build times
ARM64-only deploymentsARM64 runnersArchitecture-specific testing and optimization
High-volume buildsSelf-hosted runnersCost efficiency, dedicated resources
Security-sensitive buildsSelf-hosted runnersNetwork isolation, compliance requirements

Runner Sizing Guidelines

For Docker builds:

  • Minimum: 2 vCPU, 4GB RAM, 20GB storage
  • Recommended: 4 vCPU, 8GB RAM, 50GB storage
  • Heavy workloads: 8+ vCPU, 16GB+ RAM, 100GB+ storage

Storage considerations:

  • Docker images and layers consume significant space
  • Consider using external storage or regular cleanup scripts
  • Monitor /var/lib/docker usage

Runner Maintenance

Automated Cleanup

#!/bin/bash
# cleanup-runner.sh - Run periodically to manage disk space

# Clean Docker resources
docker system prune -af
docker volume prune -f

# Clean runner cache
rm -rf /tmp/actions-runner/_work/_temp/*
rm -rf /tmp/actions-runner/_work/_actions/*

# Clean package caches
sudo apt-get clean
sudo apt-get autoclean

Monitoring

#!/bin/bash
# monitor-runner.sh - Check runner health

# Check disk usage
df -h | grep -E "(/$|/var/lib/docker)"

# Check runner service
sudo systemctl status actions.runner.your-org-your-repo.your-runner-name

# Check Docker
docker info
docker system df

This comprehensive setup ensures optimal performance for all actions in the repository, with particular attention to multi-platform Docker builds and architecture-specific requirements.