Post

Jenkins kickstart

🧰 What is Jenkins?

Jenkins is an open-source automation server written in Java. It helps automate the parts of software development related to building, testing, and deploying, facilitating continuous integration (CI) and continuous delivery (CD).

Originally developed as Hudson, Jenkins has grown to support a vast plugin ecosystem and works well with all major tools in the DevOps ecosystem including Git, Docker, Kubernetes, Ansible, and many more.

🌐 Jenkins in the DevOps Lifecycle

In the DevOps pipeline, Jenkins plays a central role by automating:

  • Code Integration (CI)
  • Testing (unit/integration)
  • Building artifacts
  • Deployment (CD)
  • Monitoring and post-deployment scripts

This automation reduces manual effort, increases speed, and improves consistency across development and production environments.

Example: A developer pushes code to GitHub → Jenkins automatically triggers a build → runs tests → deploys to staging → notifies via Slack.

⏰ Jenkins Triggers Explained

Triggers are ways to automate builds based on events. Here’s a detailed guide on how to set up different types of triggers in Jenkins:

✅ 1. Trigger Builds Remotely (e.g., from scripts)

This option allows you to trigger builds using a simple HTTP request:

  1. In your job configuration, select “Trigger builds remotely”
  2. Provide an authentication token (e.g., token1) - this should be unique
  3. Jenkins will provide a URL in this format: JENKINS_URL/job/jobname/build?token=TOKEN_NAME
  4. Replace with your actual values:
    • Example: http://<server_ip>:8080/job/job4/build?token=token1
  5. You can trigger the build by:
    • Opening this URL in any browser
    • Using curl with API token: curl -l -u admin:<apiToken> http://<publicIP>:8080/job/CloneRepo/build?token=token1

✅ 2. GitHub Hook Trigger for GITScm Polling

Automatically trigger builds when changes are pushed to GitHub:

  1. In Jenkins job configuration, select “GitHub hook trigger for GITScm polling”
  2. Save the job configuration
  3. Go to your GitHub repository settings
  4. Select “Webhooks” on the left side
  5. Delete any existing webhooks if necessary
  6. Click “Create webhook” on the right side
  7. Configure the webhook:
    • Payload URL: http://your-jenkins-url/github-webhook/ (e.g., http://<server_ip>:8080/github-webhook/)
    • Content type: Select application/json
    • Secret: No value needed
    • For “Which events would you like to trigger this webhook?”, select “Just the push event”
    • Ensure “Active” is selected
  8. Click “Add webhook”

Now, whenever you make changes to your repository, Jenkins will automatically trigger a new build.

✅ 3. Build Periodically (Cron Jobs)

Schedule builds to run at specific times:

  1. In job configuration, select “Build periodically”
  2. Enter a cron expression (e.g., */2 * * * * to run every 2 minutes)
  3. Save the configuration

Jenkins will automatically generate builds according to the schedule you specified.

✅ 4. Poll SCM

This option checks for changes in your source code repository at regular intervals:

  1. Configure your job with source code management (e.g., Git)
    • Example repository: https://github.com/githubusername/repo
  2. Select “Poll SCM” under Build Triggers
  3. Enter a cron expression (e.g., * * * * * to check every minute)

Unlike “Build periodically”, this will only generate a build when changes are detected in the repository.

✅ 5. Upstream/Downstream Triggers

Chain jobs together:

  • Upstream triggers downstream once completed
  • Useful in multi-stage pipelines
    1
    
    build job: 'downstream-job-name'
    

🧪 Parameters in Jenkins Jobs

Parameters let you customize job behavior during runtime.

Freestyle Parameters

  • Go to Configure → This project is parameterized
  • Add parameters like:
    • String Parameter (e.g., ENVIRONMENT = staging)
    • Choice Parameter (e.g., BRANCH = dev/test/prod)
1
2
#!/bin/bash
echo "Deploying to $ENVIRONMENT"

You can also reference parameters in Pipeline scripts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pipeline {
    agent any

    parameters {
        string(name: 'USERNAME', defaultValue: 'admin')
    }
    stages {
        stage('Echo Username') {
            steps {
                echo "Hello ${params.USERNAME}"
            }
        }
    }
}

