diff --git a/.env.example b/.env.example
index f8209f46d40bb5947e16d98f126b6f2a634ed246..4b6ec2500455d9d90dbdb2eb2da08f22c69b6e80 100644
--- a/.env.example
+++ b/.env.example
@@ -9,5 +9,8 @@ DB_NAME=film-db
 # ADMINER
 ADMINER_PORT=8080
 
+# NGINX
+NGINX_PORT=3050
+
 # CLIENT
 CLIENT_PORT=3000
diff --git a/.gitignore b/.gitignore
index 6ee69d07071012e1d6c3dc09e75e27033a89bca0..4e9d991eebf180ab844f733929a2de14026601a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,5 @@
-# Node
-node_modules/
-
 # JetBrains IDEA
 .idea/
 
 # .env files
 .env
-
-# Database
-database-storage
diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js
index 8f5aedb718c87c8f4a192c2530ad1f90efc8dc25..b9aada61a79eb6224475099eed969af5cbd835c4 100644
--- a/backend/.eslintrc.js
+++ b/backend/.eslintrc.js
@@ -17,9 +17,85 @@ module.exports = {
   },
   ignorePatterns: ['.eslintrc.js'],
   rules: {
-    '@typescript-eslint/interface-name-prefix': 'off',
-    '@typescript-eslint/explicit-function-return-type': 'off',
-    '@typescript-eslint/explicit-module-boundary-types': 'off',
-    '@typescript-eslint/no-explicit-any': 'off',
+    '@typescript-eslint/explicit-function-return-type': ['error'],
+    '@typescript-eslint/no-explicit-any': ['error'],
+    '@typescript-eslint/prefer-nullish-coalescing': ['error'],
+    '@typescript-eslint/restrict-plus-operands': ['error'],
+    '@typescript-eslint/type-annotation-spacing': ['error'],
+
+    '@typescript-eslint/brace-style': ['error', '1tbs'],
+    '@typescript-eslint/comma-spacing': ['error', { 'before': false, 'after': true }],
+    '@typescript-eslint/default-param-last': ['error'],
+    '@typescript-eslint/dot-notation': ['error'],
+    '@typescript-eslint/indent': ['error', 2],
+    '@typescript-eslint/keyword-spacing': ['error', { 'before': true, 'after': true }],
+    '@typescript-eslint/no-empty-function': ['error'],
+    '@typescript-eslint/no-extra-parens': ['error'],
+    '@typescript-eslint/no-extra-semi': ['error'],
+    '@typescript-eslint/no-shadow': ['error'],
+    '@typescript-eslint/no-unused-expressions': ['error'],
+    '@typescript-eslint/no-unused-vars': ['error'],
+    '@typescript-eslint/quotes': ['error', 'single'],
+    '@typescript-eslint/require-await': ['error'],
+    '@typescript-eslint/semi': ['error', 'always'],
+    '@typescript-eslint/space-before-blocks': ['error'],
+
+    'no-unreachable': 'error',
+    'no-unused-vars': 'off',
+
+    'camelcase': 'error',
+    'default-param-last': 'off',
+    'dot-notation': 'off',
+    'eqeqeq': 'error',
+    'no-confusing-arrow': 'error',
+    'no-else-return': 'error',
+    'no-empty': 'error',
+    'no-empty-function': 'off',
+    'no-extra-semi': 'off',
+    'no-lonely-if': 'error',
+    'no-mixed-operators': 'error',
+    'no-multi-assign': 'error',
+    'no-negated-condition': 'error',
+    'no-nested-ternary': 'error',
+    'no-param-reassign': 'error',
+    'no-shadow': 'off',
+    'no-shadow-restricted-names': 'error',
+    'no-throw-literal': 'error',
+    'no-unneeded-ternary': 'error',
+    'no-unused-expressions': 'off',
+    'no-useless-rename': 'error',
+    'no-useless-return': 'error',
+    'no-var': 'error',
+    'operator-assignment': ['error', 'always'],
+    'prefer-const': 'error',
+    'prefer-template': 'error',
+    'require-await': 'off',
+    'require-yield': 'error',
+    'spaced-comment': ['error', 'always'],
+
+    'arrow-parens': ['error', 'always'],
+    'arrow-spacing': 'error',
+    'block-spacing': 'error',
+    'brace-style': 'off',
+    'comma-spacing': 'off',
+    'comma-style': ['error', 'last'],
+    'func-call-spacing': ['error', 'never'],
+    'implicit-arrow-linebreak': ['error', 'beside'],
+    'indent': 'off',
+    'jsx-quotes': ['error', 'prefer-single'],
+    'keyword-spacing': 'off',
+    'no-mixed-spaces-and-tabs': 'error',
+    'no-multi-spaces': 'error',
+    'no-multiple-empty-lines': 'error',
+    'no-tabs': 'error',
+    'no-trailing-spaces': 'error',
+    'no-whitespace-before-property': 'error',
+    'quotes': 'off',
+    'rest-spread-spacing': ['error', 'never'],
+    'semi': 'off',
+    'space-before-blocks': 'off',
+    'space-in-parens': 'error',
+    'switch-colon-spacing': 'error',
+    'wrap-regex': 'error',
   },
 };
diff --git a/backend/.gitignore b/backend/.gitignore
index 22f55adc5647206db11558139164c3deb77f5c01..5bb3f5e76208dba8b65262ca659ef2519c9385ca 100644
--- a/backend/.gitignore
+++ b/backend/.gitignore
@@ -1,3 +1,6 @@
+# Database
+database-storage
+
 # compiled output
 /dist
 /node_modules
diff --git a/backend/.prettierrc b/backend/.prettierrc
index dcb72794f5300a3e0ccd2ad0669d802b62f3d370..920290445a33e01b1497022e6106dbd300585243 100644
--- a/backend/.prettierrc
+++ b/backend/.prettierrc
@@ -1,4 +1,5 @@
 {
   "singleQuote": true,
-  "trailingComma": "all"
+  "trailingComma": "all",
+  "bracketSameLine": true
 }
\ No newline at end of file
diff --git a/backend/package-lock.json b/backend/package-lock.json
index a85dbef5bd9029312a90321961a7dfa6adabed22..ca5a6ee8fbbf039a2b1660f247e2d90311f7c3da 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -10,6 +10,7 @@
       "license": "UNLICENSED",
       "dependencies": {
         "@nestjs/common": "^8.0.0",
+        "@nestjs/config": "^2.1.0",
         "@nestjs/core": "^8.0.0",
         "@nestjs/platform-express": "^8.0.0",
         "jshint": "^2.13.4",
@@ -1541,6 +1542,22 @@
         }
       }
     },
+    "node_modules/@nestjs/config": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.1.0.tgz",
+      "integrity": "sha512-wUpt1/QJEN7xnJl4pM3c9rHrY1widq2yPOZfjaMD1//XAP9LLHTaW+RxSEG6BSGIm3w4wGtjco+gKNB2WL7yRg==",
+      "dependencies": {
+        "dotenv": "16.0.1",
+        "dotenv-expand": "8.0.3",
+        "lodash": "4.17.21",
+        "uuid": "8.3.2"
+      },
+      "peerDependencies": {
+        "@nestjs/common": "^7.0.0 || ^8.0.0",
+        "reflect-metadata": "^0.1.13",
+        "rxjs": "^6.0.0 || ^7.2.0"
+      }
+    },
     "node_modules/@nestjs/core": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.6.tgz",
@@ -3523,6 +3540,22 @@
         "domelementtype": "1"
       }
     },
+    "node_modules/dotenv": {
+      "version": "16.0.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
+      "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/dotenv-expand": {
+      "version": "8.0.3",
+      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz",
+      "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -9979,6 +10012,17 @@
         "uuid": "8.3.2"
       }
     },
+    "@nestjs/config": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.1.0.tgz",
+      "integrity": "sha512-wUpt1/QJEN7xnJl4pM3c9rHrY1widq2yPOZfjaMD1//XAP9LLHTaW+RxSEG6BSGIm3w4wGtjco+gKNB2WL7yRg==",
+      "requires": {
+        "dotenv": "16.0.1",
+        "dotenv-expand": "8.0.3",
+        "lodash": "4.17.21",
+        "uuid": "8.3.2"
+      }
+    },
     "@nestjs/core": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.6.tgz",
@@ -11518,6 +11562,16 @@
         "domelementtype": "1"
       }
     },
+    "dotenv": {
+      "version": "16.0.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
+      "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ=="
+    },
+    "dotenv-expand": {
+      "version": "8.0.3",
+      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz",
+      "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg=="
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
diff --git a/backend/package.json b/backend/package.json
index 8c71fb3e7ca4c36dbbe8e3a77716bd8be33803db..21cdb97e6e3e69b5129c275f8a811eb986e64a49 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -22,6 +22,7 @@
   },
   "dependencies": {
     "@nestjs/common": "^8.0.0",
+    "@nestjs/config": "^2.1.0",
     "@nestjs/core": "^8.0.0",
     "@nestjs/platform-express": "^8.0.0",
     "jshint": "^2.13.4",
diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts
index 86628031ca2a10fe172fe824f69d1720c44b43ce..278b638f9d853fe8c1ff8cb67ea693775b49b99e 100644
--- a/backend/src/app.module.ts
+++ b/backend/src/app.module.ts
@@ -1,9 +1,10 @@
 import { Module } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
 import { AppController } from './app.controller';
 import { AppService } from './app.service';
 
 @Module({
-  imports: [],
+  imports: [ConfigModule.forRoot()],
   controllers: [AppController],
   providers: [AppService],
 })
diff --git a/backend/src/main.ts b/backend/src/main.ts
index 13cad38cff92aa3b3d3ef6232306e450cadf5713..7ec8d4b3d866f07bcd7d37cf38ec08df84363467 100644
--- a/backend/src/main.ts
+++ b/backend/src/main.ts
@@ -1,8 +1,14 @@
 import { NestFactory } from '@nestjs/core';
+import { ConfigService } from '@nestjs/config';
 import { AppModule } from './app.module';
 
-async function bootstrap() {
+async function bootstrap(): Promise<void> {
   const app = await NestFactory.create(AppModule);
-  await app.listen(3000);
+  const configService = app.get(ConfigService);
+
+  const port = configService.get<number>('PORT');
+  console.log(`NestJS server is listening on: http://localhost:${port}`);
+  await app.listen(port);
 }
+
 bootstrap();
diff --git a/docker-compose.yml b/docker-compose.yml
index a3c568507ecbf46ba016da700befbefada105898..b7466238cdfb6adb3d288bf0f49a47912eaaaa94 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -8,16 +8,17 @@ services:
       context: ./backend
       dockerfile: Dockerfile
     command: npm run start:debug
-    env_file: .env
     ports:
-      - 127.0.0.1:${SERVER_PORT}:3000
+      - 127.0.0.1:${SERVER_PORT}:${SERVER_PORT}
+    networks:
+      - backend-network
     volumes:
       # changes in host's ./backend directory will be propagated to the container
       - ./backend:/usr/src/app
       # this prevents our host files from overriding container's node_modules
       - exclude-server:/usr/src/app/node_modules/
-    networks:
-      - backend-network
+    environment:
+      - PORT=${SERVER_PORT}
     restart: always
     depends_on:
       - postgres
@@ -25,11 +26,10 @@ services:
   postgres:
     container_name: postgres
     image: postgres:14.3-alpine
-    env_file: .env
-    volumes:
-      - ./backend/database-storage:/var/lib/postgresql/data
     networks:
       - backend-network
+    volumes:
+      - ./backend/database-storage:/var/lib/postgresql/data
     environment:
       POSTGRES_USER: ${DB_USER}
       POSTGRES_PASSWORD: ${DB_PASSWORD}
@@ -39,7 +39,6 @@ services:
   adminer:
     container_name: adminer
     image: adminer:4.8.1
-    env_file: .env
     ports:
       - 127.0.0.1:${ADMINER_PORT}:${ADMINER_PORT}
     networks:
@@ -50,26 +49,51 @@ services:
     depends_on:
       - postgres
 
+  nginx:
+    container_name: nginx
+    image: nginx:1.21.6-alpine
+    ports:
+      - 127.0.0.1:${NGINX_PORT}:${NGINX_PORT}
+    networks:
+      - backend-network
+      - frontend-network
+    volumes:
+      - ./nginx/templates:/etc/nginx/templates
+      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
+    environment:
+      - NGINX_PORT=${NGINX_PORT}
+      - SERVER_PORT=${SERVER_PORT}
+    restart: always
+    depends_on:
+      - server
+      - postgres
+
   client:
     container_name: client
     image: client:1.0.0
     build:
       context: ./frontend
       dockerfile: Dockerfile
-    env_file: .env
     ports:
-      - 127.0.0.1:${CLIENT_PORT}:3000
+      - 127.0.0.1:${CLIENT_PORT}:${CLIENT_PORT}
+    networks:
+     - frontend-network
     volumes:
       # changes in host's ./frontend directory will be propagated to the container
       - ./frontend:/usr/src/app
       # this prevents our host files from overriding container's node_modules
       - exclude-client:/usr/src/app/node_modules/
+    environment:
+      - PORT=${CLIENT_PORT}
+      # all the traffic goes through Nginx server
+      - SERVER_PORT=${NGINX_PORT}
     restart: always
 
+networks:
+  backend-network:
+  frontend-network:
+
 volumes:
   database-storage:
   exclude-server:
   exclude-client:
-
-networks:
-  backend-network:
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 4ae3ca97e58ce0222fa411f31f51a099880126be..6f69c7ad2ac8e1307dc16752fd9a41674bf394b8 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -552,6 +552,11 @@
         "node": ">= 8.0.0"
       }
     },
