
애플리케이션 앞에 Nginx 를 두는 이유는 TLS 를 한곳에서 끝내고, 보안 헤더를 한곳에서 붙이고, 백엔드는 그 뒤에서 단순하게 두기 위해서입니다. 그런데 '일단 돌아가게' 만든 설정은 보통 이 셋 중 하나가 빠져 있습니다. 아래는 가장 흔한 구성(Let's Encrypt + 백엔드 127.0.0.1:8080)을 기준으로 한 최소한의 올바른 설정입니다.

1. 인증서 — certbot 과 자동 갱신
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
systemctl list-timers | grep certbot
certbot 이 server 블록에 인증서 경로를 넣어 줍니다. 갱신 타이머가 켜져 있는지(certbot.timer) 확인하고, sudo certbot renew --dry-run 으로 갱신이 되는지도 한 번 봐 둡니다.
2. HTTP 는 HTTPS 로 넘긴다
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
3. TLS — 버전과 암호 모음
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
TLS 1.0·1.1 은 끕니다. 암호 모음은 Nginx·OpenSSL 기본값이 충분히 현대적이라 억지로 길게 적지 않아도 됩니다(오래된 가이드를 복사하면 오히려 약한 모음이 섞입니다).
4. 보안 헤더 다섯 줄
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header Content-Security-Policy "default-src 'self'" always;

CSP 는 가장 효과가 크지만 가장 깨지기 쉬운 헤더입니다. 외부 스크립트·폰트·이미지를 쓰는 사이트라면 처음엔 Content-Security-Policy-Report-Only 로 두고 브라우저 콘솔의 위반 보고를 본 뒤 허용 목록을 채워 넣는 순서가 안전합니다. always 를 붙여야 4xx·5xx 응답에도 헤더가 나갑니다. 그리고 add_header 는 하위 블록에서 하나라도 선언하면 상위 것이 모두 사라지는 성질이 있어, location 블록에 add_header 를 쓸 때는 다섯 줄을 다시 적어야 합니다.
5. 프록시 — 백엔드에 실제 정보를 넘긴다
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
이 네 헤더가 없으면 백엔드 로그에 모든 요청이 127.0.0.1 로 찍히고, 앱이 만든 리다이렉트 주소가 http:// 로 나가는 문제가 생깁니다. 백엔드는 이 헤더를 Nginx 에서 온 것만 믿도록 설정해야 합니다(프레임워크의 trusted proxy 설정).
적용 뒤 확인

curl -I https://example.com 으로 헤더를 직접 보는 것이 가장 빠릅니다. 설정은 한 번 적어 두면 바뀔 일이 거의 없으니, 템플릿으로 만들어 두고 새 서비스마다 복사해 쓰면 됩니다.
댓글