EC2 IP에 도메인 연결 과 SSL 설치 연결 Nginx config 설정

Hansu·2025년 8월 7일

현재 서비스를 중단하고 다시 시작 할 때 마다 ip주소가 변경되고 있어서 이를 고정 ip로 할당 하기 위한 작업

탄력적 IP 메뉴로 간다.

  • IP 주소 할당

  • 할당 받은 IP를 현재 인스턴스에 연결

  • 도메인을 구매한 곳에서 DNS 설정 해주기

  • 서브 도메인을 입력했을 때 Welcome to nginx
    http://api.domain.com

1단계: AWS EC2 + 도메인 연결

1.1 Elastic IP 할당

EC2 인스턴스는 재시작할 때마다 퍼블릭 IP가 변경되므로, 고정 IP인 Elastic IP를 할당해야 합니다.

AWS 콘솔에서 Elastic IP 할당:
1. EC2 대시보드 → 네트워크 및 보안탄력적 IP
2. 탄력적 IP 주소 할당 클릭
3. 할당된 IP를 EC2 인스턴스에 연결

비용 주의사항:

  • Elastic IP는 EC2 인스턴스에 연결되어 있는 동안 무료
  • 연결되지 않은 상태로 방치하면 시간당 요금 발생

1.2 DNS 설정 (가비아 기준)

A 레코드 추가:

레코드 타입: A
호스트명: api
값: [할당받은 Elastic IP]
TTL: 600

중요한 주의사항:
만약 도메인이 다른 서비스(Vercel, Netlify 등)에 연결되어 있었다면, 네임서버 설정을 확인해야 합니다.

# 현재 네임서버 확인
dig NS yourdomain.com

# 가비아 네임서버로 변경 필요시
ns.gabia.co.kr
ns1.gabia.co.kr
ns.gabia.net

1.3 DNS 전파 확인

# 가비아 DNS 직접 확인 (가장 빠름)
dig @ns1.gabia.co.kr A api.yourdomain.com

# 글로벌 DNS 확인
dig @8.8.8.8 A api.yourdomain.com
dig @1.1.1.1 A api.yourdomain.com

# 기본 DNS 확인
dig A api.yourdomain.com

DNS 전파 시간: 보통 10분~24시간 (TTL 설정에 따라)

1.4 nginx 설치 및 기본 설정

# 시스템 업데이트
sudo apt update

# nginx 설치
sudo apt install nginx -y

# 서비스 시작 및 자동 시작 설정
sudo systemctl start nginx
sudo systemctl enable nginx

# 방화벽 설정
sudo ufw allow 'Nginx Full'

# 설치 확인
curl http://localhost

정상적으로 설치되면 "Welcome to nginx!" 페이지가 표시됩니다.


