리눅스·서버 학습

nginx 리버스 프록시와 HTTPS 설정 따라하기

백엔드 앱 앞에 nginx를 두고 Let's Encrypt 인증서를 적용하는 과정을 정리했습니다.

리버스 프록시는 외부 요청을 받아 내부 애플리케이션에 전달합니다. 앱을 8080 같은 내부 포트에만 열어두고 nginx가 TLS, 압축, 정적 파일, 요청 제한을 맡습니다.

기본 설정

server {
    listen 80;
    server_name example.com;

    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;
    }
}

이 헤더를 빠뜨리면 앱이 실제 사용자 IP나 HTTPS 여부를 알 수 없어 로그가 틀리거나 리다이렉트가 잘못됩니다.

적용 전에 항상 문법 검사

sudo nginx -t && sudo systemctl reload nginx

restart 대신 reload를 쓰면 처리 중인 연결을 끊지 않습니다.

HTTPS 인증서 적용

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
sudo certbot renew --dry-run

도메인이 서버를 가리키고 80번 포트가 열려 있어야 발급됩니다. 갱신이 자동으로 되는지 마지막 명령으로 확인하세요.

자주 만나는 오류

  • 502 Bad Gateway: 앱이 꺼져 있거나 포트가 다릅니다.
  • 504 Gateway Timeout: 앱 응답이 proxy_read_timeout보다 오래 걸립니다.
  • 413 Request Entity Too Large: client_max_body_size를 늘려야 합니다.
  • WebSocket 끊김: Upgrade, Connection 헤더 전달이 필요합니다.

앱 포트를 외부에 노출하지 않기

앱이 0.0.0.0:8080으로 열려 있으면 nginx의 보안 설정을 우회해 직접 접속할 수 있습니다. 127.0.0.1에 바인딩하거나 방화벽으로 막으세요. Docker는 -p 127.0.0.1:8080:8080처럼 지정합니다.

로그인 무차별 대입 줄이기

limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;

location = /login {
    limit_req zone=login burst=10 nodelay;
    limit_req_status 429;
    proxy_pass http://127.0.0.1:8080;
}

nginx 설정 생성기