For our Blog Visitor only Get Additional 3 Month Free + 10% OFF on TriAnnual Plan YSBLOG10
Grab the Deal

How to Install CI/CD on Linux Server for 2026: (Step-by-Step Guide)

To install CI/CD on a Linux server, choose a CI engine (Jenkins, GitLab Runner, or a GitHub Actions self‑hosted runner), install prerequisites (Git, Docker/Java), register the runner or set up the server, connect your repository via SSH/webhooks, define a pipeline file (Jenkinsfile or YAML), secure the host(firewall/HTTPS), and run builds as services.

In this guide, you’ll learn how to install CI/CD on a Linux server step-by-step, using industry-proven methods. We’ll cover Jenkins, GitLab CI, and GitHub Actions self-hosted runners, add Docker for clean builds, secure everything with Nginx and Let’s Encrypt, and share practical tips learned from 12+ years of managing production servers.

What is CI/CD and Why Install it on a Linux Server?

What Is CI/CD and Why Install It on a Linux Server?

CI/CD (Continuous Integration/Continuous Delivery) automates building, testing, and deploying code. Installing CI/CD on a Linux server gives you control, data sovereignty, predictable costs, and the flexibility to build on your own infrastructure. It’s ideal for teams needing custom tooling, on-prem compliance, or optimized performance close to production.

Search Intent and What You’ll Achieve

This tutorial targets informational and how-to intent: you want a clear, actionable way to install CI/CD on Linux. By the end, you’ll have a secure, production-ready CI/CD pipeline using your preferred stack, plus best practices for performance, security, and reliability.

Prerequisites and System Requirements

We’ll use Ubuntu 22.04 LTS in examples, but commands are similar for Debian-based systems. Red Hat/CentOS/AlmaLinux users can adapt with yum/dnf. Always run as a non-root sudo user unless noted.

Minimum Server Sizing

  • Small teams: 2 vCPU, 4 GB RAM, 40–80 GB SSD
  • Medium teams/containers: 4 vCPU, 8–16 GB RAM, 100–200 GB SSD
  • Heavy builds (Java/Android): 8+ vCPU, 16–32 GB RAM, fast NVMe

Networking, Ports, and DNS

  • Open ports: 22 (SSH), 80/443 (HTTP/HTTPS), 8080 (Jenkins, if direct)
  • Set an A record, e.g., ci.example.com, to your server IP
  • Use HTTPS with Let’s Encrypt for secure access

Required Packages and Access

  • Sudo user with SSH access
  • Git, cURL, and optionally Docker
  • Firewall control (ufw) and basic Linux familiarity

Choose Your CI/CD Engine

Jenkins (Self-Hosted CI/CD Server)

  • Pros: Extremely flexible, huge plugin ecosystem, great for complex pipelines
  • Cons: More maintenance, Java dependency, plugins require governance

GitLab CI (Runner on Your Server)

  • Pros: Native to GitLab, simple YAML, scalable runners
  • Cons: Requires GitLab (cloud or self-managed); features vary by plan

GitHub Actions (Self-Hosted Runner)

  • Pros: Tight GitHub integration, easy YAML, use your own hardware
  • Cons: Administration of runners, job isolation requires attention

If you need maximum customization, choose Jenkins. If you already use GitLab, install a GitLab Runner. If your code lives on GitHub, a self-hosted Actions runner is straightforward.

Architecture Overview

  • Public CI endpoint behind Nginx reverse proxy with HTTPS
  • Workers as services (Jenkins agents or GitLab/GitHub runners)
  • Docker for clean, reproducible builds
  • SSH deploy keys to production or a staging server

How to Install CI/CD on Linux Server (Step-by-Step)

Base Setup (All Options)

sudo apt update && sudo apt -y upgrade
sudo apt -y install git curl unzip ca-certificates gnupg lsb-release ufw

# Secure SSH (optional basics)
sudo ufw allow OpenSSH
sudo ufw enable

# Create a build user (optional good practice)
sudo adduser ci --gecos "CI User,,," --disabled-password
sudo usermod -aG sudo ci

Option A: Install Jenkins on Ubuntu

Install Java and Jenkins

# Java (Temurin or OpenJDK)
sudo apt -y install fontconfig openjdk-17-jre

# Jenkins repository
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
/usr/share/keyrings/jenkins-keyring.asc > /dev/null
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 update
sudo apt -y install jenkins

# Enable and open firewall
sudo systemctl enable --now jenkins
sudo ufw allow 8080/tcp

Initial Setup

# Get admin password
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Visit http://SERVER_IP:8080, enter the password, install recommended plugins, and create an admin user. For production, place Jenkins behind Nginx with HTTPS (see the Nginx section below) and disable direct port 8080 externally.

Sample Jenkinsfile

pipeline {
  agent any
  options { skipDefaultCheckout(false) }
  stages {
    stage('Checkout') {
      steps { checkout scm }
    }
    stage('Build') {
      steps { sh 'docker build -t myapp:ci .' }
    }
    stage('Test') {
      steps { sh 'docker run --rm myapp:ci npm test' }
    }
    stage('Deploy') {
      when { branch 'main' }
      steps { sh './deploy/scripts/deploy.sh' }
    }
  }
  post {
    always { archiveArtifacts artifacts: 'logs/**', onlyIfSuccessful: false }
  }
}

Store this Jenkinsfile at your repo root and configure a Multibranch Pipeline or a Pipeline job pointing to your SCM with webhooks for automatic builds.

Option B: Install GitLab Runner on Ubuntu

Use this if your repository is hosted on GitLab. You’ll register the runner with a project or the whole GitLab instance.

Install and Register GitLab Runner

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt -y install gitlab-runner

# Register (get token from GitLab: Settings > CI/CD > Runners)
sudo gitlab-runner register
# Enter:
# GitLab URL: https://gitlab.com/ (or your self-managed URL)
# Registration token: <TOKEN>
# Description: ubuntu-runner
# Tags: docker,linux
# Executor: docker (recommended) or shell

For Docker executor, define a default image and enable Docker in Docker or bind the host Docker socket, depending on your security model.

Sample .gitlab-ci.yml

image: node:20-alpine

stages:
  - build
  - test
  - deploy

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/

build:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

test:
  stage: test
  script:
    - npm test -- --ci

deploy:
  stage: deploy
  only:
    - main
  script:
    - ./deploy/scripts/deploy.sh

Option C: Install a GitHub Actions Self-Hosted Runner

Perfect if your code is on GitHub and you want to run Actions on your own hardware.

Install and Configure Runner

# Create a runner directory
mkdir -p ~/actions-runner && cd ~/actions-runner

# Download the latest runner from GitHub (replace version as needed)
curl -o actions-runner.tar.gz -L https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz
tar xzf actions-runner.tar.gz

# In GitHub: Repo Settings > Actions > Runners > New self-hosted runner to get URL/TOKEN
./config.sh --url https://github.com/ORG/REPO --token YOUR_TOKEN

# Install as a service
sudo ./svc.sh install
sudo ./svc.sh start

Sample GitHub Workflow

name: CI

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  build-test:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm test -- --ci

Add Docker for Clean, Reproducible Builds

Install Docker Engine

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
# Re-login to apply group membership

Use Docker images per language (node, python, maven, golang) for consistent builds. In Jenkins, add the Docker Pipeline plugin or run shell steps. In GitLab CI/GitHub Actions, select an appropriate container image in YAML.

Reverse Proxy and HTTPS with Nginx + Let’s Encrypt

Install and Configure Nginx

sudo apt -y install nginx
sudo ufw allow 'Nginx Full'

# Example for Jenkins at localhost:8080 (adjust server_name)
sudo tee /etc/nginx/sites-available/ci.conf >/dev/null <<'EOF'
server {
  listen 80;
  server_name ci.example.com;

  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}
EOF

sudo ln -s /etc/nginx/sites-available/ci.conf /etc/nginx/sites-enabled/ci.conf
sudo nginx -t && sudo systemctl reload nginx

Add Let’s Encrypt TLS

sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx -d ci.example.com --redirect --agree-tos -m admin@example.com

After enabling HTTPS, close external access to port 8080 and expose only 80/443 through Nginx.

Security Hardening Essentials

  • Least privilege: run CI services under dedicated users
  • Firewall: allow only SSH and HTTP/HTTPS; restrict internal ports
  • SSH hardening: key-based auth, disable root login, change default port if policy allows
  • Secrets: store tokens/keys in Jenkins Credentials, GitLab CI Variables, or GitHub Secrets
  • Isolation: prefer Docker executor over shell; consider ephemeral runners
  • Updates: automate system and container image updates; patch weekly
  • Backups: backup Jenkins $JENKINS_HOME, runner configs, and Nginx/SSL data

