# Caddy 설정 — 웹서버 + 리버스 프록시 + 자동 HTTPS # 학습 포인트: 운영에서 사용자는 Caddy(80/443)만 만나요. # - 정적 파일(React 빌드 결과)은 Caddy가 직접 서빙 # - /api/* 요청은 백엔드 컨테이너(backend:8080)로 넘김 — 개발 때 vite 프록시와 같은 역할 # - 도메인이 연결되면 HTTPS 인증서를 자동으로 받아요 (Let's Encrypt) # ── 공통 보안 응답 헤더 (snippet) ── # 학습 포인트: 브라우저는 서버가 주는 헤더를 보고 "이 사이트를 어떻게 다룰지" 정한다. # 아래 헤더 몇 줄이 흔한 공격을 브라우저 단에서 막아 준다. 학생 세션쿠키·개인정보를 # 다루는 사이트라 특히 중요하다. (import security 로 각 사이트 블록에서 끌어 쓴다) (security) { header { # HTTPS만 쓰라고 브라우저에 각인 (1년) — 평문 접속·다운그레이드 공격 차단 Strict-Transport-Security "max-age=31536000; includeSubDomains" # 다른 사이트가 우리 화면을 iframe에 넣는 것 금지 → 클릭재킹 방어 X-Frame-Options "DENY" # 브라우저가 파일 종류를 멋대로 추측(MIME 스니핑)하지 못하게 X-Content-Type-Options "nosniff" # 다른 사이트로 이동할 때 우리 주소(경로)를 흘리지 않음 Referrer-Policy "no-referrer" # 서버 종류를 굳이 알려주지 않음 -Server } } # 도메인 접속 (DNS 연결 후 자동 HTTPS) edu.awesomedevapp.com { import security encode gzip handle /api/* { reverse_proxy backend:8080 } handle { root * /srv try_files {path} /index.html # 새로고침해도 React 라우터가 동작하게 하는 설정 file_server } } # 학습 포인트: 예전엔 여기에 `:80 { }`(모든 HTTP를 평문으로 서빙) 블록이 있었다. # 그런데 그게 Caddy의 자동 HTTP→HTTPS 리다이렉트를 "가로채" 평문 접속을 열어 뒀다. # 이 블록을 지우면 Caddy가 edu.awesomedevapp.com의 80포트를 자동으로 443으로 돌려보낸다 # → 평문으로 로그인 정보가 오갈 표면 자체가 사라진다. (DNS가 붙었으니 IP 평문 접속은 불필요.)