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.
Add a slave node named
App Server 1. It should be labeled asstapp01and its remote root directory should be/home/sarah/jenkins_agent(the repository is cloned under/var/www/html).We have already cloned repository on App Server 1 under
/var/www/html.Apache is already installed on the app server and is running on port
8080.-
Create a Jenkins pipeline job named
xfusion-webapp-job(it must not be aMultibranch pipeline) and configure it to:- Add a string parameter named
BRANCH. - It should conditionally deploy the code from
web_apprepository under/var/www/htmlon App Server 1, as this is the document root of the app server. The pipeline should have a single stage namedDeploy( which is case sensitive ) to accomplish the deployment. - The pipeline should be conditional, if the value
masteris passed to theBRANCHparameter then it must deploy themasterbranch, on the other hand if the valuefeatureis passed to theBRANCHparameter then it must deploy thefeaturebranch.
- Add a string parameter named
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:
- 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 runningon plugin installation/update page i.eupdate 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. - 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 │
│ Parameters: │
│ BRANCH (string, default: master) │
│ │
│ Pipeline: │
│ agent: label 'stapp01' │
│ stage: Deploy │
│ if BRANCH == master → git checkout master │
│ if BRANCH == feature → git checkout feature │
└──────────────────┬────────────────────────────────────────────┘
│
│ 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> │
└───────────────────────────────────────────────────────────────┘
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 |
| String Parameter | BRANCH |
| Stage Name |
Deploy (case sensitive) |
| Repository |
sarah/web_app (Gitea) |
| Deploy Path | /var/www/html |
| Conditional Logic |
BRANCH=master → deploy master; BRANCH=feature → deploy feature |
Part 1: Prepare the Infrastructure
Step 1: SSH to Jenkins Server
ssh jenkins@jenkins
# Password: j@rv!s
Step 2: Generate SSH Key (if missing)
ls -la ~/.ssh/id_rsa
# If missing:
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa # Copy this 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
# Verify passwordless access
ssh -o StrictHostKeyChecking=no sarah@stapp01 hostname
Expected output:
stapp01
Step 4: Install Java 21 on App Server 1
Jenkins agents require Java 17 or higher. Java 11 causes UnsupportedClassVersionError.
ssh -t sarah@stapp01 "sudo yum install -y java-21-openjdk"
# Password: Sarah_pass123
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"
Verify:
ssh sarah@stapp01 "java -version"
Expected output:
openjdk version "21.0.12.1" 2026-08-18 LTS
Step 5: Create the Agent Directory
ssh sarah@stapp01 "mkdir -p /home/sarah/jenkins_agent"
Part 2: Install Required Jenkins Plugins
Jenkins requires several plugins for SSH-based agents and declarative pipelines.
- Log in to Jenkins as
admin/Adm!n321 - Navigate to Manage Jenkins → Plugins → Available plugins
- Install the following:
| 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 |
- Restart Jenkins when prompted (select Restart Jenkins when installation is complete and no jobs are running)
- Refresh the UI page after the restart
Part 3: Add SSH Credentials
- Navigate to Manage Jenkins → Credentials → System → Global credentials (unrestricted)
- Click Add Credentials
- Select SSH Username with private key → Next
- Configure:
-
ID:
sarah-stapp01-credentials - Description: Sarah SSH credentials for App Server 1
-
Username:
sarah -
Private Key: Select Enter directly → paste the private key from
~/.ssh/id_rsa
-
ID:
- Click Create
Part 4: Add the Jenkins Agent Node
- Navigate to Manage Jenkins → Nodes → New Node
-
Name:
App Server 1 - Select Permanent Agent → OK
- 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 |
- Click Save
- Verify the node shows Online with a green checkmark
Agent log should show:
Agent successfully connected and online
Note: The JavaPath advanced option is not required here because the default java in PATH already points to Java 21.
Part 5: Create the Conditional Pipeline Job
Step 1: Create a New Pipeline Job
- From the Jenkins Dashboard, click New Item
- Enter name:
xfusion-webapp-job - Select Pipeline (NOT Multibranch Pipeline)
- Click OK
Step 2: Add the BRANCH Parameter
- In the General section, check This project is parameterized
- Click Add Parameter → String Parameter
- Configure:
-
Name:
BRANCH -
Default Value:
master - Description: Enter the branch to deploy (master or feature)
-
Name:
Step 3: Configure the Pipeline Script
Scroll down to the Pipeline section and enter:
pipeline {
agent { label 'stapp01' }
parameters {
string(name: 'BRANCH', defaultValue: 'master', description: 'Enter the branch to deploy (master or feature)')
}
stages {
stage('Deploy') {
steps {
script {
if (params.BRANCH == 'master') {
sh '''
cd /var/www/html
git config --global --add safe.directory /var/www/html
git fetch origin master
git checkout master
git reset --hard origin/master
'''
} else if (params.BRANCH == 'feature') {
sh '''
cd /var/www/html
git config --global --add safe.directory /var/www/html
git fetch origin feature
git checkout feature
git reset --hard origin/feature
'''
} else {
error("Invalid BRANCH value: ${params.BRANCH}. Allowed values: master, feature")
}
}
}
}
}
}
Explanation of the Script
| Line | Purpose |
|---|---|
agent { label 'stapp01' } |
Runs the pipeline on the agent node |
parameters { string(...) } |
Declares the BRANCH parameter |
stage('Deploy') |
Single stage named Deploy (case sensitive) |
script { ... } |
Enables Groovy conditional logic |
if (params.BRANCH == 'master') |
Checks if BRANCH is master
|
git fetch origin master |
Fetches the latest from the master branch |
git checkout master |
Switches to the master branch |
git reset --hard origin/master |
Ensures the working tree matches the remote exactly |
else if (params.BRANCH == 'feature') |
Checks if BRANCH is feature
|
error(...) |
Fails the pipeline for invalid values |
Step 4: Save the Job
Click Save at the bottom of the page.
Part 6: Verify the Feature Branch Exists
Before testing the feature deployment, ensure the feature branch exists in the Gitea repository.
- Click the Gitea button on the top bar
- Login as
sarah/Sarah_pass123 - Open the
web_apprepository - If
featurebranch doesn't exist:- Click the branch selector → New Branch
- Name:
feature - Base:
master - Click Create Branch
- Commit a small change to the feature branch to differentiate it from master
Part 7: Test Both Deployments
Test 1: Deploy master Branch
- In Jenkins, click Build with Parameters
- Set BRANCH =
master - Click Build
- Check the Console Output
Expected 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] stage
[Pipeline] { (Deploy)
[Pipeline] sh
+ cd /var/www/html
+ git config --global --add safe.directory /var/www/html
+ git fetch origin master
+ git checkout master
+ git reset --hard origin/master
HEAD is now at <hash> <master-commit-message>
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS
Test 2: Deploy feature Branch
- Click Build with Parameters again
- Set BRANCH =
feature - Click Build
- Check the Console Output
Expected Output:
+ git fetch origin feature
+ git checkout feature
+ git reset --hard origin/feature
HEAD is now at 4a8b390 Added feature.html file
Finished: SUCCESS
Verification
Verify on App Server 1
ssh sarah@stapp01 "cd /var/www/html && git branch --show-current && git log -1 --oneline"
Expected: Branch matches the last deployed branch (master or feature).
Verify via Load Balancer
- Click the App button on the top bar
- Confirm the website loads at the root URL (
https://<LBR-URL>) - Verify the URL does not have a subdirectory like
/web_app
Complete Configuration Summary
| Setting | Value |
|---|---|
| Job Name | xfusion-webapp-job |
| Job Type | Pipeline |
| Parameter Name | BRANCH |
| Parameter Type | String Parameter |
| Default Value | master |
| Agent Label | stapp01 |
| Stage Name | Deploy |
| Deploy Path | /var/www/html |
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
git fetch origin feature fails |
Branch doesn't exist on remote | Create the feature branch in Gitea |
| "dubious ownership" Git error | Modern Git requires safe.directory | Add git config --global --add safe.directory in the pipeline |
| Permission denied on /var/www/html | Directory not owned by sarah | Run sudo chown -R sarah:sarah /var/www/html
|
| Invalid BRANCH value error | Wrong input | Use exactly master or feature (case sensitive) |
params.BRANCH is null |
Parameter not declared | Add the parameters { string(...) } block |
| Credentials/Pipeline options missing | Plugins not installed | Install Credentials, SSH Credentials, and Pipeline plugins |
Task Summary
| Requirement | Status |
|---|---|
Agent node App Server 1 online |
✅ |
Label stapp01
|
✅ |
Remote root /home/sarah/jenkins_agent
|
✅ |
String parameter BRANCH added |
✅ |
Pipeline job xfusion-webapp-job created |
✅ |
Single stage named Deploy
|
✅ |
| Conditional deploy (master vs feature) | ✅ |
| Website accessible at root URL | ✅ |
Key Learnings
Parameterized Pipelines: The
parametersblock lets jobs accept user inputs at build time, making them more flexible and reusable.Conditional Logic in Declarative Pipelines: The
script { }block enables Groovy-based conditionals such asif/elseinside declarative syntax.Exact Branch Matching: Using
git fetch+git checkout+git reset --hardguarantees the local branch matches the remote exactly, avoiding stale files or merge conflicts.Failing Fast: Using
error(...)for invalid inputs prevents unexpected behavior and makes debugging easy.Reusability: A single pipeline job handles multiple branches, reducing the number of jobs needed for different deployment scenarios.
Load Balancer Routing: Regardless of which branch is deployed, content must be served from
/var/www/htmlroot for the LB to route correctly.
Conclusion
In this challenge, we extended our Jenkins deployment pipeline with a conditional mechanism driven by a BRANCH string parameter. The same job now:
- Deploys the
masterbranch whenBRANCH=masteris passed - Deploys the
featurebranch whenBRANCH=featureis passed - Fails with a clear error message for any other value
This pattern is common in real-world CI/CD pipelines where a single job handles multiple environments or branches, using parameters and conditionals to route deployment logic.
The pipeline now provides a flexible, reusable deployment mechanism through the Load Balancer at the root URL, and developers can trigger deployments for either branch directly from the Jenkins UI.
Next Steps
To further enhance this pipeline:
- Add more branches: Use a choice parameter to present available branches
- Environment-specific deployments: Deploy to different servers based on the branch
- Post-Build Notifications: Send Slack or email notifications on success/failure
- Webhook Integration: Automatically trigger builds on Gitea push events
- Rollback: Add a stage to roll back to the previous commit on failure
Top comments (0)