Jenkins is the oldest widely-used CI/CD server — open-source, self-hosted, and infinitely extensible through plugins. It remains common in enterprises with strict on-premises requirements.

Jenkins vs GitHub Actions

Aspect Jenkins GitHub Actions
Hosting Self-hosted Cloud (GitHub)
Configuration Jenkinsfile + UI YAML in repo
Plugins 1800+ plugins GitHub Marketplace actions
Setup complexity Higher Lower
Cost Infrastructure + maintenance Free tier + minutes

Choose Jenkins when you need on-premises control, custom agents, or complex enterprise integrations.

Installation

Docker (Quickest)

  docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts-jdk17
  

Get initial admin password:

  docker exec jenkins cat /var/lib/jenkins/secrets/initialAdminPassword
  

Open http://localhost:8080, install suggested plugins, create admin user.

Linux (Package)

  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
sudo apt update
sudo apt install jenkins
sudo systemctl enable jenkins
sudo systemctl start jenkins
  

Declarative Pipeline (Jenkinsfile)

Store pipeline as code in your repository:

  // Jenkinsfile
pipeline {
    agent any

    tools {
        nodejs 'NodeJS-20'
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }

        stage('Lint') {
            steps {
                sh 'npm run lint'
            }
        }

        stage('Test') {
            steps {
                sh 'npm test'
            }
        }

        stage('Build') {
            steps {
                sh 'npm run build'
            }
        }
    }

    post {
        always {
            junit 'test-results/*.xml'
            cleanWs()
        }
        failure {
            mail to: '[email protected]',
                 subject: "Build Failed: ${env.JOB_NAME}",
                 body: "Check ${env.BUILD_URL}"
        }
    }
}
  

Create a Pipeline job in Jenkins pointing to your Git repo — Jenkins reads Jenkinsfile automatically.

Multibranch Pipeline

Automatically discovers branches and PRs:

  1. New Item → Multibranch Pipeline
  2. Add Git source (GitHub, GitLab, Bitbucket)
  3. Build configuration: by Jenkinsfile
  4. Scan triggers: webhook or periodic

Each branch gets its own pipeline run on push.

Agents (Nodes)

Run builds on specific machines:

  pipeline {
    agent {
        label 'docker-agent'
    }
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp .'
            }
        }
    }
}
  

Configure agents in Manage Jenkins → Nodes. Use Docker agents for isolated builds:

  pipeline {
    agent {
        docker {
            image 'node:20-alpine'
        }
    }
    stages {
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
    }
}
  

Essential Plugins

Plugin Purpose
Git Git SCM integration
GitHub Branch Source Multibranch + webhooks
Pipeline Jenkinsfile support
Docker Pipeline Docker agents and builds
JUnit Test result reporting
Blue Ocean Modern pipeline UI
Credentials Binding Inject secrets into builds
SonarQube Scanner Code quality analysis

Install via Manage Jenkins → Plugins.

Credentials and Secrets

Store secrets in Jenkins credential store:

  1. Manage Jenkins → Credentials → Add
  2. Types: Secret text, Username/password, SSH key
  3. Reference in pipeline:
  environment {
    DATABASE_URL = credentials('database-url')
    DOCKER_TOKEN = credentials('docker-hub-token')
}

steps {
    sh 'echo $DATABASE_URL'  // masked in logs
}
  

Never hardcode secrets in Jenkinsfile — use credentials binding.

Webhook Integration

Trigger builds on Git push:

  1. Jenkins job → Build Triggers → GitHub hook trigger
  2. GitHub repo → Settings → Webhooks → Add
    • URL: https://jenkins.example.com/github-webhook/
    • Events: push, pull_request

Parallel Stages

  stage('Test') {
    parallel {
        stage('Unit Tests') {
            steps {
                sh 'npm run test:unit'
            }
        }
        stage('Integration Tests') {
            steps {
                sh 'npm run test:integration'
            }
        }
        stage('Lint') {
            steps {
                sh 'npm run lint'
            }
        }
    }
}
  

Shared Libraries

Reuse pipeline code across projects:

  @Library('my-shared-library') _

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                deployToEnv('staging')
            }
        }
    }
}
  

Backup and Maintenance

  • Backup $JENKINS_HOME (jobs, configs, plugins)
  • Keep Jenkins LTS updated — test in staging first
  • Monitor disk space — build artifacts accumulate
  • Use Configuration as Code (JCasC) plugin for reproducible setup

What Comes Next

Apply pipeline design patterns in CI/CD Best Practices — whether using Jenkins, GitHub Actions, or both in hybrid setups.