parameters in Pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
pipeline {
    agent any

    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')

        // Additional parameters
        run(name: 'RUN_PARAM', description: 'Select a build to use')  // Select a build from another job
        file(name: 'FILE_PARAM', description: 'Upload a file')       // Upload a file
        credentials(name: 'CREDENTIALS_PARAM', description: 'Select credentials') // Select Jenkins stored credentials
        booleanParam(name: 'FLAG', defaultValue: false, description: 'A simple flag')
        string(name: 'EMAIL', defaultValue: '', description: 'User email address')
        text(name: 'NOTES', defaultValue: '', description: 'Additional notes')
    }

    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"
                echo "Biography: ${params.BIOGRAPHY}"
                echo "Toggle: ${params.TOGGLE}"
                echo "Choice: ${params.CHOICE}"
                echo "Password: ${params.PASSWORD}"
                echo "Run param: ${params.RUN_PARAM}"
                echo "File param: ${params.FILE_PARAM}"
                echo "Credentials param: ${params.CREDENTIALS_PARAM}"
                echo "Flag: ${params.FLAG}"
                echo "Email: ${params.EMAIL}"
                echo "Notes: ${params.NOTES}"
            }
        }
    }
}

🗺️ Groovy Map Variables

Map variables are useful for structured data or lookups inside pipelines.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Script 1: Example Map Usage
pipeline {
    agent any

    stages {
        stage('Example') {
            steps {
                script {
                    def myMap = [
                        name: 'Alice',
                        city: 'New York',
                        job: 'Developer'
                    ]

                    echo "Name: ${myMap.name}"
                    echo "City: ${myMap['city']}"
                    echo "Job: ${myMap.job}"
                }
            }
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Script 2: Deploy with Config Map
def config = [
  dev : "10.0.0.1",
  prod: "10.0.0.2"
]

pipeline {
    agent any
    parameters {
        choice(name: 'ENV', choices: ['dev', 'prod'], description: 'Select Environment')
    }
    stages {
        stage('Deploy') {
            steps {
                script {
                    def selected_ip = config[params.ENV]
                    echo "Deploying to IP: ${selected_ip}"
                }
            }
        }
    }
}

Pipeline Project

Jenkins is a core DevOps tool that automates the CI/CD lifecycle. Whether you’re deploying a basic Freestyle job or a full-blown multibranch pipeline, Jenkins supports it all.

Mastering Jenkins triggers, parameters, and build types will give you a significant advantage in automating your delivery processes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello, Jenkins!'
            }
            post {
                always {
                    echo 'This will always run after the stage.'
                }
                success {
                    echo 'This runs only if the stage succeeds.'
                }
                failure {
                    echo 'This runs only if the stage fails.'
                }
            }
        }
    }
}

🔌 Jenkins Plugins

Jenkins’ power comes from its extensive plugin ecosystem. Here’s how to install and use plugins effectively.

There are two ways to install Jenkins plugins:

Method 1: Through the Jenkins UI

  1. Navigate to Manage JenkinsManage Plugins
  2. Click on the Available tab
  3. Use the search box to find your desired plugin
  4. Check the box next to the plugin name
  5. Click Install without restart or Download now and install after restart
  6. If needed, restart Jenkins after installation

Method 2: Using Jenkins CLI

1
java -jar jenkins-cli.jar -s http://your-jenkins-url/ install-plugin plugin-name

Warnings Plugin Installation

The Warnings Next Generation plugin is a powerful tool for static code analysis that can parse and visualize warnings from various tools.

  1. Go to Manage JenkinsManage PluginsAvailable
  2. Search for “Warnings Next Generation”
  3. Check the box and click Install without restart

Maven with Warnings Plugin

Here’s an example of integrating the Warnings plugin in a pipeline:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        
        stage('Static Analysis') {
            steps {
                // Run static analysis tools
                sh 'mvn checkstyle:checkstyle pmd:pmd spotbugs:spotbugs'
            }
            post {
                always {
                    // Process the results using Warnings NG plugin
                    recordIssues(
                        tools: [
                            checkStyle(pattern: '**/checkstyle-result.xml'),
                            pmdParser(pattern: '**/pmd.xml'),
                            spotBugs(pattern: '**/spotbugsXml.xml')
                        ],
                        qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]],
                        healthy: 10,
                        unhealthy: 100,
                        minimumSeverity: 'HIGH'
                    )
                }
            }
        }
    }
}

