Operations 8 min read

How to SSH into GitHub Actions Runners: Bypass Restrictions with tmate and ngrok

This article explains how to bypass GitHub Actions' lack of interactive SSH access by using tmate and ngrok, providing step‑by‑step workflow examples, required server specifications, code snippets, and tips for maintaining persistent connections, while emphasizing responsible, non‑malicious usage.

Programmer DD
Programmer DD
Programmer DD
How to SSH into GitHub Actions Runners: Bypass Restrictions with tmate and ngrok

GitHub Actions is GitHub's continuous integration service launched in October 2018. Each action performs a specific task such as fetching code, running tests, or deploying to third‑party services. Actions are combined to form a CI workflow and are shared via GitHub repositories.

GitHub Actions provides a server environment with the following specifications:

2‑core CPU

7 GB RAM

84 GB SSD storage

The detailed system environment is shown below:

Besides Ubuntu, the runner also supports Windows Server 2019 and macOS Catalina 10.15. However, GitHub Actions does not allow direct interactive SSH connections, so obtaining a VPS‑like shell requires workarounds.

Solution 1

mxschmitt/action-tmate provides the first method to establish an interactive tmate session on the Actions runner. The connection ends when you exit, so it cannot continue to subsequent steps, but it is useful for quick SSH access.

name: CI
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup tmate session
      uses: mxschmitt/action-tmate@v2

Solution 2

csexton/debugger-action builds on the tmate approach, allowing the workflow to continue after the SSH session. It adds a 15‑minute auto‑disconnect which can be disabled by touching /tmp/keepalive.

name: debugger-action
on:
  watch:
    types: started
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup Debug Session
      uses: csexton/debugger-action@master

Action log output:

Solution 3

This method does not use an Action; instead it creates an SSH tunnel via ngrok to expose port 22 of the runner.

#!/bin/bash

if [[ -z "$NGROK_TOKEN" ]]; then
  echo "Please set 'NGROK_TOKEN'"
  exit 2
fi

if [[ -z "$USER_PASS" ]]; then
  echo "Please set 'USER_PASS' for user: $USER"
  exit 3
fi

echo "### Install ngrok ###"
wget -q https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-386.zip
unzip ngrok-stable-linux-386.zip
chmod +x ./ngrok

echo "### Update $USER password ###"
echo -e "$USER_PASS
$USER_PASS" | sudo passwd "$USER"

echo "### Start ngrok proxy for 22 port ###"
rm -f .ngrok.log
./ngrok authtoken "$NGROK_TOKEN"
./ngrok tcp 22 --log ".ngrok.log" &

sleep 10
HAS_ERRORS=$(grep "command failed" < .ngrok.log)

if [[ -z "$HAS_ERRORS" ]]; then
  echo "=========================================="
  echo "To connect: $(grep -o -E "tcp://(.+)" < .ngrok.log | sed "s/tcp:\/\//ssh $USER@/" | sed "s/:/ -p /")"
  echo "=========================================="
else
  echo "$HAS_ERRORS"
  exit 4
fi

First, register on the ngrok website and obtain a tunnel authtoken. Then add the following workflow to create the tunnel when a job fails:

name: Debugging with SSH
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Try Build
      run: ./not-exist-file.sh it bloke build
    - name: Start SSH via Ngrok
      if: ${{ failure() }}
      run: curl -sL https://gist.githubusercontent.com/retyui/.../debug-github-actions.sh | bash
      env:
        NGROK_TOKEN: ${{ secrets.NGROK_TOKEN }}
        USER_PASS: ${{ secrets.USER_PASS }}
    - name: Don't kill instance
      if: ${{ failure() }}
      run: sleep 1h

The server’s default lifetime is one hour, which can be adjusted. Secrets should be stored in GitHub’s encrypted secrets as described in the official documentation.

Action log output:

Disclaimer: Use these techniques only for learning and research purposes; do not employ them for malicious activities.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ci/cdSSHGitHub Actionsngroktmate
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.