Building a Self-Hosted CI/CD Pipeline on a Linux VPS for Pakistani Software Agencies
As the software development industry in Pakistan scales rapidly, agencies are managing increasingly complex applications that demand rigorous testing, continuous integration, and continuous deployment (CI/CD). Relying on cloud-based, multi-tenant SaaS CI/CD tools (like GitHub Actions or GitLab CI SaaS) often introduces unpredictable billing, shared-runner queues, and bandwidth bottlenecks—especially when pulling or pushing massive Docker images from local networks in Karachi, Lahore, or Islamabad.
By migrating to a self-hosted CI/CD pipeline on a robust Linux VPS, DevOps teams can eliminate queue times, strictly control security environments, and dramatically reduce costs for compute-intensive build jobs. In this comprehensive guide, we will walk through the architecture, configuration, and optimization of a self-hosted CI/CD pipeline using Jenkins and GitLab Runner on an NVMe-powered Linux VPS.
Why Self-Host Your CI/CD in Pakistan?
- Unrestricted Build Minutes: Avoid arbitrary limits on pipeline execution time. Pay only for the VPS infrastructure, regardless of how many pipelines run daily.
- Eliminate Shared Runner Queues: Dedicated compute means jobs start instantly, accelerating developer feedback loops.
- Data Sovereignty & Security: Keep proprietary source code, credentials, and artifacts entirely within your controlled infrastructure.
- Local Network Proximity: Hosting your runners on infrastructure closer to your developers can drastically speed up artifact downloads and code deployments.
For large-scale enterprise deployments involving heavy high-concurrency builds or extensive parallel testing environments, typical VPS instances might hit CPU or RAM bottlenecks. In such cases, software agencies often upgrade to Dedicated Servers. Furthermore, utilizing Dedicated Servers in Pakistan provides the bare-metal processing power and unmetered network throughput required for executing hundreds of Docker-in-Docker (DinD) CI pipelines simultaneously without missing a beat.
Step 1: Provisioning the Linux VPS
For a reliable CI/CD controller and runner node, we recommend the following minimum specifications:
- OS: Ubuntu 24.04 LTS
- CPU: 4 vCores (for compiling code and running Docker)
- RAM: 8 GB (Jenkins JVM and concurrent GitLab Runners are memory-intensive)
- Storage: 80 GB+ NVMe SSD (for fast I/O during npm install, Maven builds, and Docker layer caching)
Update your system immediately after provisioning:
sudo apt update && sudo apt upgrade -y
Step 2: Installing and Securing Jenkins
Jenkins remains the industry standard for extensive, highly customizable automation pipelines.
1. Install Java Development Kit
Jenkins requires Java to run.
sudo apt install fontconfig openjdk-17-jre -y
2. Add Jenkins Repository and Install
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/" | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins -y
3. Start Jenkins and Retrieve Admin Password
sudo systemctl enable --now jenkins
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Use the output password to unlock Jenkins via the web UI (http://<YOUR_VPS_IP>:8080). Complete the setup wizard by installing the suggested plugins and creating an admin user.
Step 3: Deploying GitLab Runner for Docker Environments
If your agency uses GitLab, hosting your own GitLab Runner is a massive upgrade over shared runners. We will deploy the runner in Docker execution mode.
1. Install Docker Engine
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
2. Install GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner -y
3. Register the Runner
Navigate to your GitLab Project/Group Settings -> CI/CD -> Runners, and copy the registration token.
sudo gitlab-runner register \
--non-interactive \
--url "https://gitlab.com/" \
--registration-token "YOUR_REGISTRATION_TOKEN" \
--executor "docker" \
--docker-image alpine:latest \
--description "VPS-Runner-Pak-Agency" \
--tag-list "docker,vps,pakistan" \
--run-untagged="true" \
--locked="false"
Step 4: Optimizing CI/CD Performance
Enable Docker Layer Caching
In your .gitlab-ci.yml, ensure Docker image layers are cached to drastically reduce build times for Node.js or Python projects:
variables:
DOCKER_DRIVER: overlay2
DOCKER_BUILDKIT: 1
build_image:
image: docker:24.0.5
services:
- docker:24.0.5-dind
script:
- docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
Concurrency Tuning
By default, GitLab Runner processes one job at a time. To utilize your VPS’s multi-core CPU efficiently, edit /etc/gitlab-runner/config.toml:
concurrent = 4 # Adjust based on VPS vCores
check_interval = 0
Restart the runner:
sudo systemctl restart gitlab-runner
Conclusion
By architecting a self-hosted Jenkins or GitLab Runner CI/CD pipeline on a Linux VPS, Pakistani software agencies can gain absolute control over their deployment pipelines, eliminate unpredictable SaaS costs, and achieve faster build times. As your team grows, remember that migrating to higher-tier dedicated infrastructure ensures that your automation capabilities can scale linearly with your agency’s success.
