DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Day 77: Jenkins Deploy Pipeline

The development team of xFusionCorp Industries is working on to develop a new static website and they are planning to deploy the same on Nautilus App Server using Jenkins pipeline. They have shared their requirements with the DevOps team and accordingly we need to create a Jenkins pipeline job. Please find below more details about the task:

Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.

Similarly, click on the Gitea button on the top bar to access the Gitea UI. Login using username sarah and password Sarah_pass123. There under user sarah you will find a repository named web_app that is already cloned on App Server 1 under /var/www/html. sarah is a developer who is working on this repository.

  1. Add a slave node named App Server 1. It should be labeled as stapp01 and its remote root directory should be /home/sarah/jenkins_agent (the repository is cloned under /var/www/html; the agent uses a separate directory so it does not pollute the repo).

  2. We have already cloned repository on App Server 1 under /var/www/html.

  3. Apache is already installed on the app server and is running on port 8080.

  4. Create a Jenkins pipeline job named xfusion-webapp-job (it must not be a Multibranch pipeline) and configure it to:

- Deploy the code from `web_app` repository under `/var/www/html` on **App Server 1**, as this is the document root of the app server. The pipeline should have a single stage named `Deploy` ( which is case sensitive ) to accomplish the deployment.  
Enter fullscreen mode Exit fullscreen mode

LB server is already configured. You should be able to see the latest changes you made by clicking on the App button. Please make sure the required content is loading on the main URL https://<LBR-URL> i.e there should not be a sub-directory like https://<LBR-URL>/web_app etc.

Note:

  1. You might need to install some plugins and restart Jenkins service. So, we recommend clicking on Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page i.e update centre. Also, Jenkins UI sometimes gets stuck when Jenkins service restarts in the back end. In this case, please make sure to refresh the UI page.
  2. For these kind of scenarios requiring changes to be done in a web UI, please take screenshots so that you can share it with us for review in case your task is marked incomplete. You may also consider using a screen recording software such as loom.com to record and share your work.

Understanding the Architecture

┌───────────────────────────────────────────────────────────────┐
│           Jenkins Controller (jenkins server)                 │
│                                                               │
│  Job: xfusion-webapp-job                                      │
│  ├── agent: label 'stapp01'                                   │
│  └── stages:                                                  │
│      └── Deploy: git pull in /var/www/html                    │
└──────────────────┬────────────────────────────────────────────┘
                   │
                   │ SSH (sarah user)
                   ▼
┌───────────────────────────────────────────────────────────────┐
│           Jenkins Agent (App Server 1 / stapp01)              │
│                                                               │
│  Workspace: /home/sarah/jenkins_agent/workspace/...           │
│  Repository: /var/www/html (sarah/web_app)                    │
│  Apache: port 8080                                            │
└──────────────────┬────────────────────────────────────────────┘
                   │
                   │ HTTP
                   ▼
┌───────────────────────────────────────────────────────────────┐
│                 Load Balancer (LBR)                           │
│              Routes to App Server 1:8080                      │
│                https://<LBR-URL>                              │
└───────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Task Requirements

Requirement Details
Job Name xfusion-webapp-job
Job Type Pipeline (not Multibranch)
Agent Node App Server 1
Agent Label stapp01
Remote Root Directory /home/sarah/jenkins_agent
Stage Name Deploy (case sensitive)
Repository sarah/web_app (Gitea)
Deploy Path /var/www/html

Part 1: Configure the Jenkins Agent Node

Step 1: Access Jenkins Server via SSH

ssh jenkins@jenkins
# Password: j@rv!s
Enter fullscreen mode Exit fullscreen mode

Step 2: Generate SSH Key on Jenkins Server

The Jenkins agent runs as the jenkins user, so SSH keys must be generated for that user.

ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa
Enter fullscreen mode Exit fullscreen mode

Copy the private key output — you'll need it for Jenkins credentials.

Step 3: Copy SSH Key to sarah on App Server 1

ssh-copy-id -o StrictHostKeyChecking=no sarah@stapp01
# Password: Sarah_pass123
Enter fullscreen mode Exit fullscreen mode

Verify passwordless SSH:

ssh -o StrictHostKeyChecking=no sarah@stapp01 hostname
# Output: stapp01
Enter fullscreen mode Exit fullscreen mode

