Let's Encrypt 붙이면서 놓칠 뻔한 것 두 가지
도메인을 연결하고 certbot으로 인증서를 받았다. 과정 자체는 금방 끝난다.
dnf install epel-release
dnf install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com --redirect
"Congratulations!" 뜨고 브라우저에 자물쇠도 나왔다. 여기서 끝인 줄 알았는데 확인해 보니 두 가지가 걸렸다.
1. 자동 갱신이 안 돌고 있었다
certbot은 끝날 때 "자동 갱신 작업을 등록했다"고 알려 준다. 그런데 Rocky 9(EPEL 패키지)에서 타이머를 보니 이렇게 나왔다.
systemctl list-timers --all | grep certbot
# - - - - certbot-renew.timer certbot-renew.service
enabled인데 다음 실행 시각이 비어 있다. 켜져는 있는데 시작이 안 된 상태다. 이대로 두면 90일 뒤에 인증서가 그냥 만료된다.
systemctl enable --now certbot-renew.timer
certbot renew --dry-run
이제 다음 실행 시각이 제대로 찍힌다. dry-run도 성공.
2. HSTS 헤더가 두 개
nginx에 HSTS 헤더를 직접 넣었다.
add_header Strict-Transport-Security "max-age=31536000" always;
그런데 curl -I로 보니 헤더가 두 줄이었다.
strict-transport-security: max-age=31536000 ; includeSubDomains
strict-transport-security: max-age=31536000
윗줄은 스프링 시큐리티가 붙인 거다. 시큐리티는 기본으로 HSTS를 켜 두는데, 요청이 https일 때만 헤더를 보낸다. 앞 글에서 프록시 헤더(X-Forwarded-Proto)를 제대로 읽게 해 놨더니 이제 앱이 https 요청이라는 걸 알아보고 헤더를 붙이기 시작한 것이다.
같은 헤더가 두 번 오면 브라우저마다 처리가 애매할 수 있어서 nginx 쪽을 지웠다. 설정을 한 군데에서만 관리하는 게 낫다.
정리
- certbot 끝나고
systemctl list-timers로 갱신 타이머가 진짜 도는지 볼 것 certbot renew --dry-run한 번 돌려 볼 것- HSTS는 앱이나 nginx 중 한 곳에서만 붙일 것
HSTS를 켜면 브라우저가 1년 동안 그 도메인을 https로만 연다. 나중에 인증서를 날려 먹으면 접속 자체가 안 되니까, 갱신 확인은 진짜 중요하다.