---
title: "Running a self-hosted GitHub Actions Runner"
description: "There's very little to it; you're following the GitHub instructions, but then doing a little bit of systemd work to make sure the runner keeps running."
url: https://exe-staging.dev/deploy/github-actions-runner
category: "Developer tools"
updated: 2026-10-17
---

# Running a self-hosted GitHub Actions Runner

Log in easily into your CI environment

- **Software:** GitHub Actions runner (https://docs.github.com/en/actions/hosting-your-own-runners)
- **Source:** https://github.com/actions/runner
- **License:** MIT
- **Example VM name:** `my-github-actions-runner` (yours will differ; on the VM, `hostname` prints it)
- **Machine-readable:** https://exe-staging.dev/deploy/github-actions-runner/manifest.json

## What you get

- A self-hosted runner, registered with your GitHub organization or repository
- The `gh-actions-runner` systemd service, which restarts the runner after a reboot
- `Listening for Jobs` in `sudo systemctl status gh-actions-runner.service`

Running on the VM:

- **GitHub Actions runner**: `gh-actions-runner.service`, managed by systemd, data in `~/actions-runner`

## Deploy with Shelley

Open https://exe-staging.dev/new?prompt=GITHUB_RUNNER_URL%3D%3Cfill-this-in%3E%0AGITHUB_RUNNER_TOKEN%3D%3Cfill-this-in%3E%0A%0ASet%20up%20GitHub%20Actions%20runner%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Fgithub-actions-runner.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20GITHUB_RUNNER_URL%3A%20the%20%60--url%60%20in%20the%20%60.%2Fconfig.sh%60%20command%20on%20GitHub%27s%20new%20self-hosted%20runner%20page%2C%20for%20your%20organization%20or%20repository%0A-%20GITHUB_RUNNER_TOKEN%3A%20the%20%60--token%60%20in%20the%20same%20command%3B%20it%20expires%20after%20an%20hour%0AAsk%20me%20for%20any%20that%20still%20say%20%3Cfill-this-in%3E%20before%20you%20need%20them.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-github-actions-runner.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-github-actions-runner.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20A%20self-hosted%20runner%2C%20registered%20with%20your%20GitHub%20organization%20or%20repository%0A-%20The%20%60gh-actions-runner%60%20systemd%20service%2C%20which%20restarts%20the%20runner%20after%20a%20reboot%0A-%20%60Listening%20for%20Jobs%60%20in%20%60sudo%20systemctl%20status%20gh-actions-runner.service%60%0A%0AGitHub%27s%20instructions%20are%20on%20the%20page%20I%20open%20in%20my%20browser%3B%20reproduce%0Athem%20here.%20Download%20the%20latest%20Linux%20x64%20runner%20from%0Ahttps%3A%2F%2Fgithub.com%2Factions%2Frunner%2Freleases%20into%20~%2Factions-runner%2C%20check%0Aits%20SHA-256%2C%20and%20run%20.%2Fconfig.sh%20--unattended%20with%20my%20URL%20and%20token%20and%0A--name%20%22%24%28hostname%29%22.%20Don%27t%20start%20run.sh%20by%20hand%3A%20the%20systemd%20service%0Aruns%20it.%20Never%20echo%20the%20token%20back.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open.%0A to create a VM whose agent, Shelley, follows this recipe. From a terminal:

```sh
curl -fsSL https://exe-staging.dev/deploy/github-actions-runner/prompt.txt | ssh exe.dev new --prompt=/dev/stdin
```

Or follow the steps below by hand.

There's very little to it; you're following the GitHub instructions, but then
doing a little bit of systemd work to make sure the runner keeps running.

First, create a new VM with `ssh exe.dev new`. This will create
a new VM. SSH into it with `ssh vmname.exe.xyz`. The trickiest
bit is to find the GitHub URLs. Replace the placeholders in the following:

 * [https://github.com/organizations/ORG/settings/actions/runners/new?arch=x64&os=linux](https://github.com/organizations/ORG/settings/actions/runners/new?arch=x64&os=linux)
 * [https://github.com/USER/REPO/settings/actions/runners/new?arch=x64&os=linux](https://github.com/USER/REPO/settings/actions/runners/new?arch=x64&os=linux)

Copy and paste the instructions from GitHub's instructions into your shell
session. It's pretty quick and easy until "run.sh".

To make sure the runner restarts after a reboot, we can create
a systemd service:

Create the service file at `/home/exedev/actions-runner/gh-actions-runner.service`:

```bash
cat > /home/exedev/actions-runner/gh-actions-runner.service << 'EOF'
[Unit]
Description=GitHub Actions Runner
After=network.target

[Service]
Type=simple
User=exedev
WorkingDirectory=/home/exedev/actions-runner
ExecStart=/home/exedev/actions-runner/run.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
```

Then copy the service file to systemd directory

```bash
sudo cp /home/exedev/actions-runner/gh-actions-runner.service /etc/systemd/system/
```

And start the service:

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now gh-actions-runner.service
```

Verify the service is running

```console
sudo systemctl status gh-actions-runner.service

gh-actions-runner.service - GitHub Actions Runner
     Loaded: loaded (/etc/systemd/system/gh-actions-runner.service; enabled; preset: enabled)
     Active: active (running) since Sun 2025-11-09 04:33:28 UTC; 41s ago
   Main PID: 1151 (run.sh)
      Tasks: 15 (limit: 2384)
     Memory: 93.2M (peak: 101.6M)
        CPU: 1.447s
     CGroup: /system.slice/gh-actions-runner.service
             /bin/bash /home/exedev/actions-runner/run.sh
             /bin/bash /home/exedev/actions-runner/run-helper.sh
             /home/exedev/actions-runner/bin/Runner.Listener run

Nov 09 04:33:30 ...exe.dev run.sh[1159]: Connected to GitHub
Nov 09 04:33:31 ...exe.dev run.sh[1159]: Current runner version: '2.329.0'
Nov 09 04:33:31 ...exe.dev run.sh[1159]: 2025-11-09 04:33:31Z: Listening for Jobs
```

You're all set!

## Related

- [Forgejo](https://exe-staging.dev/deploy/forgejo.md): Self-hosted Git forge with exe.dev SSO
- [Gitea](https://exe-staging.dev/deploy/gitea.md): Self-hosted Git forge with exe.dev SSO
- [VS Code in your browser, with code-server](https://exe-staging.dev/deploy/code-server.md): Your editor in a tab. Your projects right where you left them.
- [Dev, Test, Prod: Choose One, Two, or Three](https://exe-staging.dev/deploy/dev-test-prod.md): You can build, test, and deploy on exe.dev.
- [Spinning up a Marimo Notebook](https://exe-staging.dev/deploy/marimo.md): An open source reactive notebook
- [Self-host n8n](https://exe-staging.dev/deploy/n8n.md): Connect your apps. Let the boring bits run themselves.