Step 4: Install Java 21 on App Server 1

Jenkins agents require Java 17 or higher. Java 11 will cause an UnsupportedClassVersionError.

# Install with TTY allocation for sudo
ssh -t sarah@stapp01 "sudo yum install -y java-21-openjdk"
# Password: Sarah_pass123
Enter fullscreen mode Exit fullscreen mode

Register Java 21 as an alternative and set it as default:

ssh sarah@stapp01 "echo 'Sarah_pass123' | sudo -S alternatives --install /usr/bin/java java /usr/lib/jvm/java-21-openjdk-21.0.12.1.1-2.1.el9.x86_64/bin/java 2000"
ssh sarah@stapp01 "echo 'Sarah_pass123' | sudo -S alternatives --set java /usr/lib/jvm/java-21-openjdk-21.0.12.1.1-2.1.el9.x86_64/bin/java"
Enter fullscreen mode Exit fullscreen mode

Verify:

ssh sarah@stapp01 "java -version"
# Expected: openjdk version "21.0.12.1"
Enter fullscreen mode Exit fullscreen mode

Step 5: Create the Agent Directory

ssh sarah@stapp01 "mkdir -p /home/sarah/jenkins_agent"
Enter fullscreen mode Exit fullscreen mode

Part 2: Install Required Jenkins Plugins

Jenkins does not ship with the plugins needed for SSH agents and pipelines by default. Navigate to Manage JenkinsPluginsAvailable plugins and install:

Plugin Purpose
Credentials Core credential management
Credentials Binding Bind credentials to build environment
SSH Credentials Adds "SSH Username with private key" option
SSH Build Agents Launch agents via SSH
Pipeline Core Pipeline functionality
Pipeline: Declarative Enables the pipeline { } syntax

After installing, select Restart Jenkins when installation is complete and no jobs are running. Refresh the UI page after Jenkins restarts.


Part 3: Add SSH Credentials

  1. Navigate to Manage JenkinsCredentialsSystemGlobal credentials (unrestricted)
  2. Click Add Credentials
  3. Select SSH Username with private key and click Next
  4. Configure:
    • ID: sarah-stapp01-credentials
    • Description: Sarah SSH credentials for App Server 1
    • Username: sarah
    • Private Key: Select Enter directly and paste the private key from Step 2
  5. Click Create

Part 4: Add the Jenkins Agent Node

  1. Navigate to Manage JenkinsNodesNew Node
  2. Name: App Server 1
  3. Select Permanent AgentOK
  4. Configure:
Field Value
Remote root directory /home/sarah/jenkins_agent
Labels stapp01
Usage Use this node as much as possible
Launch method Launch agents via SSH
Host stapp01
Credentials sarah-stapp01-credentials
Host Key Verification Strategy Non-verifying Verification Strategy
  1. Click Save

Verify the Node is Online

Go to Manage JenkinsNodes. The node should show Online with a green checkmark. The agent log will show:

Agent successfully connected and online
Enter fullscreen mode Exit fullscreen mode

Note on JavaPath: In this setup, the JavaPath advanced option is not required because the default java command in the agent's PATH already points to Java 21.


Part 5: Create the Pipeline Job

Step 1: Create a New Pipeline Job

  1. From the Jenkins Dashboard, click New Item
  2. Enter name: xfusion-webapp-job
  3. Select Pipeline (NOT Multibranch Pipeline)
  4. Click OK

Step 2: Configure the Pipeline Script

Scroll to the Pipeline section and enter:

