Disappearing GitHub Self-Hosted Runner
Published: April 9, 2025
I had two GitHub Actions runners installed on a DigitalOcean droplet. I noticed that one of them had disappeared from GitHub. Locally the service was still running, but GitHub no longer showed it in the runner list.
TL;DR: GitHub automatically removes self-hosted runners that don’t pick up a job for more than 14 days. The runner on my droplet hadn’t been used during that period, so GitHub cleaned it up.
Debugging
At first, I checked the runner status:
sudo systemctl status actions.runner.<org>-<repo>-<name>.service
The service was active, so I restarted it:
sudo systemctl restart actions.runner.<org>-<repo>-<name>.service
But GitHub still didn’t recognize it. I also tried:
./config.sh remove
./config.sh
The remove step failed because GitHub had already deleted the runner. At this point it was clear: the local service thought it was fine, but GitHub had removed the registration.
Solution
The fix was to wipe the old runner and set up a new one.
# stop and remove
sudo systemctl stop actions.runner.<org>-<repo>-<name>.service
rm -rf actions-runner
# download fresh runner
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/latest/download/actions-runner-linux-x64.tar.gz
tar xzf ./actions-runner-linux-x64.tar.gz
# register again
./config.sh --url https://github.com/<org>/<repo> --token <new-token-from-repo-settings>
sudo ./svc.sh install
sudo ./svc.sh start
After this, the runner showed up in GitHub again and started picking jobs normally.
Side Effect
Right after reinstalling, my website showed an Nginx “Bad Gateway” error. This happened because the new runner had no _work
directory yet. GitHub creates that folder only when a workflow runs. After triggering a deployment, the files were back in place and Nginx worked fine.
Preventing It
To avoid this in the future, I added a scheduled workflow to keep the runner active. It runs every 7 days at midnight:
name: Alive Check - Keep Runner Active
on:
schedule:
- cron: '0 5 1,10,20 * *' # Runs at 5 AM UTC on the 1st, 10th, and 20th of every month
workflow_dispatch: # Allows manual triggering, where you can click a button to manually run this workflow
jobs:
keep_runner_active:
runs-on: self-hosted
steps:
- name: Keep runner active
run: echo "Keeping runner active at $(date)"
- name: Restart application
run: |
cd /home/<user_name>/<actions_runner_name>/_work/project_name
pm2 restart 1
Let's connect
Always interested in good conversations about technology, football, or interesting projects.