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. 🚀
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 environment, faster 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 gnupgAdd 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.ascAdd 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 updateInstall Docker Engine:
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginVerify that Docker is running:
systemctl start docker
systemctl enable docker
docker --versionTest Docker:
docker run hello-worldIf 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-runnerAdd the user to the docker group (so it can run Docker commands):
usermod -aG docker github-runnerSwitch to the GitHub Runner user:
su - github-runnerStep 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-runnerDownload 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.gzConfigure 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_TOKENStart the runner manually for testing:
./run.shIf 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:
exitCreate the systemd service file:
nano /etc/systemd/system/github-runner.servicePaste 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.targetEnable and start the service:
systemctl daemon-reload
systemctl enable github-runner
systemctl start github-runnerCheck if the runner is running:
systemctl status github-runnerIf 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-worldPush 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.