노트

Let's Encrypt로 HTTPS 적용

HTTPS with Let's Encrypt

인프라#security#http · 연결된 개념 7개

쉽게 말하면

Let's Encrypt는 사이트의 신분증인 TLS 인증서를 무료로, 자동으로 발급해 주는 기관이에요. 덕분에 누구나 HTTPS를 켤 수 있고, certbot이 발급부터 웹 서버 설치와 갱신까지 대신해 줘요.

비유가 깨지는 곳 이 신분증은 유효 기간이 기본 90일로 짧고 앞으로 더 줄어들 예정이라 자동 갱신이 전제예요. 발급 때 80번 포트로 도메인 소유를 확인하니 방화벽을 열고 DNS가 이 서버를 가리켜야 해요.

Let's Encrypt는 무료로 TLS(Transport Layer Security) 인증서를 자동 발급하는 인증 기관(Certificate Authority, CA)이고, certbot은 그 인증서를 받아 웹 서버에 설치·갱신하는 대표 클라이언트다. 인증서 유효 기간이 짧아(기본 90일, 2027-02부터 64일, 2028-02부터 45일로 단계적으로 줄어듦, 2026 기준) 자동 갱신이 전제다.

nginx에 적용

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
sudo certbot renew --dry-run   # 갱신 시험
  • certbot이 도메인 소유를 확인하려고 80번 포트로 들어오는 요청(HTTP-01 챌린지, HTTP-01 challenge)에 응답한다. 방화벽·보안 그룹(security group)에서 80·443을 열어 둔다. DNS가 이 서버를 가리켜야 한다(DNS와 CNAME)
  • --nginx는 서버 블록에 listen 443 ssl, 인증서 경로 등을 자동으로 추가한다
  • 패키지로 설치하면 대개 systemd 타이머나 cron이 하루 두 번 certbot renew를 실행한다. 직접 cron을 걸 때는 갱신 뒤 웹 서버를 reload하는 훅을 붙인다
0 3 * * * certbot renew --deploy-hook "systemctl reload nginx"

자주 만나는 문제

  • certbot이 타임아웃되면 80번 포트를 다른 프로세스가 잡고 있지 않은지 본다(포트를 쓰는 프로세스 찾아 종료하기)
  • 앱 프로세스가 /etc/letsencrypt/live 아래 키를 못 읽으면, 앱을 root로 돌리지 말고 그룹 권한을 주거나 nginx가 TLS를 끝내고 앱에는 평문으로 넘긴다(nginx로 SPA 배포)

스프링 부트에 직접 붙일 때

내장 Tomcat은 PEM(Privacy-Enhanced Mail) 형식 대신 PKCS#12(Public-Key Cryptography Standards #12) 키스토어(keystore)를 쓰는 경우가 많다.

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name app

server.ssl.key-store에 경로를, 비밀번호는 저장소가 아니라 환경변수나 비밀 저장소에서 읽게 한다(스프링 설정 외부화와 프로파일). 스프링 부트 3.1부터는 PEM을 바로 읽는 SSL(Secure Sockets Layer) 번들을 쓸 수 있고, reload-on-update: true를 켜면 certbot이 파일을 갱신할 때 내장 Tomcat·Netty가 재시작 없이 인증서를 다시 읽는다. 그래도 앱이 여러 개라면 앞단의 nginx나 로드밸런서에서 TLS를 끝내는 구성이 관리하기 쉽다.

HTTPS가 무엇을 지켜 주는지는 HTTP와 HTTPS, HTTPS가 있어야 쓸 수 있는 브라우저 기능(Secure 쿠키 등)은 HTTP 쿠키를 본다.

출처: Let's Encrypt: Decreasing Certificate Lifetimes to 45 Days · Let's Encrypt: Challenge Types (HTTP-01) · Certbot 사용법: Renewal · Certbot: Hooks · Spring Boot: Reloading SSL Bundles

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • XSS

    XSS(Cross-Site Scripting)는 공격자가 넣은 스크립트가 내 사이트의 출처(origin) 권한으로 사용자 브라우저에서 실행되는 공격이다. 같은 출처의 코드로 돌기 때문에 same-origin-policy가 막아 주지 못한다. 그 스크립트는 페이지를 바꾸고, 로그인한 사용자 행세를 하며 요청을 보내고, JS가 읽을 수 있는 데이터(localStorage의 토큰 등)를 빼 갈 수 있다.

  • Spring Boot Actuator

    Spring Boot Actuator는 운영 중인 앱의 상태를 HTTP 엔드포인트로 보여주는 모듈이다. 헬스 체크, 지표, 설정값, 로그 레벨, 등록된 빈 같은 정보를 /actuator/* 아래에 노출한다.

  • loading 경계와 레이아웃 끌어올리기

    Next.js App Router에서 loading.tsx는 같은 세그먼트의 page와 그 아래(하위 layout 포함)를 suspense로 감싸지만, **같은 세그먼트의 layout은 감싸지 않는다**. 그래서 데이터를 기다릴 필요가 없는 공통 UI(탭바, 필터 헤더)를 page에서 layout으로 끌어올리면 스켈레톤에 덮이지 않고 처음부터 실제 모습으로 보인다.

  • Tailscale Serve와 Funnel

    Tailscale은 WireGuard 위에 만든 메시 VPN(mesh Virtual Private Network)으로, 내 기기들을 하나의 사설망(tailnet)으로 묶는다. tailscale serve는 내 기기의 로컬 서비스를 tailnet 안에서만 HTTPS로 열어 주고, tailscale funnel은 같은 서비스를 공개 인터넷에 연다.

  • CSRF

    CSRF(Cross-Site Request Forgery, 사이트 간 요청 위조)는 로그인한 사용자가 악성 사이트를 방문했을 때, 그 사이트가 사용자의 브라우저를 시켜 사용자 모르게 원래 사이트에 요청을 보내게 하는 공격이다. 공격자는 토큰을 훔치지 않는다. 브라우저가 쿠키를 알아서 붙여 준다는 점을 이용한다.

보기 옵션