+    "node_modules/@types/node": {
+      "version": "17.0.42",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz",
+      "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ=="
+    },
     "node_modules/@types/prop-types": {
       "version": "15.7.5",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@@ -2651,6 +2656,11 @@
         "picomatch": "^2.2.2"
       }
     },
+    "@types/node": {
+      "version": "17.0.42",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz",
+      "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ=="
+    },
     "@types/prop-types": {
       "version": "15.7.5",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 0b85ee5e9480eff7fc43e870e19373455966af98..7a04fd94acb28e053476320c97169b67b45d2b94 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import { defineConfig, loadEnv } from 'vite'
 import react from '@vitejs/plugin-react'
 
 // https://vitejs.dev/config/
@@ -7,6 +7,7 @@ export default defineConfig({
   server: {
     watch: {
       usePolling: true
-    }
+    },
+    port: +process.env.PORT
   }
 })
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e39c4ff5b869d5eb4278e325c3b90e6c1e78bb1e
--- /dev/null
+++ b/nginx/nginx.conf
@@ -0,0 +1,28 @@
+user nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log;
+pid        /var/run/nginx.pid;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  include       /etc/nginx/mime.types;
+  default_type  application/octet-stream;
+
+  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                    '$status $body_bytes_sent "$http_referer" '
+                    '"$http_user_agent" "$http_x_forwarded_for"';
+
+  # TODO: logging does not work
+  access_log  /var/log/nginx/access.log;
+
+  sendfile on;
+
+  keepalive_timeout 65;
+
+  # template files in /etc/nginx/templates/*.template are outputed as a result of executing envsubst to the /etc/nginx/conf.d folder
+  include /etc/nginx/conf.d/*.conf;
+}
diff --git a/nginx/templates/default.conf.template b/nginx/templates/default.conf.template
new file mode 100644
index 0000000000000000000000000000000000000000..831ce45a67c5df1ce253e15555ad05d032767c40
--- /dev/null
+++ b/nginx/templates/default.conf.template
@@ -0,0 +1,26 @@
+upstream nestjs_server {
+  server server:${SERVER_PORT};
+}
+
+server {
+  # IPv4
+  listen      ${NGINX_PORT} default_server;
+  # IPv6
+  listen      [::]:${NGINX_PORT} default_server;
+
+  location / {
+    proxy_http_version 1.1;
+    proxy_cache_bypass $http_upgrade;
+
+    #proxy_buffering off;
+
+    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_pass http://nestjs_server;
+  }
+}