Python with Warnings Plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Setup Python') {
            steps {
                sh 'pip install -r requirements.txt'
                sh 'pip install pylint flake8'
            }
        }
        
        stage('Static Analysis') {
            steps {
                sh 'pylint --output-format=parseable --reports=no *.py > pylint.log || true'
                sh 'flake8 --format=pylint *.py > flake8.log || true'
            }
            post {
                always {
                    recordIssues(
                        tools: [
                            pyLint(pattern: 'pylint.log'),
                            flake8(pattern: 'flake8.log')
                        ],
                        qualityGates: [[threshold: 10, type: 'TOTAL', unstable: true]]
                    )
                }
            }
        }
        
        stage('Test') {
            steps {
                sh 'python -m pytest --junitxml=test-results.xml'
            }
            post {
                always {
                    junit 'test-results.xml'
                }
            }
        }
    }
}

🐳 Jenkins Pipelines with Docker Agent

Docker agents allow you to run your pipeline steps inside Docker containers, providing isolated and consistent environments for your builds.

Setting Up Docker Integration

Prerequisites

  1. Connect to your Jenkins server via terminal:
    1
    2
    
    sudo su -
    apt-get update && apt-get install docker.io
    
  2. Install the Docker Pipeline plugin:
    • Navigate to Manage JenkinsManage PluginsAvailable
    • Search for “Docker Pipeline”
    • Select it and click Install
    • After installation, restart Jenkins:
      1
      
      systemctl restart jenkins
      
  3. Configure Docker permissions:
    1
    2
    3
    4
    
    # Add jenkins user to docker group
    usermod -aG docker jenkins
    # Restart Jenkins service
    systemctl restart jenkins
    

Maven Docker Agent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pipeline {
    agent {
        docker {
            image 'maven:3.8.6-openjdk-11'
            args '-v $HOME/.m2:/root/.m2'
        }
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn -B clean package'
            }
        }
        
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit '**/target/surefire-reports/TEST-*.xml'
                }
            }
        }
    }
}

Python Docker Agent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
pipeline {
    agent {
        docker {
            image 'python:3.9'
            args '-v ${WORKSPACE}:/app -w /app'
        }
    }
    
    stages {
        stage('Setup') {
            steps {
                sh 'pip install -r requirements.txt'
                sh 'pip install pytest pytest-cov'
            }
        }
        
        stage('Test') {
            steps {
                sh 'python -m pytest --cov=. --cov-report=xml'
            }
            post {
                always {
                    junit 'test-results.xml'
                    recordCoverage(
                        tools: [[parser: 'COBERTURA', pattern: 'coverage.xml']],
                        qualityGates: [[threshold: 80, metric: 'LINE', unstable: true]]
                    )
                }
            }
        }
    }
}

Docker Multi-Stage Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pipeline {
    agent none
    
    stages {
        stage('Build') {
            agent {
                docker {
                    image 'node:14'
                    args '-v ${WORKSPACE}:/app -w /app'
                }
            }
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }
        
        stage('Test') {
            agent {
                docker {
                    image 'node:14'
                    args '-v ${WORKSPACE}:/app -w /app'
                }
            }
            steps {
                sh 'npm test'
            }
        }
        
        stage('Deploy') {
            agent {
                docker {
                    image 'amazon/aws-cli:latest'
                    args '--entrypoint=""'
                }
            }
            steps {
                sh 'aws s3 sync ./build s3://my-bucket/'
            }
        }
    }
}

📢 Jenkins Notifications

Notifications keep your team informed about build and deployment status. Here’s how to set up different notification systems.

Slack Integration

Installing Slack Plugin

  1. Go to Manage JenkinsManage PluginsAvailable
  2. Search for “Slack Notification”
  3. Install the plugin and restart Jenkins if needed

