For efficient GitHub Actions self-hosted runner operation, it is optimal to use a VPS with 4 GB of RAM, 2 vCPUs, and an NVMe drive — this configuration ensures stable Docker container builds and speeds up CI/CD processes by 5–10 times compared to standard free GitHub runners.
Why GitHub Actions self-hosted is the standard for professional development
Using GitHub cloud runners is convenient for small Open Source projects, but professional development quickly hits limitations: slow processors, build time limits (2,000 minutes per month on the free tier), and a lack of environment control. Moving processes to your own
ci cd vps solves these problems by providing dedicated resources that are not shared with other users.
Build acceleration and caching
The main factor in acceleration is local data storage. In the GitHub cloud, every run starts from a "clean slate": dependencies (node_modules, Go packages, Maven cache) are downloaded anew or restored from a network cache, which can take up to 70% of the pipeline time. On a
self hosted runner vps, the cache is stored on the physical disk. For example, building a heavy React application that takes 8 minutes in the cloud is reduced to 45–60 seconds on a VPS with an NVMe drive due to instant access to already downloaded Docker layers and dependencies.
Cost-effectiveness at scale
GitHub's free minutes run out quickly, and the cost of additional minutes in the cloud is disproportionately high. Renting one powerful VPS allows you to run dozens or hundreds of builds a day at no extra cost. This is especially important for teams using self-hosted Sentry or other monitoring tools that require frequent deployments and integration tests.
Choosing a ci cd vps configuration for various tasks
The performance of an
actions runner directly depends on the allocated resources. Compiling heavy C++ or Java projects requires high CPU frequency and RAM volume, while minimal resources are sufficient for deploying static sites.
VPS characteristics comparison table for runners
| Project Type |
Recommended CPU |
RAM (GB) |
Disk (NVMe) |
Performance (vs Cloud) |
| Frontend (React/Vue/Next.js) |
2 vCPU (3.0+ GHz) |
4 GB |
40 GB |
5x faster |
| Backend (Go/Rust/Java) |
4-8 vCPU |
8-16 GB |
80 GB |
8x faster |
| Docker-heavy (Microservices) |
4 vCPU |
8 GB |
100 GB |
10x faster |
| Mobile (Android/iOS) |
8 vCPU |
16+ GB |
200 GB |
Depends on emulation |
When choosing a server, it is important to consider not only the number of cores but also their architecture. Modern processors with frequencies above 3 GHz significantly reduce the execution time of unit tests, which often run in a single thread.
Looking for a reliable server for your projects?
VPS from $10/mo and dedicated servers from $9/mo with NVMe, DDoS protection, and 24/7 support.
View offers →
Step-by-step installation of GitHub Actions self-hosted on Ubuntu
The installation process takes no more than 10 minutes. To get started, you will need a clean VPS with Ubuntu 22.04 or 24.04. It is recommended to create a separate user to run the runner to avoid running as root for security reasons.
System preparation and user creation
sudo useradd -m -s /bin/bash github-runner
sudo usermod -aG sudo github-runner
sudo apt update && sudo apt upgrade -y
# Install necessary dependencies
sudo apt install -y curl git jq build-essential libssl-dev libffi-dev python3
Registering the runner in the repository
Go to your repository settings on GitHub:
Settings -> Actions -> Runners -> New self-hosted runner. Select Linux and follow the instructions to download the archive. Example commands for downloading (version may change):
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz
./config.sh --url https://github.com/OWNER/REPO --token YOUR_TOKEN
After completing the configuration, the script will ask for the runner's name and labels. Labels are critical for management: you can tag a server as `production`, `gpu`, or `high-performance` to direct specific tasks to the appropriate nodes.
Configuring Docker-in-Docker and working with containers
Most modern CI/CD pipelines use Docker to build images or run tests in isolated environments. For
github actions self-hosted to interact with Docker, you must correctly configure access rights and install Docker Engine on the host machine.
Installing Docker for the runner
sudo apt install -y docker.io
sudo usermod -aG docker github-runner
# Restart to apply permissions
sudo systemctl restart docker
Using Docker on a self-hosted runner provides the advantage of a local image registry. If you frequently rebuild the same microservices, Docker layers will be taken from the local cache at `/var/lib/docker`, which practically eliminates `docker pull` time. To manage secrets and access to private registries, it is convenient to use self-hosted Bitwarden integrated into the build process.
Security: Docker Socket vs Rootless
By default, the runner uses `/var/run/docker.sock`. This gives processes inside the container root privileges on the host machine. If your CI/CD runs code from external Pull Requests, this creates a security risk. In such cases, it is recommended to use `Docker Rootless mode` or run the runner in `ephemeral` mode (one-time use), which deletes all data after the task is completed.
Comparison with GitLab Runner: architectural differences on VPS
Although the architecture of GitHub Actions and GitLab CI is similar,
gitlab runner offers more flexible scaling options on a single server. In GitLab, a single binary can manage multiple parallel build threads (executors).
Advantages of GitLab Runner for CI/CD
- Executors: Ability to choose between Shell, Docker, VirtualBox, or Kubernetes directly in the runner config.
- Auto-scaling: GitLab Runner can automatically create additional VPS instances as load increases and delete them afterward.
- Integration: Deep connection with Container Registry and Kubernetes clusters.
For stable GitLab Runner operation on a VPS, it is recommended to allocate at least 2 GB of RAM for each parallel build thread (concurrent job). If you plan complex workflow automation, consider self-hosted n8n to link CI/CD with external APIs and notifications.
Security and isolation of self-hosted runner vps
The main risk of using a
self-hosted runner vps is the execution of arbitrary code. If an attacker sends a Pull Request with malicious code in `.github/workflows/build.yml`, they could gain access to the server's file system and your secrets (API keys, database passwords).
Server protection strategies
- Separate VM: Never run a runner on the server where your main production environment is running. Use a separate VPS instance.
- Privilege restriction: Run the runner process from a user without sudo privileges.
- Network filtering: Configure a Firewall (UFW) to allow only outgoing connections to GitHub and deny incoming ones on all ports except SSH.
- Regular cleanup: Use Cron jobs on VPS to automatically clean up old Docker images and temporary build files.
To clean the system of Docker junk, you can add the following task to crontab:
0 3 * * * /usr/bin/docker system prune -af --volumes
This will delete unused data daily at 3 AM, preventing the disk from filling up.
Performance optimization: squeezing the most out of the hardware
To achieve a 10x speedup, simply installing an
actions runner is not enough. You need to optimize the pipeline structure itself.
Using a RAM disk for temporary files
If your project generates thousands of small files during compilation, using a RAM disk (tmpfs) can significantly speed up the process. Allocate part of the RAM to `/tmp` or a specific build folder.
Local dependency cache
Instead of the standard `actions/cache`, which downloads archives from the network, configure your tools to use local paths on the VPS disk. For Node.js, this could be the global npm cache:
npm config set cache /home/github-runner/.npm --global
This eliminates network latency and load on the communication channel.
Monitoring and infrastructure maintenance
A self-hosted solution requires supervision. Key metrics to track: free disk space, RAM usage, and CPU load (Load Average).
Automatic runner updates
GitHub automatically updates the runner binaries, but system dependencies (git, docker, python) must be updated manually or via automation scripts. It is recommended to set up notifications for runner process failures. The simplest way is to use a systemd unit that automatically restarts the service upon failure.
[Unit]
Description=GitHub Action Runner
After=network.target
[Service]
Type=simple
User=github-runner
WorkingDirectory=/home/github-runner/actions-runner
ExecStart=/home/github-runner/actions-runner/run.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
This configuration ensures that your
ci cd vps will be available 24/7. For storing documentation on your CI/CD processes and server configurations,
self-hosted Nextcloud is an excellent choice, where the team can collaboratively edit files and instructions.
Conclusions
For stable CI/CD operation based on GitHub Actions self-hosted runner, a VPS with 4-8 GB of RAM and an NVMe drive is best suited, allowing you to reduce build times significantly and maintain full control over data security. Using your own server removes limits on free minutes and provides the opportunity for deep caching optimization to speed up development.
Ready to choose a server?
VPS and dedicated servers in 72+ countries with instant activation and full root access.
Start Now →