From 83e5ebde7ed82fcacfa29c8a17be8715268281e2 Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 06:53:04 +0000 Subject: [PATCH 01/15] adding docker file for backend --- backend/Dockerfile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 backend/Dockerfile diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..5209ca4 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,19 @@ +# Stage 1: Maven build environment +FROM maven:3.9-openjdk-17 AS build-env +WORKDIR /app +COPY pom.xml ./ +RUN mvn dependency:go-offline + +# Stage 2: Build Spring Boot application +FROM maven:3.9-openjdk-17 AS build +WORKDIR /app +COPY pom.xml ./ +COPY src ./src +RUN mvn clean package -DskipTests + +# Stage 3: JRE runtime +FROM openjdk:17-jre-slim AS runtime +WORKDIR /app +COPY --from=build /app/target/*.jar app.jar +EXPOSE 8080 +CMD ["java", "-jar", "app.jar"] From faf1a47a1e3162f0b689db575a6eccaba5e7cd58 Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 07:18:07 +0000 Subject: [PATCH 02/15] adding frontend docker file --- frontend/Dockerfile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 frontend/Dockerfile diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..983e5ab --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,21 @@ +# Stage 1: Node.js build environment +FROM node:18-alpine AS build-env +WORKDIR /app +COPY package*.json ./ +RUN npm ci --only=production + +# Stage 2: Build React application +FROM node:18-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +# Stage 3: Lightweight runtime with built files +FROM node:18-alpine AS runtime +WORKDIR /app +COPY --from=build /app/build ./build +RUN npm install -g serve +EXPOSE 3000 +CMD ["serve", "-s", "build", "-l", "3000"] From 7c38b01704ceb699483f9880d2701920f2257037 Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 07:29:12 +0000 Subject: [PATCH 03/15] adding nginx configuration --- nginx/nginx.conf | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 nginx/nginx.conf diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..c57829e --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,59 @@ +events { + worker_connections 1024; +} + +http { + upstream frontend { + server frontend:3000; + } + + upstream backend { + server backend:8080; + } + + server { + listen 80; + server_name your-domain.com; + + location /.well-known/acme-challenge/ { + root /var/www/html; + } + + location / { + return 301 https://$server_name$request_uri; + } + } + + server { + listen 443 ssl; + server_name your-domain.com; + + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + location / { + proxy_pass http://frontend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /api { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /ws { + proxy_pass http://backend; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} From d4ec914cb542ca86d2fc56753ae8e2bc920716dc Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 07:41:19 +0000 Subject: [PATCH 04/15] addmin docker-compose file --- docker-compose.yml | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dd88601 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +version: '3.8' + +services: + mysql: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: enter_root_password + MYSQL_DATABASE: chattingo + MYSQL_USER: chattingo + MYSQL_PASSWORD: user_password + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + networks: + - chattingo-network + + backend: + build: ./backend + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/chattingo + SPRING_DATASOURCE_USERNAME: chattingo + SPRING_DATASOURCE_PASSWORD: password + depends_on: + - mysql + networks: + - chattingo-network + + frontend: + build: ./frontend + networks: + - chattingo-network + + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf + depends_on: + - frontend + - backend + networks: + - chattingo-network + +volumes: + mysql_data: + +networks: + chattingo-network: + driver: bridge From f4c7bf45608ecae37e037d7389b592ca21d8c836 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 7 Sep 2025 08:00:50 +0000 Subject: [PATCH 05/15] updating nginx configuration --- nginx/nginx.conf | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index c57829e..2fe3d7d 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,3 +1,4 @@ +nginx events { worker_connections 1024; } @@ -6,37 +7,20 @@ http { upstream frontend { server frontend:3000; } - + upstream backend { server backend:8080; } server { listen 80; - server_name your-domain.com; - - location /.well-known/acme-challenge/ { - root /var/www/html; - } - - location / { - return 301 https://$server_name$request_uri; - } - } - - server { - listen 443 ssl; - server_name your-domain.com; - - ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + server_name ; location / { proxy_pass http://frontend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; } location /api { @@ -44,7 +28,6 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; } location /ws { @@ -53,7 +36,6 @@ http { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; } } } From 24f5be8f049ccb8709a89d616c1b45d87cf4a450 Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 08:09:23 +0000 Subject: [PATCH 06/15] updating backend Docker file --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 5209ca4..a94da7c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -12,7 +12,7 @@ COPY src ./src RUN mvn clean package -DskipTests # Stage 3: JRE runtime -FROM openjdk:17-jre-slim AS runtime +FROM eclipse-temurin:17-jre-alpine AS runtime WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 From c1939bb7ddfb5dd611d919aa9d9676bc19f5ca77 Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 09:05:08 +0000 Subject: [PATCH 07/15] updating docker compose file --- docker-compose.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index dd88601..8fc5bc4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,11 +3,8 @@ version: '3.8' services: mysql: image: mysql:8.0 - environment: - MYSQL_ROOT_PASSWORD: enter_root_password - MYSQL_DATABASE: chattingo - MYSQL_USER: chattingo - MYSQL_PASSWORD: user_password + env_file: + - ./backend/.env ports: - "3306:3306" volumes: @@ -17,10 +14,8 @@ services: backend: build: ./backend - environment: - SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/chattingo - SPRING_DATASOURCE_USERNAME: chattingo - SPRING_DATASOURCE_PASSWORD: password + env_file: + - ./backend/.env depends_on: - mysql networks: @@ -28,6 +23,8 @@ services: frontend: build: ./frontend + env_file: + - ./frontend/.env networks: - chattingo-network From 72e767936a368422a90ab3958d6afcf879fa3d5d Mon Sep 17 00:00:00 2001 From: dk Date: Sun, 7 Sep 2025 09:17:38 +0000 Subject: [PATCH 08/15] updating nginx conf --- nginx/nginx.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 2fe3d7d..d2888da 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,4 +1,3 @@ -nginx events { worker_connections 1024; } From 84657c83464a7557c3c2ef926f964e870ec51dc1 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 7 Sep 2025 10:06:26 +0000 Subject: [PATCH 09/15] updating files --- backend/Dockerfile | 4 ++-- docker-compose.yml | 5 +++++ frontend/Dockerfile | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index a94da7c..aa5acde 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,11 +1,11 @@ # Stage 1: Maven build environment -FROM maven:3.9-openjdk-17 AS build-env +FROM maven:3.9.6-eclipse-temurin-17 AS build-env WORKDIR /app COPY pom.xml ./ RUN mvn dependency:go-offline # Stage 2: Build Spring Boot application -FROM maven:3.9-openjdk-17 AS build +FROM maven:3.9.6-eclipse-temurin-17 AS build WORKDIR /app COPY pom.xml ./ COPY src ./src diff --git a/docker-compose.yml b/docker-compose.yml index 8fc5bc4..08ade3c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,11 @@ version: '3.8' services: mysql: image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} env_file: - ./backend/.env ports: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 983e5ab..bea23a8 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -2,13 +2,13 @@ FROM node:18-alpine AS build-env WORKDIR /app COPY package*.json ./ -RUN npm ci --only=production +RUN npm install --only=production # Stage 2: Build React application FROM node:18-alpine AS build WORKDIR /app COPY package*.json ./ -RUN npm ci +RUN npm install COPY . . RUN npm run build From 3c1b300d32094bb9150a2cbab7d4c09236b6eef2 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 8 Sep 2025 04:18:38 +0000 Subject: [PATCH 10/15] updating files and adding jenkins file --- Jenkinsfile | 128 +++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 39 ++++++-------- 2 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..cbe5e76 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,128 @@ +pipeline { + agent any + + environment { + DOCKER_HUB_CREDENTIALS = credentials('docker-hub-credentials') + REGISTRY = 'chattingo-app' + IMAGE_TAG = "${BUILD_NUMBER}" + AWS_DEFAULT_REGION = 'ap-south-1' + S3_BUCKET = 'chattingo-app' + } + + stages { + stage('Git Clone') { + steps { + git branch: 'mini-hackathon', url: 'https://github.com/dushyantkumark/chattingo.git' + } + } + + stage('Image Build') { + steps { + script { + sh 'docker build -t ${REGISTRY}/frontend:${IMAGE_TAG} ./frontend' + sh 'docker build -t ${REGISTRY}/backend:${IMAGE_TAG} ./backend' + } + } + } + + stage('Filesystem Scan') { + steps { + script { + sh ''' + echo "Starting filesystem security scan..." > filesystem-scan-results.txt + docker run --rm -v $(pwd):/src securecodewarrior/docker-security-scanner /src >> filesystem-scan-results.txt 2>&1 + echo "Filesystem scan completed at $(date)" >> filesystem-scan-results.txt + ''' + } + } + } + + stage('Image Scan') { + steps { + script { + sh ''' + echo "Starting Docker image security scan..." > docker-scan-results.txt + echo "Scanning frontend image..." >> docker-scan-results.txt + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image ${REGISTRY}/frontend:${IMAGE_TAG} >> docker-scan-results.txt 2>&1 + echo "Scanning backend image..." >> docker-scan-results.txt + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image ${REGISTRY}/backend:${IMAGE_TAG} >> docker-scan-results.txt 2>&1 + echo "Docker image scan completed at $(date)" >> docker-scan-results.txt + ''' + } + } + } + + stage('Upload Scans to S3') { + steps { + script { + def timestamp = new Date().format('yyyy-MM-dd-HH-mm-ss') + + // Upload scan results to S3 + sh "aws s3 cp filesystem-scan-results.txt s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-${timestamp}.txt" + sh "aws s3 cp docker-scan-results.txt s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/docker-scan-${timestamp}.txt" + + // Generate 5-minute presigned URLs + def filesystemUrl = sh( + script: "aws s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-${timestamp}.txt --expires-in 300", + returnStdout: true + ).trim() + + def dockerUrl = sh( + script: "aws s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/docker-scan-${timestamp}.txt --expires-in 300", + returnStdout: true + ).trim() + + echo "=== SCAN RESULTS URLS (Valid for 5 minutes) ===" + echo "Filesystem Scan: ${filesystemUrl}" + echo "Docker Scan: ${dockerUrl}" + + // Save URLs for reference + writeFile file: 'scan-urls.txt', text: """Filesystem Scan: ${filesystemUrl} + Docker Scan: ${dockerUrl} + Generated: ${new Date()} + Expires: 5 minutes""" + } + } + } + + stage('Push to Registry') { + steps { + script { + docker.withRegistry('https://index.docker.io/v1/', 'docker-hub-credentials') { + sh 'docker push ${REGISTRY}/frontend:${IMAGE_TAG}' + sh 'docker push ${REGISTRY}/backend:${IMAGE_TAG}' + } + } + } + } + + stage('Update Compose') { + steps { + sh """ + sed -i 's|image: ${REGISTRY}/frontend:.*|image: ${REGISTRY}/frontend:${IMAGE_TAG}|g' docker-compose.yml + sed -i 's|image: ${REGISTRY}/backend:.*|image: ${REGISTRY}/backend:${IMAGE_TAG}|g' docker-compose.yml + """ + } + } + + stage('Deploy') { + steps { + script { + sh """ + cd /home/ubuntu/mini/chattingo + docker-compose pull + docker-compose up -d + """ + } + } + } + } + } + + post { + always { + archiveArtifacts artifacts: 'filesystem-scan-results.txt,docker-scan-results.txt,scan-urls.txt', allowEmptyArchive: true + sh 'docker system prune -f' + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 08ade3c..466d14b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,49 +1,44 @@ -version: '3.8' - services: mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE: ${MYSQL_DATABASE} - MYSQL_USER: ${MYSQL_USER} - MYSQL_PASSWORD: ${MYSQL_PASSWORD} - env_file: - - ./backend/.env + MYSQL_ROOT_PASSWORD: securepassword123 + MYSQL_DATABASE: chattingo_db + MYSQL_USER: chattingo + MYSQL_PASSWORD: chatpassword123 ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql networks: - chattingo-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + timeout: 20s + retries: 10 backend: - build: ./backend + image: chattingo-app/backend:latest env_file: - ./backend/.env depends_on: - - mysql + mysql: + condition: service_healthy + ports: + - "8080:8080" networks: - chattingo-network + restart: unless-stopped frontend: - build: ./frontend + image: chattingo-app/frontend:latest env_file: - ./frontend/.env - networks: - - chattingo-network - - nginx: - image: nginx:alpine ports: - - "80:80" - volumes: - - ./nginx/nginx.conf:/etc/nginx/nginx.conf - depends_on: - - frontend - - backend + - "3000:3000" networks: - chattingo-network + restart: unless-stopped volumes: mysql_data: From 2889b23b67179ea353b868fd9f366441debb070c Mon Sep 17 00:00:00 2001 From: dushyant Date: Mon, 8 Sep 2025 10:49:44 +0000 Subject: [PATCH 11/15] updated code --- Jenkinsfile | 154 ++++++++++++------ backend/.env.example | 12 +- .../chattingo/Controller/AuthController.java | 11 +- .../chattingo/Controller/RealTimeChat.java | 6 +- .../ServiceImpl/MessageServiceImpl.java | 16 +- .../java/com/chattingo/config/AppConfig.java | 4 +- .../com/chattingo/config/JwtValidator.java | 6 +- .../com/chattingo/config/WebSocketConfig.java | 2 +- docker-compose.yml | 4 +- frontend/src/Components/HomePage.jsx | 21 ++- frontend/src/Components/Register/Signup.jsx | 4 +- 11 files changed, 152 insertions(+), 88 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index cbe5e76..ac37c0f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,10 +3,12 @@ pipeline { environment { DOCKER_HUB_CREDENTIALS = credentials('docker-hub-credentials') - REGISTRY = 'chattingo-app' - IMAGE_TAG = "${BUILD_NUMBER}" - AWS_DEFAULT_REGION = 'ap-south-1' - S3_BUCKET = 'chattingo-app' + AWS_CREDENTIALS = credentials('aws-cred') + FRONTEND_REPO = credentials('frontend-repo') + BACKEND_REPO = credentials('backend-repo') + IMAGE_TAG = "${BUILD_NUMBER}" + AWS_DEFAULT_REGION = credentials('my-region') + S3_BUCKET = credentials('bucket') } stages { @@ -19,8 +21,8 @@ pipeline { stage('Image Build') { steps { script { - sh 'docker build -t ${REGISTRY}/frontend:${IMAGE_TAG} ./frontend' - sh 'docker build -t ${REGISTRY}/backend:${IMAGE_TAG} ./backend' + sh 'docker build --no-cache -t ${FRONTEND_REPO}:${IMAGE_TAG} ./frontend' + sh 'docker build --no-cache -t ${BACKEND_REPO}:${IMAGE_TAG} ./backend' } } } @@ -28,11 +30,7 @@ pipeline { stage('Filesystem Scan') { steps { script { - sh ''' - echo "Starting filesystem security scan..." > filesystem-scan-results.txt - docker run --rm -v $(pwd):/src securecodewarrior/docker-security-scanner /src >> filesystem-scan-results.txt 2>&1 - echo "Filesystem scan completed at $(date)" >> filesystem-scan-results.txt - ''' + sh 'trivy fs --format json --output filesystem-scan-report.json .' } } } @@ -40,14 +38,8 @@ pipeline { stage('Image Scan') { steps { script { - sh ''' - echo "Starting Docker image security scan..." > docker-scan-results.txt - echo "Scanning frontend image..." >> docker-scan-results.txt - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image ${REGISTRY}/frontend:${IMAGE_TAG} >> docker-scan-results.txt 2>&1 - echo "Scanning backend image..." >> docker-scan-results.txt - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image ${REGISTRY}/backend:${IMAGE_TAG} >> docker-scan-results.txt 2>&1 - echo "Docker image scan completed at $(date)" >> docker-scan-results.txt - ''' + sh 'trivy image --format json --output frontend-scan-report.json ${FRONTEND_REPO}:${IMAGE_TAG}' + sh 'trivy image --format json --output backend-scan-report.json ${BACKEND_REPO}:${IMAGE_TAG}' } } } @@ -57,30 +49,56 @@ pipeline { script { def timestamp = new Date().format('yyyy-MM-dd-HH-mm-ss') - // Upload scan results to S3 - sh "aws s3 cp filesystem-scan-results.txt s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-${timestamp}.txt" - sh "aws s3 cp docker-scan-results.txt s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/docker-scan-${timestamp}.txt" - - // Generate 5-minute presigned URLs - def filesystemUrl = sh( - script: "aws s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-${timestamp}.txt --expires-in 300", - returnStdout: true - ).trim() - - def dockerUrl = sh( - script: "aws s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/docker-scan-${timestamp}.txt --expires-in 300", - returnStdout: true - ).trim() - - echo "=== SCAN RESULTS URLS (Valid for 5 minutes) ===" - echo "Filesystem Scan: ${filesystemUrl}" - echo "Docker Scan: ${dockerUrl}" - - // Save URLs for reference - writeFile file: 'scan-urls.txt', text: """Filesystem Scan: ${filesystemUrl} - Docker Scan: ${dockerUrl} - Generated: ${new Date()} - Expires: 5 minutes""" + withCredentials([aws(credentialsId: 'aws-cred')]) { + ['filesystem-scan-report.json', 'frontend-scan-report.json', 'backend-scan-report.json'].each { file -> + sh """ + docker run --rm \ + -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ + -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ + -v \$(pwd):/workspace \ + amazon/aws-cli s3 cp /workspace/${file} s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/${file.replace('.json','')}-${timestamp}.json + """ + } + + def filesystemUrl = sh( + script: """docker run --rm \ + -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ + -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ + amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-report-${timestamp}.json --expires-in 300""", + returnStdout: true + ).trim() + + def frontendUrl = sh( + script: """docker run --rm \ + -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ + -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ + amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/frontend-scan-report-${timestamp}.json --expires-in 300""", + returnStdout: true + ).trim() + + def backendUrl = sh( + script: """docker run --rm \ + -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ + -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ + amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/backend-scan-report-${timestamp}.json --expires-in 300""", + returnStdout: true + ).trim() + + echo "=== SCAN RESULTS URLS (Valid for 5 minutes) ===" + echo "Filesystem Scan: ${filesystemUrl}" + echo "Frontend Scan: ${frontendUrl}" + echo "Backend Scan: ${backendUrl}" + + writeFile file: 'scan-urls.txt', text: """Filesystem Scan: ${filesystemUrl} + Frontend Scan: ${frontendUrl} + Backend Scan: ${backendUrl} + Generated: ${new Date()} + Expires: 5 minutes""" + } } } } @@ -89,8 +107,8 @@ pipeline { steps { script { docker.withRegistry('https://index.docker.io/v1/', 'docker-hub-credentials') { - sh 'docker push ${REGISTRY}/frontend:${IMAGE_TAG}' - sh 'docker push ${REGISTRY}/backend:${IMAGE_TAG}' + sh 'docker push ${FRONTEND_REPO}:${IMAGE_TAG}' + sh 'docker push ${BACKEND_REPO}:${IMAGE_TAG}' } } } @@ -99,8 +117,8 @@ pipeline { stage('Update Compose') { steps { sh """ - sed -i 's|image: ${REGISTRY}/frontend:.*|image: ${REGISTRY}/frontend:${IMAGE_TAG}|g' docker-compose.yml - sed -i 's|image: ${REGISTRY}/backend:.*|image: ${REGISTRY}/backend:${IMAGE_TAG}|g' docker-compose.yml + sed -i 's|image: .*frontend.*|image: ${FRONTEND_REPO}:${IMAGE_TAG}|g' docker-compose.yml + sed -i 's|image: .*backend.*|image: ${BACKEND_REPO}:${IMAGE_TAG}|g' docker-compose.yml """ } } @@ -109,20 +127,52 @@ pipeline { steps { script { sh """ + echo "updated docker-compose.yml to deployment directory" + cp docker-compose.yml /home/ubuntu/mini/chattingo/ + + # go into deployment folder cd /home/ubuntu/mini/chattingo - docker-compose pull - docker-compose up -d + docker compose down + docker compose pull + docker compose up -d + + # return back to original workspace + cd - """ } } } } - } post { always { - archiveArtifacts artifacts: 'filesystem-scan-results.txt,docker-scan-results.txt,scan-urls.txt', allowEmptyArchive: true - sh 'docker system prune -f' + script { + // 1. Archive scan files (latest ones only) + archiveArtifacts artifacts: 'filesystem-scan-report.json,frontend-scan-report.json,backend-scan-report.json,scan-urls.txt', allowEmptyArchive: true + + // 2. Cleanup old scan files in workspace (keep latest only) + sh ''' + echo "Cleaning up old scan reports..." + for f in filesystem-scan-report.json frontend-scan-report.json backend-scan-report.json scan-urls.txt; do + if [ -f "$f" ]; then + echo "Keeping latest: $f" + fi + done + + # remove any older .json or .txt scan reports + find . -maxdepth 1 -type f \\( -name "*scan*.json" -o -name "*scan*.txt" \\) ! -newer scan-urls.txt -exec rm -f {} + + ''' + + // 3. Remove unused Docker images (dangling + old build images) + sh ''' + echo "Cleaning up unused Docker images..." + docker image prune -af --filter "until=24h" || true + + # Remove old build images except the current IMAGE_TAG + docker images --format "{{.Repository}}:{{.Tag}}" | grep chattingo-app || true + docker images --format "{{.Repository}}:{{.Tag}}" | grep chattingo-app | grep -v ":${IMAGE_TAG}" | xargs -r docker rmi -f + ''' + } } } } diff --git a/backend/.env.example b/backend/.env.example index a28bc1d..29f143c 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,13 +1,13 @@ # JWT Configuration -JWT_SECRET=your-generated-jwt-secret-key-here +JWT_SECRET=sdd4OUI3mQs/ANIaXZwKhs1jTjNr/2c8J+BSDGHkP7AQ+U6JpLYGY9XmdYOwao0S1YRzGSuyNzpx05/x4biWKQ== # Database Configuration -SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/chattingo_db?createDatabaseIfNotExist=true +SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/chattingo_db?createDatabaseIfNotExist=true SPRING_DATASOURCE_USERNAME=root -SPRING_DATASOURCE_PASSWORD=yourpassword +SPRING_DATASOURCE_PASSWORD=securepassword123 # CORS Configuration -CORS_ALLOWED_ORIGINS=http://localhost:3000,https://your-domain.com +CORS_ALLOWED_ORIGINS=http://65.2.166.204, http://localhost:3000, http://localhost, http://mini.awscloudshop.online, https://mini.awscloudshop.online CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS CORS_ALLOWED_HEADERS=* @@ -16,5 +16,7 @@ SPRING_PROFILES_ACTIVE=development SERVER_PORT=8080 # Production Database (for Docker/VPS deployment) -MYSQL_ROOT_PASSWORD=your-secure-production-password +MYSQL_ROOT_PASSWORD=securepassword123 MYSQL_DATABASE=chattingo_db +MYSQL_USER=chattingo +MYSQL_PASSWORD=chatpassword123 diff --git a/backend/src/main/java/com/chattingo/Controller/AuthController.java b/backend/src/main/java/com/chattingo/Controller/AuthController.java index 7ca637d..6210322 100644 --- a/backend/src/main/java/com/chattingo/Controller/AuthController.java +++ b/backend/src/main/java/com/chattingo/Controller/AuthController.java @@ -56,13 +56,10 @@ public ResponseEntity createUserHandler(@RequestBody User user) th userRepository.save(createdUser); - Authentication authentication = this.authenticate(email, password); - SecurityContextHolder.getContext().setAuthentication(authentication); - - - String jwt = this.tokenProvider.generateToken(authentication); - - AuthResponse response = new AuthResponse(jwt, true); + // Don't auto-authenticate on signup + // User should manually sign in after registration + + AuthResponse response = new AuthResponse(null, true); return new ResponseEntity(response, HttpStatus.ACCEPTED); } diff --git a/backend/src/main/java/com/chattingo/Controller/RealTimeChat.java b/backend/src/main/java/com/chattingo/Controller/RealTimeChat.java index 96a5794..36e91bf 100644 --- a/backend/src/main/java/com/chattingo/Controller/RealTimeChat.java +++ b/backend/src/main/java/com/chattingo/Controller/RealTimeChat.java @@ -1,20 +1,24 @@ package com.chattingo.Controller; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.stereotype.Controller; import com.chattingo.Model.Message; +@Controller public class RealTimeChat { + @Autowired private SimpMessagingTemplate simpMessagingTemplate; @MessageMapping("/message") @SendTo("/group/public") public Message recieveMessage(@Payload Message message) { - simpMessagingTemplate.convertAndSend("/group" + message.getChat().getId().toString(), message); + simpMessagingTemplate.convertAndSend("/group/" + message.getChat().getId().toString(), message); return message; } diff --git a/backend/src/main/java/com/chattingo/ServiceImpl/MessageServiceImpl.java b/backend/src/main/java/com/chattingo/ServiceImpl/MessageServiceImpl.java index da6ee1d..fb7b620 100644 --- a/backend/src/main/java/com/chattingo/ServiceImpl/MessageServiceImpl.java +++ b/backend/src/main/java/com/chattingo/ServiceImpl/MessageServiceImpl.java @@ -45,11 +45,17 @@ public Message sendMessage(SendMessageRequest req) throws UserException, ChatExc message = this.messageRepository.save(message); - // Send message to WebSocket topic based on chat type - if (chat.isGroup()) { - messagingTemplate.convertAndSend("/group/" + chat.getId(), message); - } else { - messagingTemplate.convertAndSend( "/user/" + chat.getId(), message); + // TODO: Fix WebSocket messaging - temporarily disabled to prevent 500 errors + try { + // Send message to WebSocket topic based on chat type + if (chat.isGroup()) { + messagingTemplate.convertAndSend("/group/" + chat.getId(), message); + } else { + messagingTemplate.convertAndSend("/user/" + chat.getId(), message); + } + } catch (Exception e) { + // Log the error but don't fail the message creation + System.err.println("WebSocket messaging failed: " + e.getMessage()); } return message; diff --git a/backend/src/main/java/com/chattingo/config/AppConfig.java b/backend/src/main/java/com/chattingo/config/AppConfig.java index 85aa0f2..c36de3a 100644 --- a/backend/src/main/java/com/chattingo/config/AppConfig.java +++ b/backend/src/main/java/com/chattingo/config/AppConfig.java @@ -23,10 +23,10 @@ public class AppConfig { private final JwtValidator jwtValidator; - @Value("${cors.allowed.origins:http://localhost:3000,http://localhost}") + @Value("${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost}") private String allowedOrigins; - @Value("${cors.allowed.methods:GET,POST,PUT,DELETE,OPTIONS}") + @Value("${CORS_ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS}") private String allowedMethods; public AppConfig(JwtValidator jwtValidator) { diff --git a/backend/src/main/java/com/chattingo/config/JwtValidator.java b/backend/src/main/java/com/chattingo/config/JwtValidator.java index 900e6c4..57b9314 100644 --- a/backend/src/main/java/com/chattingo/config/JwtValidator.java +++ b/backend/src/main/java/com/chattingo/config/JwtValidator.java @@ -47,9 +47,9 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse Claims claim = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jwt).getBody(); String username = String.valueOf(claim.get("email")); - String authorities = String.valueOf(claim.get("authorities")); - - List auths = AuthorityUtils.commaSeparatedStringToAuthorityList(authorities); + + // Handle missing authorities claim - use empty list as default + List auths = AuthorityUtils.commaSeparatedStringToAuthorityList(""); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, auths); diff --git a/backend/src/main/java/com/chattingo/config/WebSocketConfig.java b/backend/src/main/java/com/chattingo/config/WebSocketConfig.java index 9c30eab..992c4bb 100644 --- a/backend/src/main/java/com/chattingo/config/WebSocketConfig.java +++ b/backend/src/main/java/com/chattingo/config/WebSocketConfig.java @@ -11,7 +11,7 @@ @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - @Value("${cors.allowed.origins:http://localhost:3000,http://localhost}") + @Value("${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost}") private String allowedOrigins; @SuppressWarnings("null") diff --git a/docker-compose.yml b/docker-compose.yml index 466d14b..9bc7ac9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,7 @@ services: retries: 10 backend: - image: chattingo-app/backend:latest + image: dushyantkumark/chattingo-app-backend:30 env_file: - ./backend/.env depends_on: @@ -31,7 +31,7 @@ services: restart: unless-stopped frontend: - image: chattingo-app/frontend:latest + image: dushyantkumark/chattingo-app-frontend:30 env_file: - ./frontend/.env ports: diff --git a/frontend/src/Components/HomePage.jsx b/frontend/src/Components/HomePage.jsx index 1e9ee2b..9d3721b 100644 --- a/frontend/src/Components/HomePage.jsx +++ b/frontend/src/Components/HomePage.jsx @@ -53,7 +53,7 @@ function HomePage() { Authorization: `Bearer ${token}`, "X-XSRF-TOKEN": getCookie("XSRF-TOKEN"), }, - onConnect: onConnect, + onConnect: () => onConnect(client), onStompError: onError, debug: (str) => { console.log('STOMP: ' + str); @@ -79,17 +79,18 @@ function HomePage() { }; // Callback for successful WebSocket connection - const onConnect = () => { + const onConnect = (client) => { setIsConnected(true); + setStompClient(client); // Ensure the client is set in state // Subscribe to the current chat messages based on the chat type - if (stompClient && currentChat) { + if (client && currentChat) { if (currentChat.group) { // Subscribe to group chat messages - stompClient.subscribe(`/group/${currentChat?.id}`, onMessageReceive); + client.subscribe(`/group/${currentChat?.id}`, onMessageReceive); } else { // Subscribe to direct user messages - stompClient.subscribe(`/user/${currentChat?.id}`, onMessageReceive); + client.subscribe(`/user/${currentChat?.id}`, onMessageReceive); } } }; @@ -128,9 +129,13 @@ function HomePage() { // Effect to handle sending a new message via WebSocket useEffect(() => { - if (message.newMessage && isConnected && stompClient && currentChat?.id) { - stompClient.send("/app/message", {}, JSON.stringify(message.newMessage)); - setMessages((prevMessages) => [...prevMessages, message.newMessage]); + if (message.newMessage && isConnected && stompClient && stompClient.connected && currentChat?.id) { + try { + stompClient.send("/app/message", {}, JSON.stringify(message.newMessage)); + setMessages((prevMessages) => [...prevMessages, message.newMessage]); + } catch (error) { + console.error("Failed to send WebSocket message:", error); + } } }, [message.newMessage, isConnected, stompClient, currentChat]); diff --git a/frontend/src/Components/Register/Signup.jsx b/frontend/src/Components/Register/Signup.jsx index e72f4fc..9feb631 100644 --- a/frontend/src/Components/Register/Signup.jsx +++ b/frontend/src/Components/Register/Signup.jsx @@ -21,9 +21,9 @@ const Signup = () => { e.preventDefault(); const res = await dispatch(register(inputData)); if (res && res.jwt) { - await dispatch(currentUser(res.jwt)); setOpenSnackbar(true); - navigate("/"); + // Don't auto-login, just show success message + // User needs to manually sign in } else { // optionally show error toast/snackbar here } From 9775d3e48ddc8f4bcd26ced3456e0a2c242ce125 Mon Sep 17 00:00:00 2001 From: dushyant Date: Mon, 8 Sep 2025 11:34:55 +0000 Subject: [PATCH 12/15] jenkins shared library --- Jenkinsfile | 155 ++++++++-------------------------------------------- 1 file changed, 24 insertions(+), 131 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ac37c0f..d06f596 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,5 @@ +@Library('jenkins-shared-library') _ + pipeline { agent any @@ -18,28 +20,14 @@ pipeline { } } - stage('Image Build') { - steps { - script { - sh 'docker build --no-cache -t ${FRONTEND_REPO}:${IMAGE_TAG} ./frontend' - sh 'docker build --no-cache -t ${BACKEND_REPO}:${IMAGE_TAG} ./backend' - } - } - } - - stage('Filesystem Scan') { - steps { - script { - sh 'trivy fs --format json --output filesystem-scan-report.json .' - } - } - } - - stage('Image Scan') { + stage('Build and Scan') { steps { script { - sh 'trivy image --format json --output frontend-scan-report.json ${FRONTEND_REPO}:${IMAGE_TAG}' - sh 'trivy image --format json --output backend-scan-report.json ${BACKEND_REPO}:${IMAGE_TAG}' + buildAndScanImages([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) } } } @@ -47,98 +35,25 @@ pipeline { stage('Upload Scans to S3') { steps { script { - def timestamp = new Date().format('yyyy-MM-dd-HH-mm-ss') - - withCredentials([aws(credentialsId: 'aws-cred')]) { - ['filesystem-scan-report.json', 'frontend-scan-report.json', 'backend-scan-report.json'].each { file -> - sh """ - docker run --rm \ - -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ - -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ - -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ - -v \$(pwd):/workspace \ - amazon/aws-cli s3 cp /workspace/${file} s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/${file.replace('.json','')}-${timestamp}.json - """ - } - - def filesystemUrl = sh( - script: """docker run --rm \ - -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ - -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ - -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ - amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/filesystem-scan-report-${timestamp}.json --expires-in 300""", - returnStdout: true - ).trim() - - def frontendUrl = sh( - script: """docker run --rm \ - -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ - -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ - -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ - amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/frontend-scan-report-${timestamp}.json --expires-in 300""", - returnStdout: true - ).trim() - - def backendUrl = sh( - script: """docker run --rm \ - -e AWS_ACCESS_KEY_ID=\$AWS_ACCESS_KEY_ID \ - -e AWS_SECRET_ACCESS_KEY=\$AWS_SECRET_ACCESS_KEY \ - -e AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ - amazon/aws-cli s3 presign s3://${S3_BUCKET}/jenkins-chattingo-app-scanning/backend-scan-report-${timestamp}.json --expires-in 300""", - returnStdout: true - ).trim() - - echo "=== SCAN RESULTS URLS (Valid for 5 minutes) ===" - echo "Filesystem Scan: ${filesystemUrl}" - echo "Frontend Scan: ${frontendUrl}" - echo "Backend Scan: ${backendUrl}" - - writeFile file: 'scan-urls.txt', text: """Filesystem Scan: ${filesystemUrl} - Frontend Scan: ${frontendUrl} - Backend Scan: ${backendUrl} - Generated: ${new Date()} - Expires: 5 minutes""" - } + uploadScansToS3([ + awsCredentialsId: 'aws-cred', + awsRegion: env.AWS_DEFAULT_REGION, + s3Bucket: env.S3_BUCKET + ]) } } } - stage('Push to Registry') { + stage('Deploy Application') { steps { script { - docker.withRegistry('https://index.docker.io/v1/', 'docker-hub-credentials') { - sh 'docker push ${FRONTEND_REPO}:${IMAGE_TAG}' - sh 'docker push ${BACKEND_REPO}:${IMAGE_TAG}' - } - } - } - } - - stage('Update Compose') { - steps { - sh """ - sed -i 's|image: .*frontend.*|image: ${FRONTEND_REPO}:${IMAGE_TAG}|g' docker-compose.yml - sed -i 's|image: .*backend.*|image: ${BACKEND_REPO}:${IMAGE_TAG}|g' docker-compose.yml - """ - } - } - - stage('Deploy') { - steps { - script { - sh """ - echo "updated docker-compose.yml to deployment directory" - cp docker-compose.yml /home/ubuntu/mini/chattingo/ - - # go into deployment folder - cd /home/ubuntu/mini/chattingo - docker compose down - docker compose pull - docker compose up -d - - # return back to original workspace - cd - - """ + deployApplication([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG, + dockerCredentialsId: 'docker-hub-credentials', + deploymentPath: '/home/ubuntu/mini/chattingo/' + ]) } } } @@ -147,31 +62,9 @@ pipeline { post { always { script { - // 1. Archive scan files (latest ones only) - archiveArtifacts artifacts: 'filesystem-scan-report.json,frontend-scan-report.json,backend-scan-report.json,scan-urls.txt', allowEmptyArchive: true - - // 2. Cleanup old scan files in workspace (keep latest only) - sh ''' - echo "Cleaning up old scan reports..." - for f in filesystem-scan-report.json frontend-scan-report.json backend-scan-report.json scan-urls.txt; do - if [ -f "$f" ]; then - echo "Keeping latest: $f" - fi - done - - # remove any older .json or .txt scan reports - find . -maxdepth 1 -type f \\( -name "*scan*.json" -o -name "*scan*.txt" \\) ! -newer scan-urls.txt -exec rm -f {} + - ''' - - // 3. Remove unused Docker images (dangling + old build images) - sh ''' - echo "Cleaning up unused Docker images..." - docker image prune -af --filter "until=24h" || true - - # Remove old build images except the current IMAGE_TAG - docker images --format "{{.Repository}}:{{.Tag}}" | grep chattingo-app || true - docker images --format "{{.Repository}}:{{.Tag}}" | grep chattingo-app | grep -v ":${IMAGE_TAG}" | xargs -r docker rmi -f - ''' + cleanupResources([ + imageTag: env.IMAGE_TAG + ]) } } } From 1b5bc1607cd8c719e7e430e0cb4e2c25018ac4fb Mon Sep 17 00:00:00 2001 From: dushyant Date: Mon, 8 Sep 2025 12:18:00 +0000 Subject: [PATCH 13/15] updating jenkins file --- Jenkinsfile | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d06f596..8871c26 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -20,10 +20,30 @@ pipeline { } } - stage('Build and Scan') { + stage('Build Images') { steps { script { - buildAndScanImages([ + buildImages([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) + } + } + } + + stage('Scan Filesystem') { + steps { + script { + scanFilesystem() + } + } + } + + stage('Scan Images') { + steps { + script { + scanImages([ frontendRepo: env.FRONTEND_REPO, backendRepo: env.BACKEND_REPO, imageTag: env.IMAGE_TAG @@ -44,14 +64,35 @@ pipeline { } } - stage('Deploy Application') { + stage('Push Images') { steps { script { - deployApplication([ + pushImages([ frontendRepo: env.FRONTEND_REPO, backendRepo: env.BACKEND_REPO, imageTag: env.IMAGE_TAG, - dockerCredentialsId: 'docker-hub-credentials', + dockerCredentialsId: 'docker-hub-credentials' + ]) + } + } + } + + stage('Update Compose') { + steps { + script { + updateCompose([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) + } + } + } + + stage('Deploy Application') { + steps { + script { + deployApp([ deploymentPath: '/home/ubuntu/mini/chattingo/' ]) } From e51564f30a19371719d939b214db23d46a98d044 Mon Sep 17 00:00:00 2001 From: dushyant Date: Tue, 9 Sep 2025 04:07:31 +0000 Subject: [PATCH 14/15] my readme file for my work --- README-WORK.md | 758 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 758 insertions(+) create mode 100644 README-WORK.md diff --git a/README-WORK.md b/README-WORK.md new file mode 100644 index 0000000..658c7b8 --- /dev/null +++ b/README-WORK.md @@ -0,0 +1,758 @@ +# Chattingo - Production-Ready Chat Application + +A full-stack real-time chat application built with React, Spring Boot, MySQL, and WebSocket, deployed with Docker, Nginx, SSL, and Jenkins CI/CD pipeline. + +## 🚀 Live Demo + +- **Application**: https://mini.awscloudshop.online +- **Jenkins CI/CD**: https://jenkins.awscloudshop.online + +## 🏗️ Architecture + +``` +Frontend (React) → Nginx Reverse Proxy → Backend (Spring Boot) → MySQL Database + ↓ + Jenkins CI/CD Pipeline + ↓ + Docker Registry + S3 Security Scans + Shared Library +``` + +## 🛠️ Tech Stack + +- **Frontend**: React 18, WebSocket, Tailwind CSS +- **Backend**: Spring Boot, JWT Authentication, WebSocket, Maven +- **Database**: MySQL 8.0 +- **Infrastructure**: Docker, Docker Compose, Nginx +- **CI/CD**: Jenkins with Shared Libraries +- **Security**: Trivy vulnerability scanning, SSL/TLS +- **Cloud**: AWS S3, IAM +- **Server**: Ubuntu VPS (Hostinger) + +## 📋 Prerequisites + +- Ubuntu VPS with root access +- Domain name with DNS configured +- Docker & Docker Compose +- Git +- Node.js 18+ (for local development) +- Java 17+ (for local development) + +## 🚀 Quick Start + +### Clone Repository +```bash +git clone https://github.com/dushyantkumark/chattingo.git +cd chattingo +``` + +### Environment Setup +```bash +# Copy environment templates +cp frontend/.env.example frontend/.env +cp backend/.env.example backend/.env + +# Generate JWT secret +openssl rand -base64 64 + +# Update .env files with your configurations +``` + +### Local Development +```bash +# Start with Docker Compose +docker-compose up -d + +# Or run individually +cd backend && ./mvnw spring-boot:run +cd frontend && npm start +``` + +### Production Deployment +```bash +# Build and deploy +docker-compose build +docker-compose up -d +``` + +## 🔧 Configuration + +### Frontend Environment (.env) +```env +# Development +REACT_APP_API_URL=http://localhost:8080 + +# Production +REACT_APP_API_URL=https://mini.awscloudshop.online +``` + +### Backend Environment (.env) +```env +# JWT Configuration +JWT_SECRET=your-generated-jwt-secret-here + +# Database Configuration +SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/chattingo_db?createDatabaseIfNotExist=true +SPRING_DATASOURCE_USERNAME=root +SPRING_DATASOURCE_PASSWORD=securepassword123 + +# CORS Configuration +CORS_ALLOWED_ORIGINS=https://mini.awscloudshop.online,http://localhost:8080,http://localhost:3000 +CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS +CORS_ALLOWED_HEADERS=* + +# Application Configuration +SPRING_PROFILES_ACTIVE=production +SERVER_PORT=8080 + +# MySQL Configuration +MYSQL_ROOT_PASSWORD=securepassword123 +MYSQL_DATABASE=chattingo_db +MYSQL_USER=chattingo +MYSQL_PASSWORD=chatpassword123 +``` + +## 🐳 Docker Configuration + +### Frontend Dockerfile +```dockerfile +# Multi-stage build for React +FROM node:18-alpine AS build-env +WORKDIR /app +COPY package*.json ./ +RUN npm install --only=production + +FROM node:18-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM node:18-alpine AS runtime +WORKDIR /app +COPY --from=build /app/build ./build +RUN npm install -g serve +EXPOSE 3000 +CMD ["serve", "-s", "build", "-l", "3000"] +``` + +### Backend Dockerfile +```dockerfile +# Multi-stage build for Spring Boot +FROM maven:3.9.6-eclipse-temurin-17 AS build-env +WORKDIR /app +COPY pom.xml ./ +RUN mvn dependency:go-offline + +FROM maven:3.9.6-eclipse-temurin-17 AS build +WORKDIR /app +COPY pom.xml ./ +COPY src ./src +RUN mvn clean package -DskipTests + +FROM eclipse-temurin:17-jre-alpine AS runtime +WORKDIR /app +COPY --from=build /app/target/*.jar app.jar +EXPOSE 8080 +CMD ["java", "-jar", "app.jar"] +``` + +### Docker Compose +```yaml +services: + mysql: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: securepassword123 + MYSQL_DATABASE: chattingo_db + MYSQL_USER: chattingo + MYSQL_PASSWORD: chatpassword123 + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + networks: + - chattingo-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + timeout: 20s + retries: 10 + + backend: + image: dushyantkumark/chattingo-app-backend:latest + env_file: + - ./backend/.env + depends_on: + mysql: + condition: service_healthy + ports: + - "8080:8080" + networks: + - chattingo-network + restart: unless-stopped + + frontend: + image: dushyantkumark/chattingo-app-frontend:latest + env_file: + - ./frontend/.env + ports: + - "3000:3000" + networks: + - chattingo-network + restart: unless-stopped + +volumes: + mysql_data: + +networks: + chattingo-network: + driver: bridge +``` + +## 🌐 Nginx Configuration + +### VPS Setup Commands +```bash +# Update system and install Nginx + Certbot +sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx + +# Create Nginx configuration +sudo nano /etc/nginx/sites-available/chattingo +``` + +### Nginx Virtual Host +```nginx +server { + listen 80; + server_name mini.awscloudshop.online; + + # Block access to hidden files + location ~ /\.(?!well-known) { + deny all; + } + + # Frontend + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + } + + # Backend API + location /api/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Auth endpoints + location /auth/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # WebSocket endpoints + location /ws/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 86400; + } +} +``` + +### SSL Setup +```bash +# Enable site and test configuration +sudo ln -s /etc/nginx/sites-available/chattingo /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx + +# Obtain SSL certificate +sudo certbot --nginx -d mini.awscloudshop.online --non-interactive --agree-tos -m your-email@example.com + +# Test auto-renewal +sudo certbot renew --dry-run +``` + +## 🔄 Jenkins CI/CD Pipeline + +### Jenkins Installation +```bash +# Install Java and Jenkins +sudo apt update && sudo apt install -y openjdk-17-jdk wget +curl -fsSL https://pkg.jenkins.io/debian/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc +echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list +sudo apt update && sudo apt install -y jenkins + +# Change Jenkins port (backend uses 8080) +sudo nano /etc/default/jenkins +# Set HTTP_PORT=8000 +sudo systemctl restart jenkins + +# Get initial admin password +sudo cat /var/lib/jenkins/secrets/initialAdminPassword +``` + +# Create Nginx configuration for Jenkins +sudo nano /etc/nginx/sites-available/jenkins +``` + +### Nginx Virtual Host +```nginx +server { + listen 80; + server_name jenkins.awscloudshop.online; + + # Block access to hidden files + location ~ /\.(?!well-known) { + deny all; + } + + # Frontend + location / { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + } +} +``` + +### SSL Setup +```bash +# Enable site and test configuration +sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx + +# Obtain SSL certificate +sudo certbot --nginx -d jenkins.awscloudshop.online --non-interactive --agree-tos -m your-email@example.com + +# Test auto-renewal +sudo certbot renew --dry-run +``` + +### Jenkins Shared Library + +The project uses a Jenkins Shared Library for reusable pipeline functions: + +**Repository**: https://github.com/dushyantkumark/jenkins-shared-library.git +**Branch**: `feat/library` + +**Functions Available**: +- `buildImages()` - Build Docker images for frontend and backend +- `scanFilesystem()` - Run Trivy filesystem vulnerability scan +- `scanImages()` - Run Trivy Docker image vulnerability scans +- `uploadScansToS3()` - Upload scan results to S3 with pre-signed URLs +- `pushImages()` - Push Docker images to registry +- `updateCompose()` - Update docker-compose.yml with new image tags +- `deployApp()` - Deploy application using docker-compose +- `cleanupResources()` - Clean up Docker resources and artifacts + +### Jenkins Shared Library Setup + +**Configure Global Pipeline Libraries**: +- Go to **Manage Jenkins** → **Configure System** → **Global Pipeline Libraries** +- Click **Add** and configure: + - **Name**: `jenkins-shared-library` + - **Default Version**: `feat/library` + - **Retrieval Method**: Modern SCM → Git + - **Project Repository**: `https://github.com/dushyantkumark/jenkins-shared-library.git` + - **Credentials**: (if private repo, otherwise leave blank) + +**Library Structure**: +``` +jenkins-shared-library/ +├── vars/ +│ ├── buildImages.groovy +│ ├── scanFilesystem.groovy +│ ├── scanImages.groovy +│ ├── uploadScansToS3.groovy +│ ├── pushImages.groovy +│ ├── updateCompose.groovy +│ ├── deployApp.groovy +│ └── cleanupResources.groovy +└── README.md +``` + +### Pipeline Configuration + +**Jenkinsfile** (using shared library): +```groovy +@Library('jenkins-shared-library@feat/library') _ + +pipeline { + agent any + + environment { + DOCKER_HUB_CREDENTIALS = credentials('docker-hub-credentials') + AWS_CREDENTIALS = credentials('aws-cred') + FRONTEND_REPO = credentials('frontend-repo') + BACKEND_REPO = credentials('backend-repo') + IMAGE_TAG = "${BUILD_NUMBER}" + AWS_DEFAULT_REGION = credentials('my-region') + S3_BUCKET = credentials('bucket') + } + + stages { + stage('Git Clone') { + steps { + git branch: 'mini-hackathon', url: 'https://github.com/dushyantkumark/chattingo.git' + } + } + + stage('Build Images') { + steps { + script { + buildImages([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) + } + } + } + + stage('Scan Filesystem') { + steps { + script { + scanFilesystem() + } + } + } + + stage('Scan Images') { + steps { + script { + scanImages([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) + } + } + } + + stage('Upload Scans to S3') { + steps { + script { + uploadScansToS3([ + awsCredentialsId: 'aws-cred', + awsRegion: env.AWS_DEFAULT_REGION, + s3Bucket: env.S3_BUCKET + ]) + } + } + } + + stage('Push Images') { + steps { + script { + pushImages([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG, + dockerCredentialsId: 'docker-hub-credentials' + ]) + } + } + } + + stage('Update Compose') { + steps { + script { + updateCompose([ + frontendRepo: env.FRONTEND_REPO, + backendRepo: env.BACKEND_REPO, + imageTag: env.IMAGE_TAG + ]) + } + } + } + + stage('Deploy Application') { + steps { + script { + deployApp([ + deploymentPath: '/home/ubuntu/mini/chattingo/' + ]) + } + } + } + } + + post { + always { + script { + cleanupResources([ + imageTag: env.IMAGE_TAG + ]) + } + archiveArtifacts artifacts: 'filesystem-scan-results.txt,docker-scan-results.txt,scan-urls.txt', allowEmptyArchive: true + } + } +} +``` + +### Required Jenkins Credentials +- `docker-hub-credentials`: Docker Hub username/password +- `aws-cred`: AWS Access Key/Secret for S3 uploads +- `frontend-repo`: Docker repository name for frontend (e.g., `dushyantkumark/chattingo-app-frontend`) +- `backend-repo`: Docker repository name for backend (e.g., `dushyantkumark/chattingo-app-backend`) +- `my-region`: AWS region (e.g., `ap-south-1`) +- `bucket`: S3 bucket name for scan reports (e.g., `chattingo-app`) + +## 🔒 Security Features + +### Vulnerability Scanning with Trivy +```bash +# Install Trivy +wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_0.55.0_Linux-64bit.deb +sudo dpkg -i trivy_0.55.0_Linux-64bit.deb + +# Scan filesystem +trivy fs . + +# Scan Docker images +trivy image your-image:tag +``` + +### AWS IAM Configuration + +**IAM User Policy**: +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllowListBucket", + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::chattingo-app" + }, + { + "Sid": "AllowReadWriteObjects", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject" + ], + "Resource": "arn:aws:s3:::chattingo-app/*" + } + ] +} +``` + +**S3 Bucket Policy**: +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AllowJenkinsUserAccess", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::YOUR-ACCOUNT-ID:user/chattingo-app-user" + }, + "Action": [ + "s3:GetObject", + "s3:PutObject" + ], + "Resource": "arn:aws:s3:::chattingo-app/jenkins-chattingo-app-scanning/*" + } + ] +} +``` + +## 📊 Application Features + +### Core Functionality +- **Real-time Chat**: WebSocket-based messaging +- **User Authentication**: JWT-based login/signup +- **User Management**: Profile management +- **Message History**: Persistent chat storage +- **Responsive Design**: Mobile-friendly UI + +### Technical Features +- **Multi-stage Docker builds** for optimized images +- **Health checks** for database connectivity +- **Graceful shutdowns** and restart policies +- **Environment-based configuration** +- **CORS handling** for cross-origin requests +- **WebSocket proxy** configuration + +## 📁 Project Structure + +``` +chattingo/ +├── frontend/ # React application +│ ├── src/ +│ │ ├── Components/ # React components +│ │ ├── Redux/ # State management +│ │ └── config/ # Configuration files +│ ├── public/ # Static assets +│ ├── Dockerfile # Frontend container +│ ├── package.json # Dependencies +│ └── .env # Environment variables +├── backend/ # Spring Boot application +│ ├── src/ +│ │ ├── main/java/ # Java source code +│ │ └── test/ # Test files +│ ├── Dockerfile # Backend container +│ ├── pom.xml # Maven dependencies +│ └── .env # Environment variales +├── docker-compose.yml # Container orchestration +├── Jenkinsfile # CI/CD pipeline +├── .gitignore # Git ignore rules +├── CONTRIBUTING.md # Development guide +└── README.md # This file +``` + +## 🚀 Deployment Commands + +### Development +```bash +# Start all services +docker compose up -d + +# View logs +docker compose logs -f + +# Rebuild after changes +docker compose build && docker compose up -d + +# Stop services +docker compose down +``` + +### Production +```bash +# Deploy with specific tags +docker compose pull +docker compose up -d + +# Update single service +docker compose up -d --no-deps backend + +# Check service status +docker compose ps +``` + +## 🔧 Troubleshooting + +### Common Issues + +**CORS Errors** +- Update `CORS_ALLOWED_ORIGINS` in backend .env +- Restart backend container + +**WebSocket Connection Failed** +- Check Nginx WebSocket proxy configuration +- Verify `/ws/` endpoint routing + +**JWT Authentication Issues** +- Ensure JWT_SECRET is properly set +- Check token expiration settings + +**Database Connection Errors** +- Verify MySQL container is healthy +- Check database credentials in .env + +**Build Failures** +- Clear Docker build cache: `docker system prune -a` +- Check Dockerfile syntax + +**Jenkins Shared Library Issues** +- Verify library configuration in Jenkins +- Check branch name: `feat/library` +- Ensure repository is accessible + +### Debug Commands +```bash +# Check container status +docker compose ps + +# View container logs +docker compose logs backend +docker compose logs frontend +docker compose logs mysql + +# Test database connection +docker compose exec mysql mysql -u root -p + +# Check Nginx configuration +sudo nginx -t + +# View SSL certificate status +sudo certbot certificates + +# Check Jenkins logs +sudo journalctl -u jenkins -f +``` + +## 📊 Monitoring & Logs + +### Application Monitoring +- **Container Health**: Docker health checks +- **Application Logs**: Centralized logging via Docker +- **SSL Certificate**: Auto-renewal with Certbot +- **Security Scans**: Automated Trivy reports uploaded to S3 + +### Log Locations +- **Application Logs**: `docker-compose logs` +- **Nginx Logs**: `/var/log/nginx/` +- **Jenkins Logs**: `/var/log/jenkins/` +- **System Logs**: `journalctl` +- **Security Scan Reports**: S3 bucket with pre-signed URLs + +## 🤝 Contributing + +- Fork the repository +- Create feature branch (`git checkout -b feature/amazing-feature`) +- Commit changes (`git commit -m 'Add amazing feature'`) +- Push to branch (`git push origin feature/amazing-feature`) +- Open Pull Request + +## 📝 License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## 🙏 Acknowledgments + +- Built during the Chattingo Mini Hackathon +- Hostinger VPS for infrastructure hosting +- AWS for cloud services and S3 storage +- Jenkins community for CI/CD automation tools +- Docker for containerization platform +- Jenkins Shared Library: https://github.com/dushyantkumark/jenkins-shared-library.git + +--- + +**🌐 Live Application**: https://mini.awscloudshop.online +**🔧 Jenkins Pipeline**: https://jenkins.awscloudshop.online +**📚 Chattingo Application**: https://github.com/dushyantkumark/chattingo.git (branch: feat/jenkinsLibrary) +**📚 Jenkins Shared Library**: https://github.com/dushyantkumark/jenkins-shared-library.git (branch: feat/library) +**📊 Security Reports**: Available via S3 pre-signed URLs in Jenkins builds. From 8ab11bc86d819d835e0f3ee2b47e430c493f118f Mon Sep 17 00:00:00 2001 From: dushyant Date: Wed, 10 Sep 2025 13:55:25 +0000 Subject: [PATCH 15/15] nginx configuration part for application and jenkins --- nginx/jenkins-nginx.conf | 13 ++++++ nginx/nginx.conf | 85 +++++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 nginx/jenkins-nginx.conf diff --git a/nginx/jenkins-nginx.conf b/nginx/jenkins-nginx.conf new file mode 100644 index 0000000..9003505 --- /dev/null +++ b/nginx/jenkins-nginx.conf @@ -0,0 +1,13 @@ +server { + listen 80; + server_name jenkins.awscloudshop.online; + + location / { + proxy_pass http://127.0.0.1:8000; # Jenkins is running here + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + diff --git a/nginx/nginx.conf b/nginx/nginx.conf index d2888da..0069c40 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,40 +1,63 @@ -events { - worker_connections 1024; -} +server { + listen 80; + server_name mini.awscloudshop.online; -http { - upstream frontend { - server frontend:3000; + # Frontend + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; } - upstream backend { - server backend:8080; + # Backend API + location /api/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; } - server { - listen 80; - server_name ; - - location / { - proxy_pass http://frontend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + # Auth endpoints + location /auth/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + } - location /api { - proxy_pass http://backend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + # WebSocket endpoints + location /ws/ { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + proxy_read_timeout 86400; + } - location /ws { - proxy_pass http://backend; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - } + # Block access to hidden files + location ~ /\.(?!well-known) { + deny all; } } +