pipeline {
    agent { label 'stapp01' }

    stages {
        stage('Deploy') {
            steps {
                sh '''
                    cd /var/www/html
                    git config --global --add safe.directory /var/www/html
                    git pull origin master
                '''
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation of the Script

Line Purpose
agent { label 'stapp01' } Runs the pipeline on the node with label stapp01
stage('Deploy') Defines a single stage named Deploy (case sensitive)
sh '''...''' Executes shell commands on the agent (as sarah)
cd /var/www/html Navigates to the Apache document root
git config --global --add safe.directory /var/www/html Prevents "dubious ownership" errors (Git 2.35.2+)
git pull origin master Pulls the latest code from Gitea

Step 3: Save and Build

  1. Click Save
  2. Click Build Now
  3. Click on the build number → Console Output

Expected Console Output

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on App Server 1 in /home/sarah/jenkins_agent/workspace/xfusion-webapp-job
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] sh
+ cd /var/www/html
+ git config --global --add safe.directory /var/www/html
+ git pull origin master
From http://gitea:3000/sarah/web_app
 * branch            master     -> FETCH_HEAD
Already up to date.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Enter fullscreen mode Exit fullscreen mode

Verification

Verify on App Server 1

ssh sarah@stapp01 "cd /var/www/html && git log -1 --oneline"
Enter fullscreen mode Exit fullscreen mode

Verify via Load Balancer

  1. Click the App button on the top bar
  2. Confirm the website loads at the root URL (https://<LBR-URL>)
  3. Ensure no subdirectory appears in the URL (e.g., NOT https://<LBR-URL>/web_app)

Test End-to-End

  1. Log in to Gitea as sarah (password: Sarah_pass123)
  2. Make a change to a file in the web_app repository
  3. Commit and push
  4. In Jenkins, click Build Now for xfusion-webapp-job
  5. Refresh the App page — the new change should be visible

Task Summary

Requirement Status
Agent node App Server 1 added
Label stapp01
Remote root /home/sarah/jenkins_agent
Agent online
Pipeline job xfusion-webapp-job
Single stage named Deploy
Deploys web_app to /var/www/html
Website accessible at root URL

Troubleshooting Reference

Issue Cause Solution
Credentials option missing Credentials plugin not installed Install Credentials plugin
SSH key option missing SSH Credentials plugin not installed Install SSH Credentials plugin
Pipeline option missing Pipeline plugin not installed Install Pipeline plugin
UnsupportedClassVersionError Java 11 instead of 21 Install Java 21 and set as default
sudo: a terminal is required No TTY for SSH Use ssh -t or `echo 'pass' \
"dubious ownership" Git error Modern Git safe.directory Add {% raw %}git config --global --add safe.directory
Agent offline Java/SSH misconfiguration Check agent log in Jenkins UI

Key Learnings

  1. Jenkins Agent Architecture: The controller schedules jobs, and agents execute them. Labels are used to target specific nodes.

  2. Pipeline as Code: Declarative pipelines use pipeline { agent { ... } stages { ... } } syntax, providing a clean, version-controllable way to define deployments.

  3. Java Version Compatibility: Jenkins agents require Java 17+. The JavaPath advanced option is only necessary when the default java doesn't point to the correct version.

  4. Plugin Dependencies: Missing plugins hide UI options. The Credentials, SSH Credentials, and Pipeline plugins are essential for this type of workflow.

  5. Git Safe Directory: Modern Git requires explicit safe.directory configuration for non-root users.

  6. Load Balancer Routing: The website must be served from /var/www/html root so the LB routes correctly without a subdirectory.


Conclusion

In this challenge, we successfully:

  1. Generated SSH keys on the Jenkins controller
  2. Copied the public key to sarah on App Server 1
  3. Installed Java 21 and set it as default
  4. Created the agent directory /home/sarah/jenkins_agent
  5. Installed the required Jenkins plugins
  6. Added SSH credentials for sarah
  7. Added the App Server 1 slave node with label stapp01
  8. Created the pipeline job xfusion-webapp-job
  9. Configured a single Deploy stage that pulls the latest code
  10. Verified the deployment through the Load Balancer

The pipeline is now ready to automatically deploy the latest code from the Gitea repository to the Apache document root on App Server 1. The website is accessible through the Load Balancer at the root URL, and developers can trigger deployments by pushing changes to the repository and clicking Build Now (or by adding a webhook for full automation).


Next Steps

To further enhance this pipeline, consider:

  • Adding a Webhook: Configure a Gitea webhook so that pushes automatically trigger the Jenkins build
  • Environment Variables: Use parameterized builds for more flexibility
  • Post-Build Actions: Add notifications (Slack, email) on success/failure
  • Multi-Stage Pipelines: Extend to build, test, and deploy stages
  • Rollback Strategy: Implement a rollback mechanism on failure

Top comments (0)