Configuring Slack Integration

  1. Create a Slack app and get the token:
    • Go to https://api.slack.com/apps
    • Click Create New AppFrom scratch
    • Name your app (e.g., “Jenkins Notifications”) and select your workspace
    • Navigate to OAuth & PermissionsBot Token Scopes
    • Add scopes: chat:write, files:write, channels:read
    • Install the app to your workspace
    • Copy the Bot User OAuth Token
  2. Configure Jenkins:
    • Go to Manage JenkinsConfigure System
    • Find the Slack section
    • Enter your Workspace name
    • Add credentials (Secret text) with the Bot User OAuth Token
    • Specify default channel (e.g., #jenkins-builds)
    • Test the connection

Using Slack in Pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
    
    post {
        success {
            slackSend(
                color: 'good',
                message: "✅ Build Successful: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
            )
        }
        failure {
            slackSend(
                color: 'danger',
                message: "❌ Build Failed: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
            )
        }
        unstable {
            slackSend(
                color: 'warning',
                message: "⚠️ Build Unstable: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
            )
        }
    }
}

Discord Integration

Installing Discord Plugin

  1. Go to Manage JenkinsManage PluginsAvailable
  2. Search for “Discord Notifier”
  3. Install the plugin and restart Jenkins if needed

Configuring Discord Integration

  1. Create a Discord webhook:
    • Open Discord and go to the server where you want to receive notifications
    • Go to Server SettingsIntegrationsWebhooks
    • Click New Webhook
    • Name it (e.g., “Jenkins Notifications”)
    • Select the channel for notifications
    • Copy the Webhook URL
  2. Configure Jenkins:
    • Go to Manage JenkinsConfigure System
    • Find the Discord Notifier section
    • Enter the Webhook URL
    • Configure other settings as needed

Using Discord in Pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
    
    post {
        always {
            discordSend(
                description: "Jenkins Build ${currentBuild.currentResult}",
                link: env.BUILD_URL,
                result: currentBuild.currentResult,
                title: "${env.JOB_NAME} #${env.BUILD_NUMBER}",
                webhookURL: 'https://discord.com/api/webhooks/your-webhook-url'
            )
        }
    }
}

🔍 SonarQube Integration with Jenkins

SonarQube provides continuous code quality inspection. Here’s how to integrate it with Jenkins.

Setting Up SonarQube

Installing SonarQube

  1. Using Docker (recommended):
    1
    
    docker run -d --name sonarqube -p 9000:9000 sonarqube:latest
    
  2. Access SonarQube at http://your-server:9000
    • Default credentials: admin/admin
    • You’ll be prompted to change the password on first login

Creating a SonarQube Project and Token

  1. Log in to SonarQube
  2. Go to AdministrationProjectsCreate Project
  3. Enter a project key and name
  4. Go to AdministrationSecurityUsers
  5. Click on your username → TokensGenerate
  6. Name your token (e.g., “jenkins-integration”) and click Generate
  7. Copy the generated token (you won’t be able to see it again)

Jenkins Configuration

Installing SonarQube Scanner Plugin

  1. Go to Manage JenkinsManage PluginsAvailable
  2. Search for “SonarQube Scanner”
  3. Install the plugin and restart Jenkins if needed

Configuring SonarQube in Jenkins

  1. Go to Manage JenkinsConfigure System
  2. Find the SonarQube servers section
  3. Click Add SonarQube
  4. Enter a name (e.g., “SonarQube”)
  5. Enter the SonarQube URL (e.g., http://your-server:9000)
  6. Add the SonarQube authentication token as a Jenkins credential
  7. Select the credential in the dropdown
  8. Save the configuration

Adding SonarQube Scanner Tool

  1. Go to Manage JenkinsGlobal Tool Configuration
  2. Find the SonarQube Scanner section
  3. Click Add SonarQube Scanner
  4. Enter a name (e.g., “SonarQube Scanner”)
  5. Choose Install automatically or specify the path to your installation
  6. Save the configuration

SonarQube in maven

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
pipeline {
    agent any
    
    tools {
        maven 'Maven 3.8.6'
        jdk 'JDK 11'
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
        
        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar -Dsonar.projectKey=my-project -Dsonar.projectName="My Project"'
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }
}

SonarQube with Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh '''
                        sonar-scanner \
                        -Dsonar.projectKey=python-project \
                        -Dsonar.projectName="Python Project" \
                        -Dsonar.sources=. \
                        -Dsonar.python.coverage.reportPaths=coverage.xml \
                        -Dsonar.python.xunit.reportPath=test-results.xml
                    '''
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }
}

