예전에는 HTTPS를 붙인다고 하면 꽤 부담스러운 작업처럼 느껴졌다.
인증서 발급, CSR 생성, 인증서 파일 적용, 웹서버 설정, 갱신 관리까지 손이 많이 갔고, 작은 서비스 하나 올리는데도 진입장벽이 있었다.
그런데 Nginx + Let’s Encrypt + Certbot 조합으로 구성해보니 생각보다 훨씬 간단했다.
특히 개인 서버나 소규모 서비스에서는 “도메인 연결 + Nginx reverse proxy + certbot 실행” 정도만으로도 HTTPS 서비스를 빠르게 올릴 수 있다.
이번 글에서는 Nginx를 이용해 SSL(HTTPS)을 붙이는 전체 흐름을 실제 적용 순서대로 정리한다.
1. 구성 목표
이번에 목표로 한 형태는 다음과 같다.
- 도메인: example.com (본인 도메인으로 변경)
- 웹서버: nginx
- 내부 서비스: 웹 애플리케이션 (예: 127.0.0.1:3000)
- 외부 접속: https://example.com
- 방식: Nginx가 80/443 포트를 받고, 내부 서비스로 reverse proxy
구조는 아래와 같다.
사용자 브라우저
↓
<https://example.com>
↓
Nginx (80/443)
↓
내부 서비스 (예: 127.0.0.1:3000)
이 구조의 장점은 명확하다.
- 외부에는 80/443만 공개
- 내부 서비스는 로컬 포트로만 유지 가능
- SSL 처리는 Nginx에서 일괄 담당
- 서비스가 늘어나도 도메인만 추가해 확장 가능
2. 먼저 도메인 연결부터
HTTPS를 붙이기 전에 가장 먼저 해야 할 일은 도메인이 서버를 정확히 가리키도록 DNS를 설정하는 것이다.
예를 들어 example.com를 쓰려면 DNS에서 A 레코드를 등록한다.
- 호스트: @ 또는 서브도메인(예: app)
- 타입: A
- 값: 서버 공인 IP
TTL은 처음에는 짧게 두면 변경 반영 여부를 확인하기 편하다.
3. Nginx reverse proxy 먼저 구성 (HTTP)
SSL을 붙이기 전에 먼저 HTTP로 서비스가 정상 연결되는지 확인하는 것이 좋다.
처음부터 HTTPS까지 한 번에 보려고 하면 DNS 문제인지, Nginx 문제인지, 애플리케이션 문제인지 구분이 어렵다.
아래는 가장 단순한 reverse proxy 예시다.
server {
listen 80;
listen [::]:80;
server_name example.com;
location / {
proxy_pass <http://127.0.0.1:3000>;
proxy_http_version 1.1;
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;
# WebSocket 등 업그레이드가 필요한 서비스라면 아래 헤더가 필요할 수 있음
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
}
설정 후에는 아래처럼 테스트한다.
sudo nginx -t
sudo systemctl reload nginx
그리고 브라우저에서 접속해본다.
<http://example.com>
여기서 서비스가 정상적으로 뜨면, 그 다음이 HTTPS 단계다.
. 중간에 만난 문제: 정적 파일 404
처음에는 reverse proxy만 걸면 끝날 줄 알았는데, 실제로는 하위 리소스(정적 파일)들이 404가 나는 문제가 있었다.
예를 들면 아래 같은 요청이 계속 실패했다.
<http://example.com/static/loader.js>
원인을 확인해보니 Nginx 설정에 남아 있던 정적 웹서버 설정(root 등)이 요청을 가로채고 있었다.
예를 들어 server 블록에 아래 설정이 남아 있으면:
root /var/www/html;
Nginx는 /static/loader.js 요청을 upstream으로 넘기지 않고 로컬 파일 경로에서 먼저 찾는다.
- 기대했던 동작: /static/loader.js → upstream(내부 서비스)로 전달
- 실제 동작: /static/loader.js → Nginx 로컬 경로에서 파일 검색 → 404
그래서 reverse proxy 전용 server 블록에서는 root, index, try_files 같은 정적 웹서버 설정을 빼고,
요청을 전부 proxy_pass로 넘기는 구조가 더 깔끔했다.
5. Certbot으로 HTTPS 적용
HTTP가 정상이라면 이제 SSL 인증서를 붙이면 된다.
지금은 Certbot이 발급과 Nginx 설정 변경까지 대부분을 자동화해준다.
(1) 설치 (Ubuntu 예시)
배포판/환경에 따라 설치 방식이 다를 수 있으니, 공식 문서를 함께 확인하는 것을 권장한다.
sudo apt update
sudo apt install -y snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
(2) 인증서 발급 및 Nginx 설정 자동 반영
sudo certbot --nginx -d example.com
실행 중 이메일, 약관 동의, HTTP→HTTPS 리다이렉트 여부 등을 묻는다.
리다이렉트를 선택하면 Certbot이 Nginx 설정까지 자동으로 수정해준다.
6. 최종 구성 형태 (HTTPS + 리다이렉트)
최종적으로는 아래와 같은 형태가 된다.
인증서 경로는 Certbot이 발급한 도메인 기준으로 자동 생성되며, 환경에 따라 다를 수 있다.
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass <http://127.0.0.1:3000>;
proxy_http_version 1.1;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
}
이제 사용자는 https://example.com로 접속하고,
Nginx가 SSL을 종료한 뒤 내부 서비스로 안전하게 전달한다.
7. 자동 갱신 확인
SSL 구축이 쉬워진 가장 큰 이유는 갱신 관리까지 자동화가 가능하다는 점이다.
아래처럼 dry-run으로 갱신 테스트를 해볼 수 있다.
sudo certbot renew --dry-run
이게 성공하면 운영 중 인증서 만료로 인한 사고 가능성이 크게 줄어든다.
8. 여러 서비스로 확장하기
이 구조는 한 서비스에서 끝나지 않고, 서비스가 늘어나도 쉽게 확장할 수 있다.
- app.example.com → 웹 서비스
- api.example.com → API 서버
- admin.example.com → 관리자 페이지
즉 Nginx를 진입점으로 두고, 뒤쪽 서비스들을 reverse proxy로 나누면 된다.
소규모 환경에서는 호스트에 Nginx를 설치해 SSL과 라우팅을 담당하게 하는 방식이 특히 실용적이다.
마무리
정리하면 흐름은 단순하다.
- 도메인을 서버 IP에 연결
- Nginx reverse proxy로 내부 서비스 연결
- HTTP로 정상 동작 확인
- Certbot으로 SSL 적용
- HTTPS 리다이렉트 및 자동 갱신 확인
예전에는 SSL이 어렵게 느껴졌지만,
지금은 오히려 기본 인프라 작업 중 가장 빠르게 끝나는 편에 가까워졌다.