From 2913e2439867206e81d5e0dcf4b5f42b4b0eb297 Mon Sep 17 00:00:00 2001 From: Promise Fru Date: Tue, 19 Nov 2024 13:48:12 +0100 Subject: [PATCH] feat: add staging deployment pipline. --- .github/workflows/staging-deploy.yml | 51 ++++++++++++++++++++++++++++ Dockerfile | 25 ++++++++++++++ docker-compose.yml | 16 +++++++++ nginx/nginx.conf.template | 43 +++++++++++++++++++++++ run_compose.sh | 3 ++ scripts/docker-entrypoint.sh | 11 ++++++ 6 files changed, 149 insertions(+) create mode 100644 .github/workflows/staging-deploy.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx/nginx.conf.template create mode 100755 run_compose.sh create mode 100644 scripts/docker-entrypoint.sh diff --git a/.github/workflows/staging-deploy.yml b/.github/workflows/staging-deploy.yml new file mode 100644 index 0000000..a878cbb --- /dev/null +++ b/.github/workflows/staging-deploy.yml @@ -0,0 +1,51 @@ +name: Deploy RelaySMS Documentation on Server (staging) +on: + push: + branches: + - staging +jobs: + deploy: + name: Execute Deployment Script on Server + runs-on: ubuntu-latest + environment: + name: staging + url: https://staging.smswithoutborders.com:19500 + steps: + - name: Execute Remote SSH Commands + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + script: | + set -e + + echo "============================" + echo "🚀 Updating repository ..." + echo "============================" + cd ${{ secrets.PROJECT_PATH }} + if ! git pull; then + echo "❌ Error updating repository!" + exit 1 + fi + echo "===============================" + echo "✅ Repository update complete" + echo "===============================" + + echo "=========================" + echo "🚀 Building project ..." + echo "=========================" + if ! ${{ secrets.BUILD_CMD }}; then + echo "❌ Error building project!" + exit 1 + fi + echo "===========================" + echo "✅ Project build complete" + echo "===========================" + if ! ${{ secrets.CLEANUP_CMD }}; then + echo "❌ Error cleaning up builds!" + exit 1 + fi + echo "=============================" + echo "✅ Cleanup complete" + echo "=============================" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9efd71f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM node:20-alpine as build +WORKDIR /app + +COPY package.json ./ + +RUN npm install -g pnpm +RUN pnpm install + +COPY . . + +RUN pnpm build + +FROM nginx:stable-alpine + +COPY --from=build /app/build /usr/share/nginx/html + +COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.template + +COPY scripts/docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +EXPOSE 80 +EXPOSE 443 + +CMD ["/docker-entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d8cde40 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +services: + relaysms-docs: + container_name: relaysms-docs + restart: always + build: + context: . + dockerfile: Dockerfile + ports: + - ${PORT:-80}:80 + - ${SSL_PORT:-443}:443 + environment: + - SERVER_NAME=${SERVER_NAME:-localhost} + volumes: + - ${SSL_CERTIFICATE_PATH:?err}:/etc/nginx/ssl/cert.pem + - ${SSL_KEY_PATH:?err}:/etc/nginx/ssl/key.pem + - ${SSL_CHAIN_PATH:?err}:/etc/nginx/ssl/chain.pem diff --git a/nginx/nginx.conf.template b/nginx/nginx.conf.template new file mode 100644 index 0000000..fcc8230 --- /dev/null +++ b/nginx/nginx.conf.template @@ -0,0 +1,43 @@ +server { + listen 80; + server_name {{SERVER_NAME}}; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl http2; + server_name {{SERVER_NAME}}; + + ssl_certificate /etc/nginx/ssl/cert.pem; + ssl_certificate_key /etc/nginx/ssl/key.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; + ssl_ecdh_curve secp384r1; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + ssl_trusted_certificate /etc/nginx/ssl/chain.pem; + resolver 8.8.8.8 8.8.4.4 valid=300s; + resolver_timeout 5s; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; + add_header X-XSS-Protection "1; mode=block"; + add_header Referrer-Policy "strict-origin"; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com; font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com; img-src 'self' data: https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com;"; + add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options nosniff; + + server_tokens off; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri.html $uri/ /index.html; + } +} diff --git a/run_compose.sh b/run_compose.sh new file mode 100755 index 0000000..0cf7040 --- /dev/null +++ b/run_compose.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker compose -p staging-smswithoutborders up -d --build diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh new file mode 100644 index 0000000..6fbbf6c --- /dev/null +++ b/scripts/docker-entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +# Replace placeholders in NGINX configuration template with environment variable values +sed -i "s|{{SERVER_NAME}}|${SERVER_NAME}|g" /etc/nginx/conf.d/default.template + +# Copy the modified NGINX configuration from template +cp /etc/nginx/conf.d/default.template /etc/nginx/conf.d/default.conf + +# Start NGINX +nginx -g "daemon off;"