DevBoi

[AWS] Nginx + LetsEncrypt(https) + NestJs + Flutter web 본문

Infra/[AWS]

[AWS] Nginx + LetsEncrypt(https) + NestJs + Flutter web

HiSmith 2024. 5. 15. 13:27
반응형

개인적으로 사용하고 싶어서 만든 채팅 서비스가 있다.

아키텍처에 대한 구조는 아래와 같다.

 

 

그렇게 복잡하지 않다.

NestJs가 소켓처리와 MongoDb와의 통신을 통해 데이터 API 역할을 3000, 8080 포트로 나눠서 지원하고

Flutter web 은 80포트로 왔을때 처리되는 static Resource로 서버에 위치에 있다.

 

물론, 여러개의 서버를 나눠서 두는 방법도 있지만, 이건 사용자 트래픽이 몰리는 경우 고려하도록 하자

 

 

 

1) nginx 세팅

EC2 제일 앞단에서 Nginx 를 둔다.

80,443에 대한 인증서 처리 및 리버스 프록시 설정에 대한 내용들을 다룬다

 

1-1) /etc/nginx/site-avavilbles/default


server {
	listen 80 default_server;
        listen [::]:80 default_server;
	ssl_certificate /etc/letsencrypt/live/rabbithole.co.kr/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/rabbithole.co.kr/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
	root /home/ubuntu/rabbit/web;
	index index.html index.htm index.nginx-debian.html;

        server_name _;

	location / {
         try_files $uri $uri/ /index.html;
         proxy_hide_header Access-Control-Allow-Origin;
         add_header 'Access-Control-Allow-Origin' '*';
         add_header     Content-Security-Policy "upgrade-insecure-requests";
         proxy_http_version 1.1;
        }
        location /api{
          proxy_connect_timeout 300s;
          proxy_read_timeout 600s;
          proxy_send_timeout 600s;
          proxy_buffers 8 16k;
          proxy_buffer_size 32k;
          proxy_pass https://아이피:3000;
        }
        location ^~ /socket{
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://아이피:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        }
}
server {

	

	root /home/ubuntu/rabbit/web;
	index index.html index.htm index.nginx-debian.html;

	server_name _;

	location / {
	  try_files $uri $uri/ /index.html;
          proxy_hide_header Access-Control-Allow-Origin;
          add_header 'Access-Control-Allow-Origin' '*';
          add_header     Content-Security-Policy "upgrade-insecure-requests";
          proxy_http_version 1.1;
	}
	location /api{
          proxy_connect_timeout 300s;
          proxy_read_timeout 600s;
          proxy_send_timeout 600s;
          proxy_buffers 8 16k;
          proxy_buffer_size 32k;
          proxy_pass https://아이피:3000;
        }
        location ^~ /socket{
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $host;
         proxy_pass http://아이피:8080;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
        }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/rabbithole.co.kr/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/rabbithole.co.kr/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}



server {
    if ($host = rabbithole.co.kr) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

	listen 80;
	listen [::]:80;
    server_name rabbithole.co.kr;
    return 404;
}

 

1-2)  /etc/nginx/nginx.conf

nginx로 들어오게되면, 특정 계정의 권한으로 실행된다.

이때 해당 파일들의 권한을 다바꿔주기 귀찮으므로 그냥 root로 해준다.

보안이 필요하면 별도 사용자 계정을 만들어서 설정하면 된다.

해당 파일에서 사용자 및 로깅 설정 위치 등등을 설정할 수있다.

user root;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;

 

이렇게 하면 nginx는 마무리가 된다.

 

2) lets encrypt 

여러 ec2를 사용하면, 로드밸런서에 설정하지만, 단일 인스턴스는 이렇게 설정한다.

certbot 에서 nginx를 위한 플러그인을 설치하지않으면 실행되지않는다는 점을 유의하자

sudo apt install python-certbot-nginx
sudo apt-get update
sudo apt install python-certbot-nginx
sudo apt-get install python-certbot-nginx
sudo apt search python-certbot-nginx
sudo apt-get install python-certbot
certbot --version
sudo certbot --nginx
sudo systemctl restart nginx
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
sudo systemctl status caddy
sudo certbot --nginx
sudo apt install python3-certbot-nginx
sudo certbot --nginx

 

이렇게 되면 앞단의 https설정과, 특정 경로로 유입됬을때 해당 http로 프록시 패스가 가능해진다.

이렇게 활용해서 사용하면 아주 좋다.

 

 

3) nestJs설정

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface'; // CorsOptions 추가
import { IoAdapter } from '@nestjs/platform-socket.io';
import * as fs from 'fs';

async function bootstrap() {

  const httpsOptions = {
    key: fs.readFileSync('./secrets/privkey.pem'),
    cert: fs.readFileSync('./secrets/full-chain.pem'),
  };
  
  const app = await NestFactory.create(AppModule,{httpsOptions});
  const corsOptions: CorsOptions = {
    origin: '*',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    credentials: true,
  };
  app.enableCors(corsOptions);
  app.useWebSocketAdapter(new IoAdapter(app));
  
  await app.listen(3000);

}
bootstrap();

 

4) NestJs 디렉토리 구조

 

DockerFile)

FROM node:18-alpine
RUN mkdir -p /var/app
WORKDIR /var/app
COPY . .
RUN npm install --legacy-peer-deps
RUN npm run build
EXPOSE 3000
CMD [ "node", "dist/main.js" ]

 

Docker-compose)

version: "3.7"
services:
  db:
    container_name: mongo-dev
    image: mongo:4.2
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_DATABASE=auth
      - MONGO_INITDB_ROOT_PASSWORD=pass
    networks:
      - mongo-compose-network
    ports:
      - '27017:27017'
    volumes:
      - ./data:/data/db
  mongo-express:
    container_name: mongo-express
    image: mongo-express
    depends_on:
      - db
    networks:
      - mongo-compose-network
    environment:
      - ME_CONFIG_MONGODB_SERVER=mongo-dev
      - ME_CONFIG_MONGODB_ADMINUSERNAME=계정
      - ME_CONFIG_MONGODB_ADMINPASSWORD=비번
      - ME_CONFIG_BASICAUTH_USERNAME=계정
      - ME_CONFIG_BASICAUTH_PASSWORD=비번
    ports:
      - '8081:8081'
    volumes:
      - ./data:/data/db
  backend:
    container_name: backend
    image: dbtjdwocjswo/rabbit-back:0.0.17
    restart: always
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
    environment:
      - MONGODB_URL=mongodb://계정:비번@아이피:포트/db?authSource=admin
    ports:
      - 8080:8080
      - 3000:3000
    depends_on:
      - db
    networks:
      - mongo-compose-network
networks:
  mongo-compose-network:

 

 

이렇게 하면 우선 구성은  끝난다

커맨드 리스트는 히스토리를 긁은거라, 중복되는 내용이 있을수있다.

반응형