SSH into GitHub Actions runners for interactive debugging — privately via your Tailscale network.
Inspired by: https://github.com/luchihoratiu/debug-via-ssh
name: Debug Runner
on: workflow_dispatch
jobs:
debug:
runs-on: ubuntu-latest
steps:
- name: Debug via Tailscale
uses: Sharpie/debug-via-tailscale@v1
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:github-actionsThen SSH from any machine on your tailnet using the connection info printed in the workflow logs.
- A Tailscale account with a tailnet
- An OAuth client — create one at Settings > Trust credentials with
auth_keysscope - ACL tags — add
tag:github-actions(or your chosen tag) to your ACL policy:"tagOwners": { "tag:github-actions": ["autogroup:admin"] }
- Tailscale SSH ACLs — allow SSH access to tagged nodes:
"ssh": [ { "action": "accept", "src": ["autogroup:admin"], "dst": ["tag:github-actions"], "users": ["autogroup:nonroot"] } ]
| Input | Required | Default | Description |
|---|---|---|---|
oauth-client-id |
no* | — | Tailscale OAuth client ID |
oauth-secret |
no* | — | Tailscale OAuth client secret |
authkey |
no* | — | Tailscale auth key |
tags |
yes | tag:github-actions |
ACL tags for the ephemeral node |
timeout |
no | 3600 |
Max session duration in seconds (1 hour) |
tailscale-args |
no | — | Extra arguments for tailscale up |
*One auth method required: oauth-client-id + oauth-secret, or authkey.
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:github-actionsCreate an OAuth client at Settings > OAuth clients in the Tailscale admin console. The client needs the auth_keys scope.
with:
authkey: ${{ secrets.TS_AUTHKEY }}
tags: tag:github-actionsGenerate an auth key at Settings > Keys. Use a reusable, ephemeral key tagged with your CI tag.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build
- run: make test
- name: Debug on failure
if: failure()
uses: your-username/debug-via-tailscale@v1
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}on:
workflow_dispatch:
inputs:
debug:
description: 'Enable SSH debugging'
type: boolean
default: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build
- name: Debug session
if: inputs.debug
uses: your-username/debug-via-tailscale@v1
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}- Linux (ubuntu-latest, ubuntu-22.04, etc.) — full support
- macOS (macos-latest, macos-14, etc.) — full support
- Windows — not yet supported
- Validates that an authentication method is provided
- Connects the runner to your Tailscale network using tailscale/github-action with Tailscale SSH enabled
- Displays the runner's Tailscale IP and DNS name in the workflow logs
- Waits until the timeout expires or you create
~/continueto end the session early
The runner joins as an ephemeral node and is automatically removed when the workflow ends.
From inside your SSH session, run:
touch ~/continue
This signals the action to proceed, ending the debug session and continuing the workflow.