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/initialAdminPasswordAccess 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-agentWebhook 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