2단계: SSL 인증서 설치 (Let's Encrypt)

2.1 Certbot 설치

# snap을 통한 최신 certbot 설치
sudo apt install snapd -y
sudo snap install --classic certbot

# 명령어 링크 생성
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# 버전 확인
certbot --version

2.2 SSL 인증서 발급

DNS 전파가 완전히 완료되지 않은 상황에서는 DNS Challenge 방식을 사용하는 것이 가장 안정적입니다.

sudo certbot certonly --manual --preferred-challenges dns -d api.yourdomain.com

진행과정에서 DNS 전파가 제대로 이루어지지 않음으로 인한 메뉴얼 + 첼린지로 진행

DNS Challenge 과정:

  1. TXT 레코드 값 제공받음:

    _acme-challenge.api.yourdomain.com
    값: [Certbot이 제공하는 긴 문자열]
  2. 도메인 관리 페이지에서 TXT 레코드 추가:

    레코드 타입: TXT
    호스트명: _acme-challenge.api
    값: [Certbot이 제공한 값]
    TTL: 600
  3. TXT 레코드 전파 확인:

    dig +short TXT _acme-challenge.api.yourdomain.com
  4. 인증서 발급 완료:

    Certificate is saved at: /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem
    Key is saved at: /etc/letsencrypt/live/api.yourdomain.com/privkey.pem

2.3 인증서 파일 위치

/etc/letsencrypt/live/api.yourdomain.com/
├── fullchain.pem    # 전체 인증서 체인 (nginx에서 사용)
├── privkey.pem      # 개인키 (nginx에서 사용)
├── cert.pem         # 인증서
└── chain.pem        # 중간 인증서

3단계: Flask 앱 서비스 설정

3.1 Flask 앱

  • 기존의 Flask 코드 활용

3.2 systemd 서비스 파일 생성

Flask 앱을 시스템 서비스로 등록하여 자동 시작 및 관리가 가능하도록 설정합니다.

sudo nano /etc/systemd/system/flask-app.service

서비스 파일 내용:

[Unit]
Description=Flask API Application
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/your-project-directory
Environment=PATH=/home/ubuntu/your-project-directory/venv/bin
ExecStart=/home/ubuntu/your-project-directory/venv/bin/python /home/ubuntu/your-project-directory/hello.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

각 옵션 설명:

  • Description: 서비스 설명
  • After=network.target: 네트워크 시작 후 실행
  • Type=simple: 단순 프로세스 타입
  • User=ubuntu: 실행 사용자
  • WorkingDirectory: 작업 디렉토리
  • Environment=PATH: Python 가상환경 경로
  • ExecStart: 실행할 명령어
  • Restart=always: 실패시 자동 재시작
  • RestartSec=10: 재시작 대기 시간

3.3 서비스 활성화

# systemd 데몬 리로드
sudo systemctl daemon-reload

# 서비스 활성화 (부팅시 자동 시작)
sudo systemctl enable flask-app

# 서비스 시작
sudo systemctl start flask-app

# 서비스 상태 확인
sudo systemctl status flask-app

정상 동작 확인:

# Flask 앱 직접 테스트
curl http://localhost:5001
curl http://localhost:5001/hello

4단계: nginx 리버스 프록시 설정

4.1 nginx 사이트 설정 파일 생성

sudo nano /etc/nginx/sites-available/api.yourdomain.com

nginx 설정:

# HTTP to HTTPS 리다이렉트
server {
    listen 80;
    server_name api.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

# HTTPS 서버 블록
server {
    listen 443 ssl;
    server_name api.yourdomain.com;

    # SSL 인증서 설정
    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;

    # 리버스 프록시 설정
    location / {
        proxy_pass http://localhost:5001;
        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;
    }
}

4.2 설정 활성화 및 nginx 재시작

# 설정 파일 활성화
sudo ln -s /etc/nginx/sites-available/api.yourdomain.com /etc/nginx/sites-enabled/

# 기본 설정 비활성화 (포트 충돌 방지)
sudo rm /etc/nginx/sites-enabled/default

# nginx 설정 문법 테스트
sudo nginx -t

# nginx 재시작
sudo systemctl restart nginx

nginx 설정 각 부분 설명:

HTTP → HTTPS 리다이렉트

server {
    listen 80;
    server_name api.yourdomain.com;
    return 301 https://$server_name$request_uri;
}
  • 모든 HTTP 요청을 HTTPS로 영구 리다이렉트

리버스 프록시 헤더

proxy_set_header Host $host;                    # 원본 호스트명 전달
proxy_set_header X-Real-IP $remote_addr;        # 클라이언트 실제 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 프록시 체인
proxy_set_header X-Forwarded-Proto $scheme;     # 원본 프로토콜 (https)

5단계: 최종 테스트 및 검증

5.1 HTTP → HTTPS 리다이렉트 테스트

curl -I http://api.yourdomain.com

5.2 HTTPS API 엔드포인트 테스트

# 기본 엔드포인트
curl https://api.yourdomain.com/
curl https://api.yourdomain.com/hello
curl https://apo.yourdomain.com/sendMessage

# POST API 테스트
curl -X POST https://api.yourdomain.com/sendMessage \
  -H "Content-Type: application/json" \
  -d '{"message": "이력을 알려줘"}'
- 2018년 ~ 2019년: 이력
- 2020년 ~ 2025년: 이력

5.3 SSL 인증서 확인

# 브라우저에서 확인
# https://api.yourdomain.com 접속 시 자물쇠 아이콘 확인

# 명령어로 확인
openssl s_client -connect api.yourdomain.com:443 -servername api.yourdomain.com

6. 현재 포트포워딩 흐름도

1️⃣ 사용자가 http://api.yourdomain.com 입력
    ↓
2️⃣ nginx:80 포트에서 요청 수신
    ↓
3️⃣ nginx 설정 적용:
    server {
        listen 80;
        server_name api.yourdomain.com;
        return 301 https://$server_name$request_uri;
    }
    ↓
4️⃣ 301 리다이렉트 응답 전송
    Location: https://api.yourdomain.com/
    ↓
5️⃣ 브라우저가 자동으로 HTTPS 요청
    ↓
6️⃣ nginx:443 포트에서 HTTPS 처리
    ↓
7️⃣ Flask 앱으로 프록시 전달 (localhost:5001)

1. 인터넷 요청 → AWS Security Group

  • 사용자가 인터넷을 통해 웹사이트에 접속 요청
  • AWS Security Group이 방화벽 역할을 하여 포트 80, 443만 허용

2. nginx:80 (포트 80)

  • 첫 번째 nginx가 HTTP 요청을 받음
  • 하지만 보안을 위해 HTTPS로 리다이렉트 (301 응답)

3. HTTP → HTTPS 리다이렉트

  • https://...로 다시 접속하라고 안내
  • 보안 연결을 강제함

4. nginx:443 (포트 443)

  • 두 번째 nginx가 HTTPS 요청을 처리
  • SSL 인증서를 사용해 암호화된 통신

5. 프록시 전달 → Flask 앱

  • nginx가 리버스 프록시 역할
  • 실제 애플리케이션(Flask, 포트 5001)으로 요청 전달
  • proxy_pass 설정을 통해 내부 포트로 포워딩

6. API 응답

  • Flask 앱이 /, /hello, /sendMessage 등의 API 처리
  • 응답을 다시 nginx를 통해 사용자에게 전달

7. 이해를 돕기 위한 포트 번호

  • 웹서비스 포트
포트프로토콜서비스설명보안
80HTTP웹 서버일반 웹사이트, 암호화 없음⚠️ 평문
443HTTPS보안 웹 서버SSL/TLS 암호화 웹사이트🔒 암호화
8080HTTP웹 프록시/대체개발용, 프록시 서버⚠️ 평문
8443HTTPS보안 웹 대체대체 HTTPS 포트🔒 암호화
3000HTTP개발 서버React, Node.js 개발 서버⚠️ 개발용
5000HTTPFlask 기본Flask 개발 서버 기본값⚠️ 개발용
  • 원격접속 포트
포트프로토콜서비스설명플랫폼
22SSHSecure Shell리눅스/유닉스 원격 접속🐧 Linux/Mac
3389RDPRemote DesktopWindows 원격 데스크톱🪟 Windows
5900VNCVirtual Network Computing크로스플랫폼 원격 데스크톱🌐 All
23TelnetTelnet구식 원격 접속 (비보안)⚠️ 사용 금지
  • 데이터베이스 포트
포트데이터베이스설명특징
3306MySQL/MariaDB관계형 데이터베이스웹 개발 표준
5432PostgreSQL고급 관계형 DB기업용, 고성능
27017MongoDBNoSQL 문서 DBJSON 기반
6379Redis인메모리 캐시세션, 캐싱용
1433SQL ServerMicrosoft DBWindows 환경
1521Oracle엔터프라이즈 DB대기업용
  • 메일 서비스 포트
포트프로토콜용도보안설명
25SMTP메일 발송⚠️ 평문서버간 메일 전송
587SMTP메일 발송🔒 TLS클라이언트 메일 발송
465SMTPS보안 메일 발송🔒 SSL구식 보안 SMTP
110POP3메일 수신⚠️ 평문메일 다운로드
995POP3S보안 메일 수신🔒 SSL보안 메일 다운로드
143IMAP메일 동기화⚠️ 평문서버 메일 관리
993IMAPS보안 메일 동기화🔒 SSL보안 서버 메일 관리
  • 게임 & 미디어 포트
포트서비스설명
25565Minecraft마인크래프트 서버
27015SteamSteam 게임 서버
1935RTMP실시간 미디어 스트리밍
554RTSP실시간 스트리밍 프로토콜
  • 시스템 & 네트워크 포트
포트프로토콜서비스설명
53DNS도메인 네임 서버도메인 → IP 변환
67/68DHCP동적 IP 할당자동 IP 설정
21FTP파일 전송파일 업로드/다운로드
990FTPS보안 파일 전송SSL 암호화 FTP
161SNMP네트워크 관리장비 모니터링
  • 보안 주의 있는 포트
포트위험도이유대응방안
23🔴 높음Telnet 평문 전송SSH(22) 사용
21🟡 중간FTP 평문 전송SFTP/FTPS 사용
135-139🔴 높음Windows 공유방화벽 차단
445🔴 높음SMB 취약점외부 접근 차단

트러블슈팅 가이드

자주 발생하는 문제들

1. DNS 전파 지연

증상: 도메인으로 접속이 안됨
해결:

# DNS 전파 상태 확인
dig @8.8.8.8 A api.yourdomain.com
dig @ns1.gabia.co.kr A api.yourdomain.com

# 임시로 hosts 파일 수정 (테스트용)
echo "YOUR_ELASTIC_IP api.yourdomain.com" | sudo tee -a /etc/hosts

# 진짜 제대로 배포 되었는지 확인 필요
# 해당 문제는 도메인에 임시로 걸어둔 사설 IP주소 문제로 추청되어 현재 수정 중에 있음

2. SSL 인증서 문제

증상: HTTPS 접속 시 보안 경고
해결:

# 인증서 상태 확인
sudo openssl x509 -in /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem -text -noout

# 인증서 갱신
sudo certbot renew --dry-run

3. 502 Bad Gateway 오류

증상: nginx는 동작하지만 Flask 앱 연결 안됨
해결:

# Flask 서비스 상태 확인
sudo systemctl status flask-app
sudo journalctl -u flask-app -f

# Flask 앱 직접 테스트
curl http://localhost:5001

# 서비스 재시작
sudo systemctl restart flask-app

유용한 모니터링 명령어

# 전체 서비스 상태 확인
sudo systemctl status nginx flask-app

# 포트 사용 현황
sudo netstat -tlnp | grep -E ":80|:443|:5001"

# 실시간 로그 확인
sudo tail -f /var/log/nginx/access.log
sudo journalctl -u flask-app -f

# SSL 인증서 만료일 확인
sudo openssl x509 -in /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem -noout -dates

profile
humble

0개의 댓글