# Setting Up Self-Hosted Runners in GitHub: A Step-by-Step Guide

Imagine your boss wants you to use Github actions to automate the workflow of the developers. So you find this thing called Github actions and on paper it seems like the perfect solution, so you get working on it and find out that the signal to trigger the job in your pipeline is sent from one of Github’s servers.  
Now the problem is that your pipeline servers are locked behind a VPN, but Github always sends the trigger signal from 1 of the 1000 IPs that they own. The self-hosted Github runners come in handy in this situation, after setting up a custom runner in a server that has a whitelisted IP in your pipeline server, you will now be able to access automate the action for your developers to trigger straight from their code base.

The installation of a Github runner can be done at 3 levels:

* Enterprise
    
    * These runners can be assigned to all organizations and repositories.
        
* Organization
    
    * These runners can be assigned to all repositories under that organization.
        
* Repository
    
    * Runners that are assigned to a specific repository.
        

Once the runners have been assigned you can then use labels to choose which job you want running on a specific GH runner

All 3 runners are configured using similar steps, but this guide will focus on installing it at an Organization level.

<aside>
💡 Important to note that in order for this to work, you will need an existing server with your favorite cloud provider or an on-prem one.
</aside>

First you will have to click on the drop down next to your profile picture and go into “Your organizations”

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732510834571/b6786cb6-6d76-47ff-a0bd-2fe279562f48.png align="center")

Next click on the “Settings” button next to your organization’s name.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732510893650/dd9c3696-2687-428c-b2ce-cb87cd00bd0c.png align="center")

Go to “Actions” & “Runners”

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732510913966/57648dda-706a-4a83-9261-2632249c77ff.png align="center")

Then create a new self-hosted runner.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732510927911/e627ec17-93a2-42f7-a4d7-1bdcd0e0a07c.png align="center")

Next choose your operating system and run the commands that they have displayed within your server that you want to host the runner on.

The following steps are to help you configure a GH runner on a Linux x64 operating system.

<aside>
💡 **Note**: When proceeding from here you will need to use a non-root user in your operating system as the runner configuration step is not allowed to be executed as root user.
</aside>

### Configure Linux User

These commands will be executed assuming you’re running as root.

Create a new user

```json
//This will create a the user runner and set their home directory to their name.
//Replace "runner" with desired username.
adduser -m runner
```

Create user password

```json
//Replace "runner" with desired username.
passwd runner
```

Switch to the non-root user

```json
su runner
```

### Install & Run GH Runner

Creates a folder and cd into it

```json
mkdir actions-runner; cd actions-runner
```

Download the runner package

```json
curl -o actions-runner-linux-x64-2.297.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.297.0/actions-runner-linux-x64-2.297.0.tar.gz
```

Optional: Validate the hash

```json
echo "eb4e2fa6567d2222686be95ee23210e83fb6356dd0195149f96fd91398323d7f  actions-runner-linux-x64-2.297.0.tar.gz" | shasum -a 256 -c
```

Extract the installer from the .tar file you just downloaded.

```json
tar xzf ./actions-runner-linux-x64-2.297.0.tar.gz
```

Create the runner and start the configuration

<aside>
💡 **Note**: Executing the following config command will prompt you for config details.
- Add to group can be left as default
<ul>
<li>
<p>Name of your runner can be named as you like or leave the default option</p>
</li>
<li>
<p>Label option is an important one. By default you are given a set of default labels. But if you intend on using multiple runners, then add the appropriate labels so that you can refer to them in your workflow files to target and access your self-hosted runners.</p>
</li>
<li>
<p>Finally the name and path of your work folder. This is where it’s going to to download the actions that it runs and do all of it’s work. You can leave that with the default option which is <_work>.</p>
</li>
</ul>
</aside>

```json
./config.sh --url https://github.com/<YOUR_ORGANIZATION> --token <GITHUB_PROVIDED_TOKEN>
```

<aside>
💡 **Note**: The URL will contain the name of your organization at the end. The GITHUB_PROVIDED_TOKEN will be automatically generated by Github when you initially create the runner. It’s important to note that this token has an expiration time of 1 hour so if you take too long, you will have to refresh and generate a new one.
</aside>

Run it! (This is a manual process and you will have to run this manually each time)

```json
./run.sh
```

Note that the directory you installed the GH runner will have a [svc.sh](http://svc.sh) file this file can be executed to have your GH runner always operating in case of a server restart as well, instead of always having to manually run the ./run.cmd command.

The [svc.sh](http://svc.sh) file can only be executed as root user.

```json
su root
```

Change to your installation directory.

```json
cd /home/runner/actions-runner
```

Install the service

```json
./svc.sh install
```

Start your service

```json
./svc.sh start
```

Now if you go back to your runners tab within your organization in your Github account, you will be able to note that your self-hosted runner is now in **idle** status. This means that you currently don’t have any actions running, and that your server is listening for any incoming actions.
