Skip to content

Set up the GitHub self-hosted runner

The github-runner-01 container (192.168.10.111) runs the workflows that need access to the LAN: OpenTofu plans and applies against Proxmox and Hyperion, and the LXC bootstrap jobs. Those jobs run inside the brsalcedom/homelab-ci image, so the runner needs Docker.

This guide is for Debian 13. On another OS, follow the official Docker install docs for step 2.

  • The github-runner-01 container is deployed (see Deploy LXC containers).
  • The SSH private key set when the container was created.
  • Admin access to the repository on GitHub, to get a registration token.

Connect as root:

Terminal window
ssh -i ~/.ssh/id_ed25519 root@192.168.10.111

Steps 1 to 3 run as root without sudo.

Terminal window
apt update
apt install -y curl git sudo ca-certificates
Terminal window
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker run hello-world

The runner must not run as root.

Terminal window
useradd -m -s /bin/bash github
usermod -aG docker github
usermod -aG sudo github

Switch to the new user:

Terminal window
su - github
mkdir -p ~/actions-runner && cd ~/actions-runner

Download the runner. Replace 2.331.0 with the latest version from the runner releases page, and check the hash published there:

Terminal window
curl -o actions-runner-linux-x64-2.331.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.331.0/actions-runner-linux-x64-2.331.0.tar.gz
echo "<hash> actions-runner-linux-x64-2.331.0.tar.gz" | sha256sum -c
tar xzf ./actions-runner-linux-x64-2.331.0.tar.gz

Get a registration token in GitHub under Settings → Actions → Runners → New self-hosted runner, then:

Terminal window
./config.sh --url https://github.com/Brsalcedom/homelab-iac --token <TOKEN>

Accept the defaults, except the runner name: use github-runner-01.

5. Install the runner as a systemd service

Section titled “5. Install the runner as a systemd service”

Go back to root (exit) and run:

Terminal window
cd /home/github/actions-runner
sudo ./svc.sh install github
sudo ./svc.sh start
sudo ./svc.sh status

The service name is actions.runner.<owner>-<repo>.<runner>.service, here actions.runner.Brsalcedom-homelab-iac.github-runner-01.service. Enable it at boot:

Terminal window
sudo systemctl enable actions.runner.Brsalcedom-homelab-iac.github-runner-01.service
  1. In GitHub, Settings → Actions → Runners shows github-runner-01 as Idle.
  2. Run any workflow_dispatch workflow (for example Tofu :: Proxmox VM) and check that the runner picks it up.
Terminal window
cd /home/github/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh start
sudo ./svc.sh uninstall
# Service logs
sudo journalctl -u actions.runner.Brsalcedom-homelab-iac.github-runner-01.service -f
# Runner logs
sudo -u github tail -f /home/github/actions-runner/_diag/*.log
Terminal window
cd /home/github/actions-runner
sudo ./svc.sh stop
sudo -u github curl -o actions-runner-linux-x64-<VERSION>.tar.gz -L https://github.com/actions/runner/releases/download/v<VERSION>/actions-runner-linux-x64-<VERSION>.tar.gz
sudo -u github tar xzf ./actions-runner-linux-x64-<VERSION>.tar.gz
sudo ./svc.sh start
Symptom Check
Runner doesn’t appear in GitHub systemctl status and journalctl -n 50 for the service
Docker permission denied in jobs groups github must include docker; if not, usermod -aG docker github and restart the service
Runner shows Offline Connectivity to github.com, then restart the service
  • The github user can reach the Docker socket and its work directory ~/actions-runner/_work.
  • Secrets come from GitHub Secrets and from Bitwarden Secrets Manager (bitwarden/sm-action). Never store secrets on the container.
  • Watch CPU, RAM and disk usage of the container; container jobs and images add up.