diff --git a/lab_2/lab_artifacts/ecosystem.config.js b/lab_2/lab_artifacts/ecosystem.config.js new file mode 100644 index 0000000..182f562 --- /dev/null +++ b/lab_2/lab_artifacts/ecosystem.config.js @@ -0,0 +1,19 @@ +module.exports = { + apps: [ + { + name: 'nestjs-api', + script: 'dist/main.js', + watch: true, + env: { + PORT: 3000, + NODE_ENV: 'development', + ENV_CONFIGURATION: 'dev', + }, + env_production: { + PORT: 3000, + NODE_ENV: 'production', + ENV_CONFIGURATION: 'prod', + }, + }, + ], +}; diff --git a/lab_2/lab_artifacts/move_to_remote_host.sh b/lab_2/lab_artifacts/move_to_remote_host.sh new file mode 100644 index 0000000..1206419 --- /dev/null +++ b/lab_2/lab_artifacts/move_to_remote_host.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +SERVER_HOST_DIR=$(pwd)/nestjs-rest-api +CLIENT_HOST_DIR=$(pwd)/shop-react-redux-cloudfront + +# destination folder names can be changed +SERVER_REMOTE_DIR=/var/app/nestjs-rest-api +CLIENT_REMOTE_DIR=/var/www/shop-client + +CRT=/usr/local/etc/ssl/certs/self-signed.crt; +CRT_KEY=/usr/local/etc/ssl/private/self-signed.key; +SSH_USER=ubuntu-sshuser; + + +check_remote_dir_exists() { + echo "Check if remote directories exist" + + if ssh $SSH_USER "[ ! -d $1 ]"; then + echo "Creating: $1" + ssh -t $SSH_USER "sudo bash -c 'mkdir -p $1 && chown -R sshuser: $1'" + else + echo "Clearing: $1" + ssh $SSH_USER "sudo -S rm -r $1/*" + fi +} + +check_remote_dir_exists $SERVER_REMOTE_DIR +check_remote_dir_exists $CLIENT_REMOTE_DIR + +echo "---> Building and copying server files - START <---" +echo $SERVER_HOST_DIR +cd $SERVER_HOST_DIR && npm run build +scp -Cr dist/ package.json ecosystem.config.js $SSH_USER:$SERVER_REMOTE_DIR +echo "---> Building and transferring server - COMPLETE <---" + +echo "---> Building and transferring client files, cert and ngingx config - START <---" +echo $CLIENT_HOST_DIR +cd $CLIENT_HOST_DIR && npm run build && cd ../ +scp -Cr $CLIENT_HOST_DIR/dist/* $CRT $CRT_KEY $CLIENT_HOST_DIR/nginx.conf $SSH_USER:$CLIENT_REMOTE_DIR +echo "---> Building and transferring - COMPLETE <---" diff --git a/lab_2/lab_artifacts/nginx.conf b/lab_2/lab_artifacts/nginx.conf new file mode 100644 index 0000000..2051a42 --- /dev/null +++ b/lab_2/lab_artifacts/nginx.conf @@ -0,0 +1,76 @@ +upstream rest_api_server { + server localhost:3000; +} + +# configuration for local development of client + +#upstream front_end_app { +# server localhost:4200; +#} + +#server { +# listen 5555; +# location / { +# proxy_pass http://front_end_app; +# proxy_set_header Upgrade $http_upgrade; +# proxy_set_header Connection $http_connection; +# proxy_set_header Host $host; +# } + +# location /api/ { +# proxy_pass http://rest_api_server/; + +# proxy_http_version 1.1; +# proxy_set_header Host $host; +# proxy_set_header X-NginX-Proxy true; +# 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; +# } +#} + +server { + listen 8080; + server_name static-app.net; + root /var/www/shop-client; + index index.html; + location / { + try_files $uri $uri/ /index.html =404; + } + + location /api/ { + proxy_pass http://rest_api_server/; + + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-NginX-Proxy true; + 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; + } +} + +# https secured configuration with SSL keys +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name devops-js-app.net; #desired server_name + + ssl_certificate /var/www/shop-client/self-signed.crt; + ssl_certificate_key /var/www/shop-client/self-signed.key; + + location / { + proxy_pass http://127.0.0.1:8080/; # redirection to configuration for serving static client app + } +} + +# configuration for redirection http -> https +server { + listen 80; + listen [::]:80; + server_name devops-js-app.net; #desired server_name + + location / { + return 301 https://$host$request_uri; + } +} diff --git a/lab_2/lab_artifacts/package.json b/lab_2/lab_artifacts/package.json new file mode 100644 index 0000000..3a96147 --- /dev/null +++ b/lab_2/lab_artifacts/package.json @@ -0,0 +1,80 @@ +{ + "name": "nestjs-rest-api", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "prebuild": "rimraf dist", + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "start:pm2": "pm2 start ecosystem.config.js --env production", + "stop:pm2": "pm2 stop all", + "delete:pm2": "pm2 delete all", + "logs:pm2": "pm2 logs", + "restart:pm2": "pm2 restart nestjs-api", + "kill:pm2": "pm2 kill", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" + }, + "dependencies": { + "@nestjs/common": "^8.0.0", + "@nestjs/core": "^8.0.0", + "@nestjs/platform-express": "^8.0.0", + "class-transformer": "^0.4.0", + "class-validator": "^0.13.1", + "pm2": "^5.2.0", + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.2", + "rxjs": "^7.2.0" + }, + "devDependencies": { + "@nestjs/cli": "^8.0.0", + "@nestjs/schematics": "^8.0.0", + "@nestjs/testing": "^8.0.0", + "@types/express": "^4.17.13", + "@types/jest": "^27.0.1", + "@types/node": "^16.0.0", + "@types/supertest": "^2.0.11", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^27.2.5", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "supertest": "^6.1.3", + "ts-jest": "^27.0.3", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "^3.10.1", + "typescript": "^4.3.5" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } +}