Skip to content
Back to Blog
Automation

Jenkins CI/CD for Infrastructure Pipelines

Build Jenkins pipelines for infrastructure automation: Terraform plan/apply, Ansible runs, testing stages, and approval gates.

Nov 2025
15 min read

Introduction

Jenkins is an open-source automation server that enables continuous integration and continuous delivery (CI/CD). For infrastructure teams, Jenkins automates testing of Ansible playbooks, Terraform plans, configuration changes, and deployments. This guide shows you how to set up Jenkins for infrastructure automation.

Installing Jenkins

BASH
# Ubuntu 22.04
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key |   gpg --dearmor -o /usr/share/keyrings/jenkins-keyring.gpg

echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.gpg]   https://pkg.jenkins.io/debian-stable binary/ |   tee /etc/apt/sources.list.d/jenkins.list > /dev/null

apt update
apt install jenkins openjdk-17-jdk

systemctl enable jenkins && systemctl start jenkins

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

Access Jenkins at http://server:8080.

Required Plugins for Infrastructure

  • Pipeline (for Jenkinsfile-based pipelines)
  • Git (source code checkout)
  • Ansible (run Ansible playbooks)
  • Terraform (run Terraform commands)
  • SSH Agent (SSH credential management)
  • Credentials Binding (inject secrets into pipelines)

Setting Up Credentials

TEXT
Jenkins → Manage Jenkins → Credentials → Add Credentials

Types to add:
- SSH Username with private key (for SSH to servers)
- Secret text (for API tokens, passwords)
- Username with password (for Docker registry, etc.)

Basic Jenkinsfile for Ansible

GROOVY
// Jenkinsfile
pipeline {
    agent any

    environment {
        ANSIBLE_HOST_KEY_CHECKING = 'False'
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main',
                    url: 'https://github.com/company/infrastructure.git'
            }
        }

        stage('Syntax Check') {
            steps {
                sh 'ansible-playbook --syntax-check -i inventory/production site.yml'
            }
        }

        stage('Lint') {
            steps {
                sh 'ansible-lint site.yml'
            }
        }

        stage('Dry Run') {
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: 'deploy-key', keyFileVariable: 'SSH_KEY')]) {
                    sh '''
                        ansible-playbook -i inventory/production site.yml --check                           --private-key=$SSH_KEY
                    '''
                }
            }
        }

        stage('Deploy') {
            when {
                branch 'main'
            }
            input {
                message "Deploy to production?"
                ok "Deploy"
            }
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: 'deploy-key', keyFileVariable: 'SSH_KEY')]) {
                    sh '''
                        ansible-playbook -i inventory/production site.yml                           --private-key=$SSH_KEY
                    '''
                }
            }
        }
    }

    post {
        always {
            emailext(
                subject: "Build ${currentBuild.result}: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                body: "${env.BUILD_URL}",
                to: 'team@company.com'
            )
        }
    }
}

Terraform Pipeline

GROOVY
pipeline {
    agent any

    environment {
        TF_IN_AUTOMATION = 'true'
        AWS_ACCESS_KEY_ID = credentials('aws-access-key')
        AWS_SECRET_ACCESS_KEY = credentials('aws-secret-key')
    }

    stages {
        stage('Terraform Init') {
            steps {
                sh 'terraform init -input=false'
            }
        }

        stage('Terraform Plan') {
            steps {
                sh 'terraform plan -out=tfplan -input=false'
                // Save plan as artifact
                archiveArtifacts artifacts: 'tfplan'
            }
        }

        stage('Terraform Apply') {
            when { branch 'main' }
            input { message "Apply Terraform plan?" }
            steps {
                sh 'terraform apply -input=false tfplan'
            }
        }
    }
}

Jenkins Agents (Distributed Build)

BASH
# Add a build agent (on another server)
# Jenkins → Manage Jenkins → Nodes → New Node

# On agent server
java -jar agent.jar   -jnlpUrl http://jenkins:8080/computer/agent1/slave-agent.jnlp   -secret <secret>   -workDir /var/lib/jenkins-agent

Webhook Trigger from Git

GROOVY
// Trigger build on Git push
triggers {
    githubPush()
}

// Or poll for changes every 5 minutes
triggers {
    pollSCM('H/5 * * * *')
}

Summary

  • Jenkins is the most flexible CI/CD tool for infrastructure automation
  • Use Jenkinsfile (pipeline as code) stored in your repository
  • Add approval gates (input) before deploying to production
  • Use credentials management — never hardcode secrets in Jenkinsfiles
  • Deploy Jenkins agents close to your target infrastructure for faster pipelines