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; the agent uses a separate directory so it does not pollute the repo).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:
- 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.
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 │
│ ├── 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> │
└───────────────────────────────────────────────────────────────┘
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
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
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
Verify passwordless SSH:
ssh -o StrictHostKeyChecking=no sarah@stapp01 hostname
# Output: stapp01
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
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: openjdk version "21.0.12.1"
Step 5: Create the Agent Directory
ssh sarah@stapp01 "mkdir -p /home/sarah/jenkins_agent"
Part 2: Install Required Jenkins Plugins
Jenkins does not ship with the plugins needed for SSH agents and pipelines by default. Navigate to Manage Jenkins → Plugins → Available 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
- Navigate to Manage Jenkins → Credentials → System → Global credentials (unrestricted)
- Click Add Credentials
- Select SSH Username with private key and click Next
- 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
-
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 is Online
Go to Manage Jenkins → Nodes. The node should show Online with a green checkmark. The agent log will show:
Agent successfully connected and online
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
- From the Jenkins Dashboard, click New Item
- Enter name:
xfusion-webapp-job - Select Pipeline (NOT Multibranch Pipeline)
- 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
'''
}
}
}
}
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
- Click Save
- Click Build Now
- 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
Verification
Verify on App Server 1
ssh sarah@stapp01 "cd /var/www/html && git log -1 --oneline"
Verify via Load Balancer
- Click the App button on the top bar
- Confirm the website loads at the root URL (
https://<LBR-URL>) - Ensure no subdirectory appears in the URL (e.g., NOT
https://<LBR-URL>/web_app)
Test End-to-End
- Log in to Gitea as
sarah(password:Sarah_pass123) - Make a change to a file in the
web_apprepository - Commit and push
- In Jenkins, click Build Now for
xfusion-webapp-job - 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
Jenkins Agent Architecture: The controller schedules jobs, and agents execute them. Labels are used to target specific nodes.
Pipeline as Code: Declarative pipelines use
pipeline { agent { ... } stages { ... } }syntax, providing a clean, version-controllable way to define deployments.Java Version Compatibility: Jenkins agents require Java 17+. The
JavaPathadvanced option is only necessary when the defaultjavadoesn't point to the correct version.Plugin Dependencies: Missing plugins hide UI options. The Credentials, SSH Credentials, and Pipeline plugins are essential for this type of workflow.
Git Safe Directory: Modern Git requires explicit
safe.directoryconfiguration for non-root users.Load Balancer Routing: The website must be served from
/var/www/htmlroot so the LB routes correctly without a subdirectory.
Conclusion
In this challenge, we successfully:
- Generated SSH keys on the Jenkins controller
- Copied the public key to
sarahon App Server 1 - Installed Java 21 and set it as default
- Created the agent directory
/home/sarah/jenkins_agent - Installed the required Jenkins plugins
- Added SSH credentials for
sarah - Added the
App Server 1slave node with labelstapp01 - Created the pipeline job
xfusion-webapp-job - Configured a single
Deploystage that pulls the latest code - 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)