Configuration#
Config file location#
When you do not pass --config / -c, the config file is chosen in this order:
GH_SR_CONFIG— path to a YAML file (absolute or relative to the current working directory).~/.gh-sr/runners.yml— default aftergh sr init.
There is no automatic discovery of ./config/runners.yml in the current directory; use GH_SR_CONFIG or -c if your file lives elsewhere.
If you pass -c /path/to/runners.yml, that path is always used (and GH_SR_CONFIG is ignored).
Run gh sr config path to see which config file and ~/.gh-sr/env path apply in your environment.
Authentication#
gh sr uses the GitHub CLI only: run gh auth login on the machine where you run gh sr. Do not use github.pat in YAML or GITHUB_PAT / GITHUB_TOKEN for gh sr (legacy github.pat is rejected at load time).
See Authentication for permissions and troubleshooting.
Secrets (~/.gh-sr/env)#
Before the YAML file is loaded, gh sr applies environment variables from ~/.gh-sr/env if that file exists (dotenv-style: KEY=value, optional export , # comments). This is optional and intended for other tooling if needed — not for GitHub API tokens used by gh sr. Create the directory and file with gh sr init, or run gh sr config edit-env.
Keep ~/.gh-sr permissions tight (chmod 700 ~/.gh-sr, chmod 600 ~/.gh-sr/env if you create files by hand).
Example runners.yml#
Edit ~/.gh-sr/runners.yml (after gh sr init), or set GH_SR_CONFIG / -c to another YAML file. You can open the resolved file in $VISUAL or $EDITOR with gh sr config edit.
hosts:
my-laptop:
addr: local # run on the local machine (no SSH)
# os and arch are auto-detected; override if needed
mac-mini:
addr: user@192.168.1.50
os: darwin
arch: arm64
win-pc:
addr: user@192.168.1.51
os: windows
arch: amd64
vps-1:
addr: root@203.0.113.10
os: linux
arch: amd64
runners:
- name: enjoy-local
repo: an-lee/enjoy
host: my-laptop
count: 1
labels: [self-hosted, Linux, X64]
runner_mode: native
- name: enjoy-mac
repo: an-lee/enjoy
host: mac-mini
count: 1
labels: [self-hosted, macOS, ARM64]
- name: enjoy-win
repo: an-lee/enjoy
host: win-pc
count: 1
labels: [self-hosted, Windows, X64]
- name: hangar-ci
repo: an-lee/hangar
host: vps-1
count: 2
labels: [self-hosted, Linux, X64]
runner_mode: container
# GitHub Agentic Workflows — profile: agentic always uses container mode (DinD).
- name: hangar-aw
repo: an-lee/hangar
host: vps-1
profile: agentic
count: 2Config reference#
| Field | Description |
|---|---|
hosts.<name>.addr | SSH target (user@host or user@ip), or local to run on the machine where gh sr is running. Remote commands run as that user; on Linux, privilege expectations for setup / update follow Linux SSH user and privileges. |
hosts.<name>.os | linux, darwin, or windows. Auto-detected when addr is local. |
hosts.<name>.arch | amd64 or arm64. Auto-detected when addr is local. |
hosts.<name>.windows_ps | Optional; Windows hosts only. Which executable runs remote PowerShell payloads: powershell (default, powershell.exe) or pwsh (pwsh.exe). gh sr uses -EncodedCommand so the user’s SSH default shell (cmd.exe or pwsh) does not break nested quoting. |
runners[].name | Base name (instances become name-1, name-2, …) |
runners[].repo | GitHub owner/repo. Required unless org is set. |
runners[].org | GitHub organization name. Use instead of repo for org-level runners. |
runners[].group | Runner group name (org-level runners only). Passed as --runnergroup during registration. |
runners[].host | References a key under hosts |
runners[].count | Number of parallel instances (default: 1) |
runners[].labels | Labels for workflow runs-on matching. Include agentic when the runner should serve GitHub Agentic Workflows. With profile: agentic, the agentic label is added automatically if omitted. |
runners[].runner_mode | native (default) or container. container runs each runner instance in its own privileged Docker container with an inner dockerd (DinD), fully isolating /tmp/gh-aw, iptables, and the MCP gateway port between concurrent jobs on the same host. The image is built locally by gh sr setup and includes Docker CE, dnsmasq, gh-aw, AWF, and the actions runner. profile: agentic always uses container mode (and runner_mode: native + profile: agentic is rejected). See Agentic Workflows. |
runners[].profile | Optional. Set to agentic for GitHub Agentic Workflows: implies runner_mode: container, adds the agentic label, and bakes gh-aw/AWF/DNS/tooling into the locally built runner image. See Host setup — GitHub Agentic Workflows. |
runners[].ephemeral | Optional boolean. When true, the runner handles one job and deregisters. Container mode uses --restart no; native passes --ephemeral to config.sh. |
runners[].agentic_mcp_ports / runners[].agentic_mcp_port_base | Removed. The per-instance MCP port-label scheme is no longer used: container mode isolates the MCP gateway port per runner. gh sr rejects these fields with a migration message — delete them. |
container_runner_image.extra_apt_packages | Optional list of additional Debian package names to install in the locally built container runner image (runner_mode: container). At most 256 entries; each name must match [a-z0-9][a-z0-9+.-]* (max 200 chars). When set, the image tag gains a -x<8-hex> suffix so Docker does not reuse an image built without those packages. Core packages are in the repo manifest internal/runner/agentic-runner-image/apt-packages-core.txt. |
container_runner_image.mtu | Optional integer (576–1500). Forces the Docker network MTU for runner_mode: container — both the outer runner container’s egress interface and the inner dockerd bridge. Leave unset (0) to auto-detect the host’s egress MTU, which fixes the common reduced-MTU case (cloud overlay networks like GCP’s 1460, VPN/WireGuard) where large-packet TLS handshakes otherwise fail with Client network socket disconnected before secure TLS connection was established (e.g. actions/setup-go). Set this only when the host’s real path MTU is below its NIC MTU (a tunnel the NIC is unaware of) so auto-detection cannot see it. Only ever lowers the MTU; applied at container-create time, so changing it requires gh sr rebuild <name>. |
Unique runner names per repository: GitHub registers each self-hosted runner by its instance name (name-1, name-2, …). That name must be unique within a given owner/repo. If two machines use the same base name and count: 1, both try to register as name-1 and only one registration remains active. Prefer distinct base names (for example myapp-win vs myapp-linux) so every machine has its own GitHub runner record and gh sr status matches the right row.