How to Set Up a GitHub Self-Hosted Runner with Docker in an LXC Container on Proxmox

Using a self-hosted GitHub runner in an LXC container on Proxmox provides faster builds, unlimited CI/CD minutes, and full Docker support. This guide walks you through installing Docker, setting up a GitHub runner, and automating it with systemd, ensuring a powerful, cost-effective CI/CD workflow. 🚀

How to Set Up a GitHub Self-Hosted Runner with Docker in an LXC Container on Proxmox

Why Should You Consider Self-Hosting a GitHub Runner?

If you’re using GitHub Actions for CI/CD, you’re likely familiar with the limitations of GitHub-hosted runners. While convenient, they come with restrictions such as limited build minutes, slower performance, and lack of customization.

By running a self-hosted GitHub runner inside an LXC container on Proxmox, you gain complete control over the build environmentfaster execution times, and unlimited usage all while leveraging your existing infrastructure.

Key Benefits of Self-Hosting Your GitHub Runner:

  • Faster Build Times – Cache dependencies, Docker images, and avoid cold starts.
  • Unlimited CI/CD Minutes – No more restrictions from GitHub’s free-tier limits.
  • Customizable Environment – Install required dependencies, use specific OS versions.
  • Cost Savings – Use your own hardware instead of cloud-based runners.
  • Docker & Containerized Workflows – Run privileged Docker builds efficiently.

Now that you understand the why, let’s walk through setting up a GitHub self-hosted runner with Docker inside an LXC container on Proxmox.

Step 1: Install Docker in the LXC Container

Since our runner needs Docker support, the first step is to install Docker inside the LXC container.

Enter the LXC container (replace <container_id> with your actual container ID):

pct enter <container_id>

 Update system packages & install dependencies:

apt update && apt upgrade -y
apt install -y ca-certificates curl gnupg

Add Docker’s official GPG key:

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
chmod a+r /etc/apt/keyrings/docker.asc

Add the Docker repository:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update

Install Docker Engine:

apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verify that Docker is running:

systemctl start docker
systemctl enable docker
docker --version

Test Docker:

docker run hello-world

If you see “Hello from Docker!”, then Docker is correctly installed inside the LXC container.

Step 2: Create a Dedicated GitHub Runner User

To keep things secure and organized, we’ll create a non-root user to run the GitHub Actions runner.

Create a new user named github-runner:

adduser --disabled-password --gecos "" github-runner

Add the user to the docker group (so it can run Docker commands):

usermod -aG docker github-runner

Switch to the GitHub Runner user:

su - github-runner

Step 3: Install and Configure the GitHub Runner

Now, let’s install the GitHub Actions runner inside the container.

Create a directory for the runner and navigate to it:

mkdir -p ~/actions-runner && cd ~/actions-runner

Download the latest GitHub Runner software:

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

Configure the runner:

Go to GitHub → Your Repo → Settings → Actions → Self-hosted Runners and generate a new token.

Then, run:

./config.sh --url https://github.com/YOUR_GITHUB_REPO --token YOUR_TOKEN

Start the runner manually for testing:

./run.sh

If it connects successfully, press CTRL + C to stop it.

Step 4: Set Up GitHub Runner as a Systemd Service

To ensure the runner starts automatically, we’ll configure it as a systemd service.

Exit back to root:

exit

Create the systemd service file:

nano /etc/systemd/system/github-runner.service

Paste the following configuration:

[Unit]
Description=GitHub Actions Runner
After=network.target

[Service]
ExecStart=/home/github-runner/actions-runner/run.sh
WorkingDirectory=/home/github-runner/actions-runner
Restart=always
User=github-runner

[Install]
WantedBy=multi-user.target

Enable and start the service:

systemctl daemon-reload
systemctl enable github-runner
systemctl start github-runner

Check if the runner is running:

systemctl status github-runner

If it shows Active (running), then the GitHub Runner is correctly set up! 

Step 5: Test a Docker Build in GitHub Actions

To ensure the GitHub Runner can run Docker builds, create a workflow file in your repository:

.github/workflows/test-docker.yml

name: Test Docker Build
on: [push]

jobs:
  build:
    runs-on: self-hosted
    steps:
      - name: Check Runner
        run: echo "Runner is working!"

      - name: Set up Docker
        run: docker info

      - name: Build Docker Image
        run: docker run hello-world

Push the changes, and watch the GitHub Actions logs to ensure Docker works inside the runner.

Final Thoughts

By following this guide, you now have a self-hosted GitHub Actions runner inside an LXC container on Proxmox that supports Docker builds.

Why This Setup is Powerful

  • Faster builds compared to GitHub’s shared runners.
  • No CI/CD time limits—completely free for unlimited usage.
  • Full customization of your CI/CD environment.
  • Works perfectly with Docker and containerized workloads.

Now, your self-hosted GitHub Actions runner is fully configured and ready for real-world CI/CD deployments! 


Disclaimer: The views and opinions expressed on this website are solely those of the author and do not necessarily reflect the official policy or position of any employer or organization affiliated with the author.