Test Your Pipeline End-to-End

Push a small code change or a commit that updates tests. Confirm the CI job triggers automatically, runs build and tests, and deploys to staging. Check logs, artifacts, and any notifications (email/Slack) to ensure visibility.

Troubleshooting Common Issues

Webhooks Do Not Trigger Builds

  • Verify public DNS/HTTPS reachability
  • Confirm webhook secret and correct endpoint
  • Check reverse proxy timeouts and headers

Docker Permission Denied

  • Add runner/jenkins user to docker group: usermod -aG docker
  • Re-login or restart service
  • On hardened hosts, consider rootless Docker with proper ports

Slow Builds

  • Enable dependency caching (node_modules, Maven cache)
  • Use regional mirrors/registries
  • Scale CPU/RAM or use multiple runners/agents

Performance and Cost Optimization

  • Cache smartly: npm, pip, Maven, Gradle caches drastically cut build times
  • Parallelize tests: split tests across multiple executors
  • Ephemeral runners: auto-scale with cloud VMs or Kubernetes
  • Use base images: pre-bake dependencies into Docker images
  • Artifact retention: prune old artifacts and images regularly

When to Choose Managed Infrastructure

If you prefer to focus on development over server ops, consider managed VPS or dedicated servers optimized for CI/CD. YouStable provides NVMe-powered Linux servers with fast networking, IPv4/IPv6, and 24×7 support, making it easy to host Jenkins or runners securely with predictable performance.

Example: Full UFW and Systemd Checks

# Firewall
sudo ufw status
sudo ufw allow 80,443/tcp
sudo ufw delete allow 8080/tcp  # after Nginx/HTTPS is in place

# Services
systemctl status jenkins
systemctl status gitlab-runner
systemctl status nginx

Best Practices Recap

  • Choose the CI engine that matches your VCS (Jenkins/GitLab/GitHub)
  • Secure access with Nginx + Let’s Encrypt
  • Run builds in containers for consistency and isolation
  • Manage secrets centrally; never hardcode credentials
  • Automate updates, backups, and monitoring

FAQ’s: Install CI/CD on Linux Server

Which is better for beginners: Jenkins, GitLab CI, or GitHub Actions?

If your code is on GitHub, Actions is easiest. If you use GitLab, start with GitLab CI runner. Choose Jenkins when you need deep customization, complex pipelines, or vendor-neutral control.

Do I need Docker to install CI/CD on a Linux server?

No, but Docker simplifies dependency management and isolation. Most modern pipelines use containerized builds for reproducibility and security.

How do I secure my CI/CD server?

Use HTTPS with Let’s Encrypt, restrict ports via ufw, disable root SSH, use SSH keys, store secrets in CI vaults, and run builds in non-root containers. Keep your OS and plugins updated.

Can I deploy directly to production from CI?

Yes, but add safeguards: approvals, canary/staged deploys, automated rollbacks, and environment-specific credentials. Many teams deploy to staging on merge and to production on tag or manual approval.

What ports should I open for Jenkins or runners?

Open 80/443 for the web UI via Nginx. Keep 8080 internal for Jenkins. Always allow 22 for SSH. Runners typically initiate outbound connections, so inbound runner ports are rarely required.

How much server resource do I need for CI?

For small teams, 2 vCPU/4 GB RAM is workable. For container-heavy or Java builds, 4–8 vCPU and 8–16 GB RAM is more comfortable. Scale based on concurrency, language, and test suite size.

Where should I host my CI/CD server?

Close to your developers and registries for low latency. A performance-optimized VPS from YouStable with NVMe storage and strong network throughput is a solid starting point for most teams.

With these steps, you can confidently install CI/CD on a Linux server, secure it with best practices, and ship code faster. Whether you prefer Jenkins, GitLab CI, or GitHub Actions, the combination of Docker, Nginx, and vigilant hardening will yield a robust, scalable pipeline.

Prahlad Prajapati

Prahlad is a web hosting specialist and SEO-focused organic growth expert from India. Active in the digital space since 2019, he helps people grow their websites through clean, sustainable strategies. Passionate about learning and adapting fast, he believes small details create big success. Discover his insights on web hosting and SEO to elevate your online presence.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top