Nginx SSL/TLS 발급과 자동 갱신
Ubuntu 홈서버 구축기· 9 / 15
- 1 — 홈서버 구축 과정 정리
- 2 — 운영체제 선택과 설치
- 3 — Rufus로 Ubuntu USB 부팅 디스크 만들기
- 4 — Windows 디스크 파티셔닝과 Ubuntu 설치
- 5 — SSH 원격 접속 설정
- 6 — 방화벽 설정
- 7 — Cloudflare DNS 설정
- 8 — Nginx 설치와 리버스 프록시
- 9 — Nginx SSL/TLS 발급과 자동 갱신
- 10 — MySQL 설치와 설정
- 11 — Node.js 설치와 백엔드 애플리케이션 실행
- 12 — DHCP Reservation으로 내부 IP 고정
- 13 — 포트 포워딩
- 14 — 동적 DNS(DDNS) 개념과 테스트
- 15 — ddclient으로 동적 DNS(DDNS) 자동화
이번 문서에서는 앞서 설치한 Nginx에 SSL/TLS 설정을 추가한다. 블로그 내에 이미 SSL/TLS 설정과 관련한 기록이 있지만, 이번에는 일부 설정을 다르게 구성한 부분이 있어 다시 정리해본다.
인증서 발급 준비
SSL/TLS 인증서 발급 시 도메인 소유권 인증을 받아야 하는데, DNS-01 챌린지 방식으로 처리할 수 있다. Cloudflare를 이용한 DNS 인증을 위해서는 Cloudflare의 API 토큰을 서버에 등록하는 과정이 필요하다.
-
Cloudflare API 토큰 발급
API 토큰 발급은 아래 경로로 접근할 수 있다.
Cloudflare 홈 > [내 프로필] > [API 토큰]


토큰 발급 직후에 보여주는 토큰값은 다시 확인할 수 없으므로 미리 복사해두어야 한다.
-
서버 환경변수로 Cloudflare API 토큰 설정
vim ~/.keys/cloudflare.inidns_cloudflare_api_token = ExAMpLE2Oeya1nwmp559q3rk57smz0O3w5z글로벌 API 키를 사용하는 것이 아닌 특정 용도의 API 토큰을 발행해서 사용했을 경우, dns_cloudflare_api_key 및 dns_cloudflare_email이 아닌 dns_cloudflare_api_token으로 변수명을 설정해야 한다.
Let’s Encrypt - Certbot 설치 및 설정
Cloudflare API 토큰을 준비했다면, 인증서 발급 도구인 certbot과 Cloudflare DNS 플러그인을 설치한다.
-
패키지 및 플러그인 설치
sudo apt install certbot python3-certbot-dns-cloudflare -
SSL/TLS 인증서 발급
sudo certbot certonly --preferred-challenges dns-01 --dns-cloudflare --dns-cloudflare-credentials ~/.keys/cloudflare.ini -d api.domain.com발급된 인증서는 기본적으로
/etc/letsencrypt/live경로에 저장된다. 또한, 인증서가 발급되면 certbot 서비스가 실행되고, 자동으로 인증서를 갱신하기 위해 설정된 타이머에 따라 정기적으로 갱신 작업이 수행된다. -
자동 갱신 타이머 확인
systemctl list-timersNEXT LEFT LAST PASSED UNIT ACTIVATES Tue 2024-10-23 23:55:39 KST 5h 2min Tue 2024-10-23 05:18:05 KST 13h ago certbot.timer certbot.service서버 시스템의 타이머에서 certbot.service가 등록되어 있는 것을 확인해볼 수 있다.
Nginx 설정
마지막으로 Nginx에 SSL/TLS 설정을 추가한다.
-
서버 블록 수정
sudo vim /etc/nginx/sites-available/api.domain.com# api.domain.com 내용 server { listen 443 ssl; # 443 포트에서 SSL 사용 server_name api.domain.com; # 요청 Host 헤더가 해당 도메인일 경우의 서버 블록 # SSL 인증서 및 키 경로 ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; # TLS 프로토콜 버전 ssl_prefer_server_ciphers on; # 서버의 암호화 스위트 우선 사용 location / { proxy_pass http://127.0.0.1:3000; # 로컬 3000 포트(백엔드 앱)로 프록시 proxy_http_version 1.1; # HTTP/1.1 사용(디폴트) # 헤더 정보 추가 proxy_set_header Host $host; # 클라이언트 도메인 주소를 Host 헤더에 설정 proxy_set_header X-Real-IP $remote_addr; # 클라이언트의 IP 주소를 X-Real-IP 헤더에 설정 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 클라이언트의 IP 주소를 X-Forwarded-For 헤더에 설정 proxy_set_header X-Forwarded-Proto $scheme; # 요청 프로토콜을 X-Forwarded-Proto 헤더에 설정 proxy_set_header Upgrade $http_upgrade; # WebSocket 요청일 경우 사용 proxy_set_header Connection 'upgrade'; # WebSocket 요청일 경우 사용 proxy_cache_bypass $http_upgrade; # WebSocket 요청에 대한 캐시 우회 } } server { listen 443 ssl default_server; # 443 포트에서 SSL을 사용 및 기본 서버로 설정 server_name _; # 모든 요청을 처리하는 catch-all 서버 블록 ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem; location / { return 403; # 요청에 대해 403 Forbidden 응답 반환 } }이렇게 서버 블록을 나누어 두면, api.domain.com로 들어온 요청에 대해서만 프록시를 수행하고, 그외 모든 요청에 대해서는 403 Forbidden을 반환함으로써 보안을 강화할 수 있다.
보통 80번 포트로 들어온 요청은 443 포트로 리디렉션하지만, 해당 프록시는 일반 사용자가 직접 요청할 일이 없는 백엔드 서버이므로 보안을 위해 리디렉션을 제외했다.
-
서버 블록을 심볼릭 링크로 추가
생성한 서버 블록 설정 파일을 /etc/nginx/sites-enabled 위치에 심볼릭 링크로 추가해 서버 블록을 활성화한다.
sudo ln -s /etc/nginx/sites-available/api.domain.com /etc/nginx/sites-enabled이미 설정 파일이 존재할 경우, 삭제 후 다시 추가한다.
sudo rm /etc/nginx/sites-enabled/api.domain.com -
Nginx 재시작
설정이 모두 완료되면, Nginx를 재시작해 SSL/TLS 적용을 마친다.
sudo systemctl restart nginx
참고 자료
- [1] Let's encrypt SSL 인증서 자동 갱신하기 (Cloudflare) - j911↗