🔄 Backup of Jenkins Server

Regular backups are essential for Jenkins high availability and disaster recovery.

  1. JENKINS_HOME directory: Contains all configuration, job definitions, build history, and plugins
  2. Global configuration files: config.xml, credentials.xml, etc.
  3. Job configurations: Located in $JENKINS_HOME/jobs/
  4. User content: Located in $JENKINS_HOME/users/
  5. Plugins: Located in $JENKINS_HOME/plugins/

Method 1: File System Backup

  1. Stop Jenkins service:
    1
    
    systemctl stop jenkins
    
  2. Backup the JENKINS_HOME directory:
    1
    
    tar -czf jenkins_backup_$(date +%Y%m%d).tar.gz /var/lib/jenkins
    
  3. Start Jenkins service:
    1
    
    systemctl start jenkins
    
  4. Transfer the backup to a secure location:
    1
    
    scp jenkins_backup_*.tar.gz backup-server:/backup/jenkins/
    

Method 2: Using Jenkins Backup Plugin

  1. Install the “Backup Plugin”:
    • Go to Manage JenkinsManage PluginsAvailable
    • Search for “Backup Plugin”
    • Install the plugin and restart Jenkins if needed
  2. Configure the backup:
    • Go to Manage JenkinsBackup Manager
    • Configure backup settings:
      • Backup directory
      • Backup contents (jobs, plugins, configurations)
      • Backup schedule
      • Retention policy
  3. Run a manual backup or wait for the scheduled backup

Method 3: Using ThinBackup Plugin

  1. Install the “ThinBackup Plugin”:
    • Go to Manage JenkinsManage PluginsAvailable
    • Search for “ThinBackup”
    • Install the plugin and restart Jenkins if needed
  2. Configure ThinBackup:
    • Go to Manage JenkinsThinBackup
    • Set the backup directory
    • Configure backup settings:
      • Backup schedule
      • What to backup (configurations, plugins, build results)
      • Retention policy
  3. Run a manual backup or wait for the scheduled backup

Automated Backup Script

Create a script for automated backups:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash

# Configuration
JENKINS_HOME="/var/lib/jenkins"
BACKUP_DIR="/backup/jenkins"
BACKUP_COUNT=7  # Number of backups to keep

# Create backup filename with date
BACKUP_FILE="$BACKUP_DIR/jenkins_backup_$(date +%Y%m%d).tar.gz"

# Ensure backup directory exists
mkdir -p $BACKUP_DIR

# Stop Jenkins service
systemctl stop jenkins

# Create backup
tar -czf $BACKUP_FILE $JENKINS_HOME

# Start Jenkins service
systemctl start jenkins

# Remove old backups, keeping only the most recent $BACKUP_COUNT
ls -t $BACKUP_DIR/jenkins_backup_*.tar.gz | tail -n +$((BACKUP_COUNT+1)) | xargs -r rm

# Log the backup
echo "Jenkins backup completed: $BACKUP_FILE" >> $BACKUP_DIR/backup.log

Add this script to crontab to run automatically:

1
2
3
4
5
# Edit crontab
crontab -e

# Add this line to run backup every Sunday at 2 AM
0 2 * * 0 /path/to/jenkins_backup.sh

Restoring from Backup

  1. Stop Jenkins service:
    1
    
    systemctl stop jenkins
    
  2. Remove or rename the current Jenkins home directory:
    1
    
    mv /var/lib/jenkins /var/lib/jenkins.old
    
  3. Extract the backup:
    1
    2
    
    mkdir -p /var/lib/jenkins
    tar -xzf jenkins_backup_YYYYMMDD.tar.gz -C /
    
  4. Fix permissions:
    1
    
    chown -R jenkins:jenkins /var/lib/jenkins
    
  5. Start Jenkins service:
    1
    
    systemctl start jenkins
    
This post is licensed under CC BY 4.0 by the author.