GitHub Runner Setup & Maintenance
Comprehensive skill for managing self-hosted GitHub Actions runners with dedicated user isolation and systemd service management.
When to Use This Skill
- Setting up new self-hosted runners with dedicated user accounts
- Migrating runners from personal user accounts to dedicated runner users
- Troubleshooting runner connectivity or execution issues
- Implementing environment isolation to prevent CI/dev environment pollution
- Configuring systemd services for auto-restart on reboot
- Fixing workflow issues related to runner permissions or environment
Key Principles
- Environment Isolation: Runners run as dedicated
runneruser, not dev user - Systemd Management: Services auto-start on reboot, managed via systemd
- Skills Plane Integration: Runner user has permanent
~/.agent/skillsmount - Security: Minimal permissions for runner user (no sudo by default)
Quick Reference
Check Runner Status
# List active runners on GitHub
cd ~/prime-radiant-ai
gh api repos/stars-end/prime-radiant-ai/actions/runners --jq '.runners[] | {id, name, status, busy}'
# Check systemd service status
sudo systemctl status 'actions.runner.stars-end-prime-radiant-ai.*'
# View runner logs
sudo journalctl -u 'actions.runner.stars-end-prime-radiant-ai.*' -f
Common Tasks
Restart a Runner:
sudo systemctl restart actions.runner.stars-end-prime-radiant-ai.*
Update agent-skills for runner user:
sudo -u runner git -C ~runner/agent-skills pull origin main
Switch to runner user for debugging:
sudo su - runner
Regenerate runner token (tokens expire after a few hours):
# Generate new token
cd ~/prime-radiant-ai
TOKEN=$(gh api --method POST repos/stars-end/prime-radiant-ai/actions/runners/registration-token --jq .token)
# Stop service, reconfigure, restart
sudo systemctl stop actions.runner.stars-end-prime-radiant-ai.*
cd /home/runner/actions-runner-prime-radiant
sudo -u runner ./config.sh remove
sudo -u runner ./config.sh --url https://github.com/stars-end/prime-radiant-ai --token $TOKEN --name "$(hostname -s)-prime-radiant" --labels "self-hosted,linux,x64" --work _work --unattended
sudo systemctl start actions.runner.stars-end-prime-radiant-ai.*
Full Setup Guide
See comprehensive documentation: docs/SELF_HOSTED_RUNNER_SETUP.md
The complete setup guide covers:
- Creating dedicated runner user
- Installing runners with proper isolation
- Systemd service configuration
- Migration from personal user runners
- Troubleshooting common issues
- Security considerations
- Maintenance procedures
Architecture
/home/runner/
├── .agent/
│ └── skills -> /home/runner/agent-skills
├── agent-skills/ # Cloned from stars-end/agent-skills
├── actions-runner-prime-radiant/
│ ├── config.sh
│ ├── run.sh
│ └── svc.sh
└── actions-runner-affordabot/
├── config.sh
├── run.sh
└── svc.sh
Troubleshooting
Runner Not Appearing in GitHub
Symptoms: Runner shows as offline or doesn't appear in GitHub UI
Debug:
# Check service status
sudo systemctl status actions.runner.stars-end-prime-radiant-ai.*
# Check recent logs for errors
sudo journalctl -u actions.runner.stars-end-prime-radiant-ai.* -n 50
# Try running manually to see connection errors
sudo -u runner bash
cd ~/actions-runner-prime-radiant
./run.sh # Press Ctrl+C to stop
Common causes:
- Token expired → Regenerate token and reconfigure
- Network issues → Check firewall rules for GitHub API access
- Service not running →
sudo systemctl start ...
Workflow Fails with "Unable to locate executable file: unzip"
Symptoms: Setup actions (actions/setup-bun, actions/setup-node, etc.) fail with "unzip not found"
Solution: Install missing system utilities
# Install unzip and zip system-wide
sudo apt-get update
sudo apt-get install -y unzip zip
# Verify
sudo -u runner which unzip # Should show /usr/bin/unzip
# Restart runner to pick up changes
sudo systemctl restart actions.runner.stars-end-prime-radiant-ai.*
Workflow Needs Python 3.13
Symptoms: Workflows fail with wrong Python version or Python 3.13 not found
Solution: Install Python 3.13 via mise
# Install mise for runner user (if not already)
sudo -u runner bash -c 'curl https://mise.run | sh'
# Configure shell
sudo -u runner bash -c 'echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> ~/.bashrc'
sudo -u runner bash -c 'echo "eval \"\$(mise activate bash)\"" >> ~/.bashrc'
# Install Python 3.13
sudo -u runner bash -c 'export PATH="$HOME/.local/bin:$PATH" && mise use --global python@3.13 && mise install'
# Verify
sudo -u runner bash --login -c 'python --version' # Should show 3.13.x
# Restart runner
sudo systemctl restart actions.runner.stars-end-prime-radiant-ai.*
Workflow Fails with "Permission Denied"
Symptoms: Workflows fail with permission errors accessing files/directories
Solution: Runner user may need additional permissions
# Add to docker group (if workflows use Docker)
sudo usermod -aG docker runner
# For specific directory access, use ACLs
sudo setfacl -m u:runner:rwx /path/to/directory
# Restart runner service after group changes
sudo systemctl restart actions.runner.stars-end-prime-radiant-ai.*
Skills Mount Corruption (Dev Environment)
Symptoms: ~/.agent/skills in dev user environment points to runner workspace
Root Cause: Old workflow configuration that ran as dev user and modified global symlink
Fix:
# Fix dev user's symlink
rm -f ~/.agent/skills && ln -sfn ~/agent-skills ~/.agent/skills
# Verify runner's symlink is isolated (should NOT affect dev user)
sudo -u runner ls -la ~/.agent/skills
# Should show: /home/runner/.agent/skills -> /home/runner/agent-skills
Prevention: Ensure workflows don't create ~/.agent/skills symlinks if using dedicated runner user
Runner Service Won't Start
Debug steps:
# Check if service file exists
ls -la /etc/systemd/system/actions.runner.stars-end-*
# Reload systemd daemon
sudo systemctl daemon-reload
# Check for failed units
sudo systemctl --failed
# View detailed service errors
sudo systemctl status actions.runner.stars-end-prime-radiant-ai.* -l
Workflow Integration
Workflows running on self-hosted runners should be aware of:
Skills Environment
Runner user has permanent skills mount. Workflows should verify rather than recreate:
- name: Setup Skills Environment
run: |
# Runner user already has permanent skills mount at ~/.agent/skills → ~/agent-skills
# Verify the existing mount
ls -la ~/.agent/skills
# Workflow checkout is available at $PWD/agent-skills if needed
ls -la $PWD/agent-skills
Beads CLI
Runner user should have Beads CLI installed:
- name: Install Beads CLI
run: |
pip install beads-cli
Python/Node Setup
Use mise for consistent toolchain:
- name: Setup Python via mise
uses: ./.github/actions/setup-python-mise
Security Considerations
Minimal Permissions
Runner user should have:
- ✅ Read/write to its own home directory
- ✅ Execute permissions for required tools (git, docker, mise, etc.)
- ❌ NO sudo access (unless workflows explicitly require it)
- ❌ NO access to other users' home directories
Secrets Handling
- Never log secrets in workflow output
- Use GitHub secrets for sensitive values
- Runner has access to repository secrets during workflow execution
- Secrets are automatically masked in logs
Network Isolation
Consider:
- Firewall rules limiting runner's network access
- VPN/bastion for accessing internal resources
- Separate runner for public vs private repos
Related Documentation
docs/SELF_HOSTED_RUNNER_SETUP.md- Complete setup guidedocs/SKILLS_PLANE.md- Skills mount architecturedocs/DX_BOOTSTRAP_CONTRACT.md- Session startup requirements
Agent Guidance
When working on runner-related tasks:
- First, check runner status on GitHub and systemd
- Read logs before making changes:
sudo journalctl -u actions.runner... - Test manually before modifying systemd services:
sudo -u runner ./run.sh - Document changes in commit messages with Feature-Key trailers
- Verify isolation after changes: runner user changes shouldn't affect dev user
Quick Start for New VM
To set up self-hosted runners on a new VM:
- Create runner user:
sudo useradd -m -s /bin/bash -c "GitHub Actions Runner" runner - Clone agent-skills for runner:
sudo -u runner git clone https://github.com/stars-end/agent-skills.git ~runner/agent-skills - Setup skills mount:
sudo -u runner bash -c 'mkdir -p ~/.agent && ln -sfn ~/agent-skills ~/.agent/skills' - Follow full setup guide in
docs/SELF_HOSTED_RUNNER_SETUP.md
Notes
- Runner tokens expire after a few hours; keep track if reconfiguring
- Systemd services persist across reboots (unlike nohup/screen)
- Runner isolation prevents the "skills mount corruption" problem
- Each repository needs its own runner registration
- Runners can be shared across repos by adding multiple repo registrations
Scan to join WeChat group