HTTPS 적용하기 위한 Certbot 알아보기
SSL 인증서 발급받고 Nginx 설정은 어떻게 하는지 학습정리
nginx
certbot 이 하는 일
sudo certbot --nginx -d api.limsr12.com
위와 같이 certbot 을 실행하면 두가지 일을 한다.
1. 인증서 발급 (Let's Encrypt와 통신)
Certbot → Let's Encrypt 서버: "api.limsr12.com 인증서 주세요"
Let's Encrypt → Certbot: "이 도메인이 정말 당신 것인지 증명하세요"
Certbot → Nginx의 80포트를 이용해 검증 파일 배치
Let's Encrypt → http://api.limsr12.com/.well-known/acme-challenge/xxxx 로 접속해서 검증
Let's Encrypt → Certbot: "확인됨, 인증서 발급합니다"
발급된 인증서는 호스트의 /etc/letsencrypt/ 에 저장된다.
/etc/letsencrypt/
├── live/
│ └── api.limsr12.com/
│ ├── fullchain.pem ← 인증서 (Nginx의 ssl_certificate)
│ ├── privkey.pem ← 개인키 (Nginx의 ssl_certificate_key)
│ ├── cert.pem ← 서버 인증서만
│ └── chain.pem ← 중간 인증서만
├── renewal/
│ └── api.limsr12.com.conf ← 갱신 설정 (어떤 도메인, 어떤 방식으로 발급했는지)
└── archive/
└── api.limsr12.com/ ← 인증서 이력 (live/는 여기로의 심볼릭 링크)
2. nginx 설정 자동 수정 (--nginx 플러그인)
Certbot은 인증서 발급이 완료되면 직접 /etc/nginx/sites-available/api.limsr12.com 파일을 열어서 SSL 관련 설정을 자동으로 추가한다.
# 이 줄들은 전부 Certbot이 자동 추가한 것
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/api.limsr12.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.limsr12.com/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
컨테이너 환경에서는 다르다!
Certbot 이 Nginx 설정을 수정하지 않는다
컨테이너 환경에서는 --nginx 플러그인 대신 --webroot 방식을 사용한다.
Certbot 컨테이너 안에는 Nginx가 없기 때문에 설정 파일을 수정할 수가 없다.
그래서 Nginx 설정은 직접 미리 작성해두고, Certbot은 인증서 발급/갱신만 담당한다!
docker-compose.yml 이 정의하는 볼륨 공유 방식
[프로젝트 디렉토리]
./certbot/conf/ ←──── 볼륨 ────→ Certbot 컨테이너: /etc/letsencrypt
│ (여기에 인증서를 발급/저장)
│
└──────────── 볼륨 ────→ Nginx 컨테이너: /etc/letsencrypt (읽기전용)
(여기서 인증서를 읽어서 사용)
./certbot/www/ ←──── 볼륨 ────→ Certbot 컨테이너: /var/www/certbot
│ (검증 파일을 여기에 생성)
│
└──────────── 볼륨 ────→ Nginx 컨테이너: /var/www/certbot (읽기전용)
(검증 요청을 이 경로에서 응답)
실제 docker-compose.yml 을 보면 이런 식이다.
nginx:
volumes:
- ./certbot/conf:/etc/letsencrypt:ro # 인증서 읽기 (읽기전용)
- ./certbot/www:/var/www/certbot:ro # 검증 파일 읽기 (읽기전용)
certbot:
volumes:
- ./certbot/conf:/etc/letsencrypt # 인증서 저장 (읽기+쓰기)
- ./certbot/www:/var/www/certbot # 검증 파일 생성 (읽기+쓰기)
같은 호스트 디렉토리를 두 컨테이너가 공유하기 때문에, Certbot이 인증서를 저장하면 Nginx가 바로 볼 수 있다!
인증서 발급 시나리오 (시간순)
[Step 1] Nginx 컨테이너가 HTTP(80)로 먼저 기동
(아직 인증서 없으므로 HTTPS 서버 블록 없는 임시 설정)
[Step 2] Certbot 컨테이너 실행
certbot certonly --webroot --webroot-path /var/www/certbot -d api.limsr12.com
[Step 3] Let's Encrypt가 검증 요청
→ http://api.limsr12.com/.well-known/acme-challenge/xxxx
→ Nginx 컨테이너가 요청 수신
→ /var/www/certbot/.well-known/acme-challenge/xxxx 파일 응답
(이 파일은 Certbot이 공유 볼륨에 생성해둔 것)
[Step 4] 검증 성공 → Certbot이 인증서를 /etc/letsencrypt/live/에 저장
→ 실제로는 호스트의 ./certbot/conf/live/에 저장됨
→ Nginx 컨테이너도 같은 볼륨을 마운트하고 있으므로 접근 가능
[Step 5] Nginx 설정을 HTTPS 포함 버전으로 교체 → Nginx 재시작
인증서 갱신 시나리오
[12시간마다] Certbot 컨테이너가 certbot renew 실행
→ 만료 30일 전이면 자동 갱신
→ 새 인증서가 같은 볼륨 경로에 덮어써짐
[갱신 후] Nginx가 새 인증서를 반영하려면 reload 필요
→ crontab이나 스크립트로 자동화:
docker compose exec nginx nginx -s reload
# 로컬과 컨테이너 환경 비교
| 단계 | 로컬(certbot --nginx) | 컨테이너(certbot --webroot) |
| ------------------- | -------------------------- | ----------------------------- |
| 인증서 발급 | Certbot 이 직접 수행 | Certbot 컨테이너가 수행 |
| 검증 방식 | Nginx 플러그인이 자동 처리 | 공유 볼륨의 파일로 검증 |
| 인증서 저장 | /etc/letsencrypt/ (호스트) | ./certbot/conf/ (프로젝트 내) |
| Nginx 설정 수정 | Certbot 이 자동으로 해줌 | 직접 미리 작성해야 함 |
| Nginx가 인증서 접근 | 같은 호스트 파일 시스템 | 볼륨 마운트로 접근 |
| 갱신 후 반영 | Certbot 이 자동 reload | 별도로 nginx -s reload 필요 |