본문 바로가기

Infra

nginx를 활용한 HTTPS 인증 및 Reverse Proxy 구성 방식

Nginx 를 통해 http + ssl 인증을 구현한 https 구성 방법과 도메인 분리시 다중 서버에 Reverse Proxy를 사용하는 방법에 관해 소개할 예정입니다.

 

ex) www.test.com  -> UI 서버 진입

     www.test.com/api -> API 서버 진입

 

웹 애플리케이션을 운영할 때 HTTPS 보안은 필수 요소이며, nginx는 가장 널리 사용되는 고성능 웹 서버이자 리버스 프록시 도구입니다.

 

이 글에서는 nginx를 통해 두 개의 웹 애플리케이션을 구성하고, 경로 기반 리버스 프록시HTTPS 인증서 적용 방식을 소개합니다.

 

PreRequirement 

  • docker
  • docker compose
  • 도메인 주소 (가비아 또는 카페24에서 구매하실 수 있습니다.)

 


✅ 목표 구성

  • nginx가 80/443 포트에서 외부 요청 수신
  • / → WebApp1으로 프록시
  • /api/ → WebApp2로 프록시
  • HTTPS 인증서는 Let's Encrypt의 certbot을 nginx 컨테이너 내에서 직접 설치하여 수동 발급
  • 인증 후 /etc/letsencrypt 경로에서 nginx가 인증서 참조
  • 인증서 갱신은 crontab을 통해 nginx 컨테이너 내부에서 수행

🧱 예시 구성 서비스

서비스 이름 역할 포트
nginx 외부 요청 수신 및 HTTPS 처리, 경로 기반 프록시 80, 443
webapp1 정적 페이지 또는 웹 앱 (예: React, Vue) 8001
webapp2 REST API 또는 백엔드 서비스 (예: FastAPI, Flask) 8002

1. docker-compose를 통해 인프라 IaC관리 

Nginx, Web1, Web2 서비스를 작성합니다.

🐳 docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/html:/var/www/html
      - ./nginx/letsencrypt:/etc/letsencrypt
    networks:
      - webnet
    restart: always

  webapp1:
    image: your-webapp1-image
    container_name: webapp1
    ports:
      - "8001:80"
    networks:
      - webnet
    restart: always

  webapp2:
    image: your-webapp2-image
    container_name: webapp2
    ports:
      - "8002:80"
    networks:
      - webnet
    restart: always

networks:
  webnet:
    driver: bridge

 

2. Nginx Reverse Proxy 설정 conf파일

server {
    listen 80;
    server_name example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS 처리 및 리버스 프록시
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }


    # WebApp2 (API 서버)
    location ^~ /api/ {
        proxy_pass http://webapp2:80/;
        proxy_set_header Host $host;
        proxy_redirect off;
        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 https;
    }

    # WebApp1 (정적 웹 페이지)
    location / {
        proxy_pass http://webapp1:80/;
        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 https;
    }
}

 

3. Nginx SSL 인증 방법

  • docker compose exec -it nginx /bin/bash 
    ※사용하는 Nginx 이미지에 따라 /bin/sh 가 가능하실 수 있습니다.
  • # certbot 설치
    apt update
    apt install -y certbot nano cron
    certbot certonly --webroot -w /var/www/html -d [도메인주소].com
  • crontab -e
  • 아래의 내용 기입
    0 3 * * * certbot renew --webroot -w /var/www/html --quiet && nginx -s reload

※주의 사항

    Nginx 에서 lets encrypt를 통해 ssl 인증시 certbot을 통해 주기적인 ssl 갱신이 필요합니다. 이에 crontab내부에 작성하거나, 

    sh 파일을 작성하여 log를 따로 관리하는 방법도 존재합니다. 해당 방법은 certbot 갱신 sh 파일 작성 crontab에서 sh파일 실행  

    + log 경로 지정을 하게 되시면 log를 따로 관리하여 ssl에 관련된 오류를 따로 관리할 수 있습니다.

 

   docker-compose 파일에 작성된 ./nginx 경로는 상대경로로 지정되어 있으며, 해당 경로를 원하는 nginx 지정 경로로 변경해서 사용하는 걸 추천드립니다.