This repository contains a complete DevSecOps pipeline for deploying a Netflix clone application on Azure, implementing security scanning, monitoring, and Kubernetes deployment.
This project demonstrates a complete CI/CD pipeline with integrated security (DevSecOps) for a Netflix clone application, deployed on Azure infrastructure. The pipeline includes:
- Code Build & Test: Jenkins pipeline for building and testing the application
- Security Scanning: SonarQube, OWASP Dependency Check, and Trivy for vulnerability scanning
- Containerization: Docker for containerizing the application
- Orchestration: Azure Kubernetes Service (AKS) for container orchestration
- GitOps: ArgoCD for declarative deployments
- Monitoring: Prometheus and Grafana for monitoring
- Azure account with active subscription
- Azure B-series VM (equivalent to AWS t2.medium)
- Basic knowledge of Jenkins, Docker, and Kubernetes
Instead of AWS EC2, this project uses Azure B-series VM (equivalent to t2.medium). Azure VMs automatically create public IPs, simplifying access to the services.
# Create resource group
az group create --name netflix-devsecops --location eastus
# Create VM
az vm create \
--resource-group netflix-devsecops \
--name jenkins-vm \
--image Ubuntu2204 \
--admin-username azureuser \
--generate-ssh-keys \
--size Standard_B2sEnsure the following ports are open in your Azure Network Security Group:
- 8080: Jenkins
- 8081: Netflix application
- 9000: SonarQube
- 9090: Prometheus
- 3000: Grafana
- 9100: Node Exporter
# Open required ports
az vm open-port --resource-group netflix-devsecops --name jenkins-vm --port 8080,8081,9000,9090,3000,9100 --priority 1001ssh azureuser@<your-azure-vm-ip>git clone https://github.com/Harivelu0/Netflix.git
cd Netflixsudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker $USER
newgrp docker
sudo chmod 777 /var/run/docker.sockGet an API key from TMDB by creating an account and generating an API key in the settings.
# Build with your API key
docker build --build-arg TMDB_V3_API_KEY=<your-api-key> -t netflix .
# Run the container
docker run -d --name netflix -p 8081:80 netflix:latestAccess the application at: http://your-azure-vm-ip:8081
docker run -d --name sonar -p 9000:9000 sonarqube:lts-communityAccess SonarQube at: http://your-azure-vm-ip:9000 (default credentials: admin/admin)
sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy -ysudo apt update
sudo apt install fontconfig openjdk-17-jre -ysudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins -y
sudo systemctl start jenkins
sudo systemctl enable jenkinsAccess Jenkins at: http://your-azure-vm-ip:8080
Install the following plugins:
- Eclipse Temurin Installer
- SonarQube Scanner
- NodeJs Plugin
- Email Extension Plugin
- OWASP Dependency-Check
- Docker plugins (Docker, Docker Commons, Docker Pipeline, Docker API, docker-build-step)
- Go to Manage Jenkins → Tools
- Configure JDK 17 and NodeJS 16
- Configure SonarQube Scanner
- Configure Dependency-Check (name: "DP-Check")
- Go to Manage Jenkins → Credentials → System → Global credentials
- Add credentials:
- For Docker Hub: Use Personal Access Token (PAT) with read/write access instead of password
- For SonarQube: Create token from SonarQube admin panel
Create a Jenkins pipeline with the following configuration:
pipeline{
agent any
tools{
jdk 'jdk17'
nodejs 'node16'
}
environment {
SCANNER_HOME=tool 'sonar-scanner'
}
stages {
stage('clean workspace'){
steps{
cleanWs()
}
}
stage('Checkout from Git'){
steps{
git branch: 'main', url: 'https://github.com/Harivelu0/Netflix.git'
}
}
stage("Sonarqube Analysis"){
steps{
withSonarQubeEnv('sonar-server') {
sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=Netflix \
-Dsonar.projectKey=netflix '''
}
}
}
stage("quality gate"){
steps {
script {
// Added timeout to prevent getting stuck
timeout(time: 1, unit: 'MINUTES') {
// Added sleep to give SonarQube time to process
sleep(10)
waitForQualityGate abortPipeline: false, credentialsId: 'Sonar-token'
}
}
}
}
stage('Install Dependencies') {
steps {
sh "npm install"
}
}
stage('OWASP FS SCAN') {
steps {
dependencyCheck additionalArguments: '--scan ./ --disableYarnAudit --disableNodeAudit', odcInstallation: 'DP-Check'
dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
}
}
stage('TRIVY FS SCAN') {
steps {
sh "trivy fs . > trivyfs.txt"
}
}
stage("Docker Build & Push"){
steps{
script{
withDockerRegistry(credentialsId: 'docker', toolName: 'docker'){
sh "docker build --build-arg TMDB_V3_API_KEY=YOUR_TMDB_API_KEY -t netflix ."
sh "docker tag netflix harivp1234/netflix:latest"
sh "docker push harivp1234/netflix:latest"
}
}
}
}
stage("TRIVY"){
steps{
sh "trivy image harivp1234/netflix:latest > trivyimage.txt"
}
}
stage('Deploy to container'){
steps{
sh 'docker run -d --name netflix -p 8081:80 harivp1234/netflix:latest'
}
}
}
post {
always {
// Clean up to avoid container name conflicts on next run
sh 'docker rm -f netflix || true'
}
}
}Note: If you encounter a "docker login failed" error:
sudo su
sudo usermod -aG docker jenkins
sudo systemctl restart jenkinsFor monitoring, a separate Azure VM was created to host Prometheus and Grafana.
az vm create \
--resource-group netflix-devsecops \
--name monitoring-vm \
--image Ubuntu2204 \
--admin-username azureuser \
--generate-ssh-keys \
--size Standard_B1s
# Open ports
az vm open-port --resource-group netflix-devsecops --name monitoring-vm --port 9090,3000,9100 --priority 1001# Create user
sudo useradd --system --no-create-home --shell /bin/false prometheus
# Download and install Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.47.1/prometheus-2.47.1.linux-amd64.tar.gz
tar -xvf prometheus-2.47.1.linux-amd64.tar.gz
cd prometheus-2.47.1.linux-amd64/
sudo mkdir -p /data /etc/prometheus
sudo mv prometheus promtool /usr/local/bin/
sudo mv consoles/ console_libraries/ /etc/prometheus/
sudo mv prometheus.yml /etc/prometheus/prometheus.yml
sudo chown -R prometheus:prometheus /etc/prometheus/ /data/Configure Prometheus service:
sudo nano /etc/systemd/system/prometheus.serviceAdd the following content:
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
User=prometheus
Group=prometheus
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/data \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries \
--web.listen-address=0.0.0.0:9090 \
--web.enable-lifecycle
[Install]
WantedBy=multi-user.target
Start Prometheus:
sudo systemctl enable prometheus
sudo systemctl start prometheussudo useradd --system --no-create-home --shell /bin/false node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar -xvf node_exporter-1.6.1.linux-amd64.tar.gz
sudo mv node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/
rm -rf node_exporter*Configure Node Exporter service:
sudo nano /etc/systemd/system/node_exporter.serviceAdd the following content:
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
User=node_exporter
Group=node_exporter
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/node_exporter --collector.logind
[Install]
WantedBy=multi-user.target
Start Node Exporter:
sudo systemctl enable node_exporter
sudo systemctl start node_exporterUpdate Prometheus configuration:
sudo nano /etc/prometheus/prometheus.ymlAdd the following configuration:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'jenkins'
metrics_path: '/prometheus'
static_configs:
- targets: ['jenkins-vm-ip:8080']
- job_name: 'Netflix'
metrics_path: '/metrics'
static_configs:
- targets: ['jenkins-vm-ip:9100']Reload Prometheus configuration:
curl -X POST http://localhost:9090/-/reloadsudo apt-get update
sudo apt-get install -y apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get -y install grafana
sudo systemctl enable grafana-server
sudo systemctl start grafana-serverAccess Grafana at http://monitoring-vm-ip:3000 (default credentials: admin/admin)
Configure Grafana:
- Add Prometheus as a data source (URL: http://localhost:9090)
- Import dashboard templates (e.g., Node Exporter dashboard #1860)
# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login to Azure
az login
# Create AKS cluster
az aks create \
--resource-group netflix-devsecops \
--name netflix-cluster \
--node-count 2 \
--node-vm-size Standard_B2s \
--generate-ssh-keys
# Get credentials
az aks get-credentials --resource-group netflix-devsecops --name netflix-clusterInstall ArgoCD on the Kubernetes cluster:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Expose ArgoCD UI
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
# Get ArgoCD password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -dAccess ArgoCD UI at the LoadBalancer IP (use kubectl get svc -n argocd to find it)
Create an application in ArgoCD using the UI or CLI:
kubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: netflix-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/Harivelu0/Netflix.git
targetRevision: HEAD
path: kubernetes
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
EOFThe Kubernetes directory in the repository contains:
- deployment.yaml
- node-service.yaml
- service.yaml
To access your application running in Kubernetes, you have two options:
-
Using NodePort Service:
Verify the service is created with NodePort type:
kubectl get svc
If your service is exposed on port 30007 as specified in the service.yaml:
# Make sure port 30007 is open in your Azure Network Security Group az vm open-port --resource-group netflix-devsecops --name jenkins-vm --port 30007 --priority 1002 # Get the external IP of any node in your cluster kubectl get nodes -o wide
Access the application at: http://node-external-ip:30007
-
Using kubectl port-forward:
# Forward the service port to your local machine kubectl port-forward svc/netflix-service 8081:80Access the application at: http://localhost:8081
-
Verify deployment status:
# Check if pods are running kubectl get pods # Check logs if needed kubectl logs <pod-name> # Describe the service kubectl describe svc netflix-service
You can also see the deployment status in the ArgoCD UI, which will show you the sync status and health of your application components.
├── Dockerfile
├── README.md
├── Jenkinsfile
├── package.json
├── kubernetes/
│ ├── deployment.yaml
│ ├── node-service.yaml
│ └── service.yaml
└── src/
└── [Application Source Files]
This project demonstrates a complete DevSecOps pipeline for deploying a Netflix clone application on Azure infrastructure. The implementation includes:
- CI/CD with Jenkins
- Security scanning with SonarQube, OWASP Dependency Check, and Trivy
- Containerization with Docker
- Orchestration with Azure Kubernetes Service
- GitOps with ArgoCD
- Monitoring with Prometheus and Grafana





