
Nginx는 웹사이트 콘텐츠를 사용자에게 전달하는 역할을 하는 웹 서버 소프트웨어입니다.
리버스 프록시 기능을 통해 여러 개의 서버를 앞단에서 관리하며, 사용자의 요청을 적절한 서버로 분산시켜 부하를 줄일 수 있으며,
로드 밸런싱을 통해 여러 서버에 트래픽을 균등하게 분배하여 특정 서버에 과부하가 걸리는 것을 방지합니다
이 리버스 프록시의 기능을 통해
일반적으로 웹 서버는 80번(HTTP) 또는 443번(HTTPS) 포트를 사용합니다.
하지만 웹 서버 뒤에서 동작하는 애플리케이션(예: Node.js, Django, Spring Boot 등)은 3000번, 5000번, 8080번과 같은 고유한 포트를 사용하므로
이 때 프론트엔드와의 작업을 위하여 사용자가 웹사이트의 표준 포트(80/443)로 접속하면, Nginx가 이 요청을 받아서 실제 애플리케이션이 실행되고 있는 내부 포트로 연결해주는 역할을 합니다.
보안 강화: 애플리케이션의 실제 포트를 외부에 노출하지 않아 보안을 높일 수 있습니다.
유연성: 하나의 서버에서 여러 개의 웹 애플리케이션을 운영하면서 모두 표준 포트(80/443)를 통해 서비스할 수 있습니다.
중앙 관리: Nginx를 통해 모든 트래픽을 한 곳에서 관리하고, 로드 밸런싱이나 캐싱 등의 고급 기능을 적용할 수 있습니다.
무료 SSL/TLS 인증서를 자동으로 발급하고 갱신해주는 도구입니다.
이 인증서는 웹사이트와 사용자 간의 데이터 통신을 암호화하여 보안을 강화하는 데 사용되는데
자동 인증서 발급과 갱신을 해줍니다. 도메인 소유권을 자동으로 확인하고, Let's Encrypt로부터 SSL/TLS 인증서를 발급받습니다. 인증서 유효 기간(보통 90일)이 만료되기 전에 자동으로 갱신합니다.
Nginx와 같은 웹 서버의 설정을 자동으로 변경하여 HTTPS를 적용합니다.
웹 서버 설정 자동화를 실행해줍니다.
이 때 Nginx의 conf에 들어가는 내용에서
443에 대한 listen을 처리할 때 nginx는 certbot에서 발급한 인증서를 기반으로 작동해야합니다.
이를 기반으로 docker를 작성하기 위하여 다음과 같은 설정이 필요합니다
우선은 Nginx와 Certbot을 설정하여 docker 환경을 구축합니다.
이 때 중요한 것은 Nginx와 Certbot이 동일한 경로를 마운트해야한다는 것입니다.
nginx:
image: nginx:1.27.4
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/certbot
depends_on:
- app-blue
- app-green
networks:
- my-network
restart: always
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
- my-network
위의 코드를 보면
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/certbot
으로 설정한 것을 보면 둘이 동일한 경로를 공유한다는 것을 알 수 있습니다
이 때 마운트를 위한 경로를 미리 만들어두시기를 적극 추천드립니다..
Nginx의 conf 중 default.conf든 nginx.conf든 상관은 없습니다만 각각의 차이는 default의 경우에는 server 블록만 포함해야하고, nginx.conf는 event 포함하여 http 블록 작성해주시면 됩니다
중요한 것은 우선은 http 기반 80 포트에 대해서만 매핑을 해주지만,
http에 대하여 리다이렉트 하고 다음 설정으로 certbot과 동일한 경로를 마운트함을 표시해야합니다
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
이 Nginx 설정은 Certbot이 도메인 소유권을 확인하기 위해 사용하는 특정 경로에 대한 요청을 처리하도록 지시하는 것으로, /.well-known/acme-challenge/로 시작하는 모든 HTTP 요청을 가로채는 역할을 합니다.
이 경로는 Let's Encrypt의 ACME(Automatic Certificate Management Environment) 프로토콜에서 도메인 소유권을 검증하는 데 표준적으로 사용됩니다.
root /var/www/letsencrypt;
이 경로로 들어온 요청에 대해 Nginx가 index 파일을 찾거나 정적 파일을 제공할 루트 디렉터리를 /var/www/letsencrypt로 지정함으로써 Certbot의 webroot가 됩니다
Certbot은 SSL/TLS 인증서를 발급받기 전에 사용자가 실제로 해당 도메인의 소유자인지 확인해야 하는데 Certbot은 서버에 특정 파일을 생성하고 Let's Encrypt는 이 파일을 HTTP를 통해 요청하여 소유권을 확인합니다.
(이 설정은 Certbot의 certonly --webroot 모드에서 사용되어 --webroot 옵션 사용됨)
Certbot이 /var/www/letsencrypt/.well-known/acme-challenge/ 경로에 챌린지 파일을 만듭니다.
Let's Encrypt 서버는 http://yourdomain.com/.well-known/acme-challenge/YOUR_FILE과 같은 URL로 이 파일을 요청합니다.
Nginx는 위 설정을 통해 이 요청을 받아 root로 지정된 /var/www/letsencrypt 디렉토리에서 해당 챌린지 파일을 찾아서 Let's Encrypt에 응답합니다.
Certbot은 Let's Encrypt로부터 검증이 성공했다는 신호를 받고 인증서를 발급받습니다.
결론적으로, 이 설정은 Let's Encrypt의 도메인 검증 요청을 안전하고 정확하게 처리하기 위해 Nginx에 필요한 경로를 명시하는 것입니다.
이제 docker로 최초의 https SSL 인증서 발급을 위해선 일회성의 컨테이너를 실행해야합니다
docker compose run --rm \
-v ./data/certbot/conf:/etc/letsencrypt \
-v ./data/certbot/conf:/etc/letsencrypt \
certbot/certbot certonly \
--webroot \
--webroot-path=/var/www/certbot \
--email EMAIL@eamil.com \
--agree-tos \
--no-eff-email \
-d 도메인주소.com \
-d www.도메인주소.com
docker에서 --rm 옵션은 일회성이라는 뜻입니다.
한 번 사용되고 말 것이라면 해당 옵션을 붙입니다
이것이 성공적으로 실행된다면 이제 Successfully SSL 인증서 발급에 대한 것이 뜰 것입니다
이미 위에서 설정했던 - ./certbot/www:/var/www/certbot 덕에 지금 실행하는 일회성 Certbot에 인증서 발급이 해당 루트에 저장될 것입니다.
이제 다시 Certbot에서 받은 인증서를 기반으로 Nginx가 443 포트에 대하여 처리할 수 있도록 설정해주면 됩니다
server {
listen 443;
server_name example.com www.example.com;
# 인증서 경로
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://upstream_이름으로설정;
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;
}
}
server_name에 도메인을 추가하고 listen 443 ssl을 설정해줘야합니다. (HTTPS를 위하여)
ssl_certificate와 ssl_certificate_key 지시어를 사용하여 인증서와 개인키의 경로를 명시해 주어야 합니다.
docker-compose 기반으로 Certbot이 인증서를 자동으로 갱신해주고
이 과정에서 Nginx와 Certbot 컨테이너는 동일한 볼륨(volume)을 마운트하여 인증서 파일을 공유합니다.