A lot of CI/CD tutorials show a simple “Hello World” app and a Jenkins job that prints Build Successful. That never felt close to how systems work in real environments. At least, they never helped me.
So I decided to build a small University Management Spring Boot monolith application with JWT authentication and protected APIs, and then build a complete pipeline around it — from source control to deployment, quality checks, security scans, artifact management and validation. Since I'm not a developer, the code itself isn't great it was just me exploring a new language along with some help from AI (Needless to say!)
The application itself is intentionally simple:
- JWT-based authentication (/auth/login)
- Protected APIs (/students)
- Spring Security integration
- Maven build and Docker packaging
The goal wasn't to show how to build an application (In that case, this would be the worst tutorial). Th goal is, to show a CI/CD(partly) flow to someone in less than 15 minutes.
So I created a mini DevSecOps pipeline that includes:
- GitHub webhooks
- Jenkins Controller + Agent
- SonarQube quality gates
- Docker image creation
- Trivy security scans
- Nexus artifact storage
- Automated deployment using Docker Compose
Just incase, anyone's interested in the code, it stays here
By the end, a Git push automatically builds, scans, deploys and validates the application.
*The diagram: *
The App:
- Register using the
/auth/registerAPI
[root@server1 config]# curl -v -X POST "http://localhost:8081/auth/register?username=ram&password=redhat123"
- Pass the credentials to the
/auth/loginAPI to login . The App will return a JWT token, which will then be used to interact with the API.
[root@server1 config]# curl -X POST \
"http://localhost:8081/auth/login?username=ram&password=redhat123"
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYW0iLCJpYXQiOjE3NzkxNzA4MjIsImV4cCI6MTc3OTE3NDQyMn0.4AwQQqEa07f_-YId7LSlXYnctaWf7TdqG6xPYxTum_4
- This step is actually not required, just a part of convenience.
[root@server1 config]# export TOKEN=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYW0iLCJpYXQiOjE3NzkxNzA4MjIsImV4cCI6MTc3OTE3NDQyMn0.4AwQQqEa07f_-YId7LSlXYnctaWf7TdqG6xPYxTum_4
- Create entries using the
JWT tokento authenticate using the/studentsAPI.
[root@server1 config]# curl -X POST \
http://localhost:8081/students \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name":"John",
"email":"john@test.com"
}'
{"id":1,"name":"John","email":"john@test.com"}
- Query the API using the
token.
[root@server1 config]# curl -H "Authorization: Bearer $TOKEN" http://localhost:8081/students;echo
[{"id":1,"name":"John","email":"john@test.com"}]
The pipeline:
- We will make use of Jenkins to run the pipeline.
- I have chosen to run the jobs off of a jenkins agent, simply to separate orchestration and execution
The very first stage of the pipeline after the developer pushes the code is to
- checkout the code from source control
- Build the application using Maven.
- The build generates a jar file, which is quite famously referred to as the artifact.
- Now, this artifact is scanned by our quality gates which checks it for any code smells, Bugs, Vulnerabilities, etc.
- The sonarqube interface shows something like:
My 2 cents: Do not forget to add Jenkins call back in Sonarqube, else the job in Jenkins will wait to get the status from sonarqube and will eventually timeout.
- If our code passes quality gates, we build the docker image and bake the artifact into the image.
- Earlier, we scanned for vulnerabilities, bugs in the code. Now, it's time to scan for vulnerabilities in the docker image. I used Trivy for this. The ideal way to do this is to exit the job when there are vulnerabilities in the image. But for this lab I'm just running the scan as the image i pulled had loads of them.
- Additionally, I also posted the scan results on a nexus repository with the job number appended.
- This is the smallest CD part of the pipeline where we bring up the app using the image we built earlier using docker-compose.
- Finally, keeping the artifact on the agent is not a good idea, so I moved it to a Nexus repo and ran a cleanup of the workspace to remove it from the agent.
Future enhancements: I must admit, this document is incomplete without :
- converting this to a microservice
- Moving the application to K8s or Openshift.
- Adding monitoring for our App.












Top comments (0)