이 가이드는 Nginx에 SSL 인증서를 설치하는 전체 과정을 안내합니다 — 파일 업로드부터 TLS 설정 최적화, 일반적인 오류 해결까지. GetHTTPS, Certbot 또는 다른 소스에서 받은 인증서에 모두 적용됩니다.
아직 인증서가 없다면, 5분 만에 무료로 발급받으세요.
사전 준비 사항
- Nginx가 설치되어 있고 HTTP(포트 80)로 사이트를 제공 중
- root/sudo 접근 권한
- 인증서 파일 — 두 개가 필요합니다:
fullchain.pem— 인증서 + 중간 체인 (결합됨)privkey.pem— 개인키
어떤 파일이 어떤 것인가요? GetHTTPS는 네 개의 파일을 제공합니다. Nginx에는
fullchain.pem(cert.pem이 아닌)과privkey.pem이 필요합니다.cert.pem만 사용하면 브라우저가 인증서 체인을 검증할 수 없어 “불완전한 체인” 오류가 발생합니다. 인증서 형식 설명 →
1단계: 인증서 파일을 서버에 업로드
파일을 보안 디렉토리에 복사합니다:
# 디렉토리 생성
sudo mkdir -p /etc/ssl/gethttps
# 파일 복사 (로컬 머신에서 서버로)
sudo cp fullchain.pem /etc/ssl/gethttps/
sudo cp privkey.pem /etc/ssl/gethttps/
# 개인키 권한 제한 — root만 읽을 수 있어야 함
sudo chmod 600 /etc/ssl/gethttps/privkey.pem
sudo chmod 644 /etc/ssl/gethttps/fullchain.pem
sudo chown root:root /etc/ssl/gethttps/*
SCP로 전송하는 경우:
scp fullchain.pem privkey.pem user@your-server:/tmp/
# 서버에서:
sudo mv /tmp/fullchain.pem /tmp/privkey.pem /etc/ssl/gethttps/
2단계: HTTPS 서버 블록 설정
사이트의 Nginx 설정 파일을 편집합니다. 파일 위치는 일반적으로:
/etc/nginx/sites-available/yourdomain.conf(Debian/Ubuntu)/etc/nginx/conf.d/yourdomain.conf(CentOS/RHEL)
권장 전체 설정:
# HTTPS 서버 블록
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# ─── 인증서 파일 ───────────────────────
ssl_certificate /etc/ssl/gethttps/fullchain.pem;
ssl_certificate_key /etc/ssl/gethttps/privkey.pem;
# ─── TLS 프로토콜 및 암호화 스위트 ────────────────
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# ─── 세션 캐싱 (성능) ───────────
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# ─── OCSP 스테이플링 (빠른 검증) ─────
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# ─── 보안 헤더 ────────────────────────
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
# ─── 사이트 설정 ───────────────────────────────
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP 리다이렉트 블록
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
각 섹션의 역할:
| 지시문 | 용도 |
|---|---|
listen 443 ssl http2 | 포트 443에서 HTTP/2가 활성화된 HTTPS |
ssl_certificate | 인증서 + 체인 파일 경로 |
ssl_certificate_key | 개인키 경로 |
ssl_protocols | TLS 1.2와 1.3만 허용 (1.0/1.1은 2020년부터 사용 중단) |
ssl_prefer_server_ciphers off | 클라이언트가 최적의 암호화 스위트를 선택하도록 허용 (최신 모범 사례) |
ssl_session_cache | TLS 세션 캐싱 — 재방문자의 재핸드셰이크 방지 |
ssl_session_tickets off | 티켓은 순방향 비밀성을 약화시킬 수 있음 |
ssl_stapling | 서버가 OCSP 응답을 가져옴 — 클라이언트에게 더 빠름 |
Strict-Transport-Security | HSTS — 브라우저가 항상 HTTPS를 사용하도록 기억 |
return 301 | HTTP에서 HTTPS로 영구 리다이렉트 |
3단계: 설정 테스트
리로드 전에 항상 테스트하세요:
sudo nginx -t
예상 출력:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
테스트가 실패하면 Nginx가 오류가 있는 정확한 줄 번호를 알려줍니다. 흔한 실수:
- 파일 경로의 오타 (
ssl_certifcate대신ssl_certificate) - 지정된 경로에 파일이 없음
- 세미콜론 누락
4단계: Nginx 리로드
sudo systemctl reload nginx
restart가 아닌 reload를 사용하세요. 리로드는 기존 연결을 끊지 않고 새 연결에 새 설정을 적용합니다 — 다운타임 제로.
5단계: 인증서 확인
브라우저 확인
https://yourdomain.com을 방문합니다. 자물쇠 아이콘을 클릭하여 확인합니다:
- 발급자: “Let’s Encrypt” (또는 해당 인증 기관)
- 유효 기간: 시작 및 종료 날짜
- 도메인: URL과 일치
커맨드라인 확인
# 전체 인증서 세부 정보
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# 전체 체인 존재 여부 확인
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| grep -E 'Verify return code|depth='
예상 결과: Verify return code: 0 (ok)와 여러 depth 수준(인증서 + 중간 인증서).
온라인 확인
SSL Labs Server Test를 사용하여 종합 보고서를 확인합니다. 검사 항목:
- 인증서 체인 유효성
- 프로토콜 지원 (TLS 1.2 + 1.3만 표시되어야 함)
- 암호화 스위트 강도
- 알려진 취약점 (BEAST, POODLE, Heartbleed)
- HSTS 설정
목표: 등급 A 또는 A+.
갱신 방법
인증서 만료가 가까워지면 (Let’s Encrypt의 경우 90일 중 60일째):
- GetHTTPS에서 새 인증서를 발급받습니다(또는 갱신 도구 사용)
- 파일 교체:
sudo cp new-fullchain.pem /etc/ssl/gethttps/fullchain.pem sudo cp new-privkey.pem /etc/ssl/gethttps/privkey.pem - Nginx 리로드:
sudo systemctl reload nginx
재시작이 필요 없습니다. Nginx는 리로드 시 새 파일을 적용합니다. 전체 갱신 가이드 →
자동 갱신을 원하시나요? Certbot을 설치하면 자동으로 갱신됩니다:
sudo certbot --nginx -d example.com. Nginx 설정까지 모든 것을 처리합니다.
문제 해결
”SSL: error:0B080074:x509 certificate routines”
원인: fullchain.pem 대신 cert.pem을 사용하고 있습니다.
해결: ssl_certificate를 인증서와 중간 인증서 체인이 모두 포함된 fullchain.pem으로 변경합니다:
ssl_certificate /etc/ssl/gethttps/fullchain.pem; # cert.pem이 아님
“cannot load certificate key”
원인: 개인키 파일 권한이 잘못되었거나, 파일이 손상되었거나, 키가 인증서와 일치하지 않습니다.
해결:
# 권한 확인 (600이어야 함)
ls -la /etc/ssl/gethttps/privkey.pem
# 키 유효성 확인
sudo openssl ec -in /etc/ssl/gethttps/privkey.pem -check # ECDSA용
sudo openssl rsa -in /etc/ssl/gethttps/privkey.pem -check # RSA용
# 키와 인증서 일치 여부 확인
sudo openssl x509 -noout -modulus -in /etc/ssl/gethttps/fullchain.pem | md5sum
sudo openssl rsa -noout -modulus -in /etc/ssl/gethttps/privkey.pem | md5sum
# 두 해시가 반드시 일치해야 함
“nginx: [emerg] bind() to 0.0.0.0:443 failed”
원인: 포트 443이 다른 프로세스에서 이미 사용 중입니다.
해결:
# 포트 443을 사용 중인 프로세스 찾기
sudo ss -tlnp | grep 443
# 보통: 다른 Nginx 인스턴스 또는 Apache
sudo systemctl stop apache2 # Apache가 실행 중인 경우
sudo systemctl reload nginx
HTTPS는 작동하지만 브라우저에 “안전하지 않음” 표시
원인: 혼합 콘텐츠 — 페이지가 http://를 통해 이미지, 스크립트 또는 CSS를 로드합니다.
해결: 개발자 도구(F12) → 콘솔 → “Mixed Content” 경고를 확인합니다. 모든 리소스 URL을 https:// 또는 상대 경로로 업데이트합니다.
”ERR_SSL_VERSION_OR_CIPHER_MISMATCH”
원인: 클라이언트가 서버가 제공하는 TLS 버전이나 암호화 스위트를 지원하지 않습니다.
해결: 설정에 TLS 1.2가 포함되어 있는지 확인합니다(TLS 1.3만이 아닌):
ssl_protocols TLSv1.2 TLSv1.3; # TLSv1.3만이 아님
올바른 파일인데도 인증서가 “신뢰할 수 없음”으로 표시
원인: 인증서 체인이 불완전합니다 — fullchain.pem에 중간 인증서가 누락되었거나 파일 순서가 잘못되었습니다.
해결: 인증서 + 중간 인증서를 연결하여 fullchain.pem을 다시 구성합니다:
cat cert.pem chain.pem > fullchain.pem
순서가 중요합니다: 인증서가 먼저, 그다음 중간 인증서.
자주 묻는 질문
HTTP와 HTTPS에 별도의 설정 파일이 필요한가요?
아닙니다. 두 server 블록(포트 80과 443)을 같은 파일에 넣으세요. HTTP 블록은 HTTPS로 리다이렉트하기 위해서만 존재합니다.
ssl on;을 사용해야 하나요?
아닙니다. ssl on;은 더 이상 사용되지 않습니다. 대신 listen 443 ssl;을 사용하세요 — listen 지시문의 ssl 매개변수가 최신 방식입니다.
reload와 restart의 차이점은?
reload는 기존 연결을 끊지 않고 새 연결에 새 설정을 부드럽게 적용합니다. restart는 프로세스를 중지했다가 시작하므로 모든 연결이 잠시 끊깁니다. 인증서 변경 시에는 항상 reload를 사용하세요.
서로 다른 인증서로 여러 도메인을 제공할 수 있나요?
네. 각기 다른 server_name, ssl_certificate, ssl_certificate_key 지시문이 있는 별도의 server 블록을 사용하세요. Nginx는 SNI(Server Name Indication)를 사용하여 요청된 호스트 이름에 따라 올바른 인증서를 제공합니다.
Nginx는 ECDSA/ECC 인증서를 지원하나요?
네. Nginx는 RSA와 동일한 방식으로 ECDSA 인증서를 처리합니다 — 같은 지시문, 같은 파일 형식. GetHTTPS는 기본적으로 ECDSA P-256을 생성합니다(더 작은 키, 더 빠른 핸드셰이크).
HTTP/2를 활성화하려면?
listen 지시문에 http2를 추가합니다: listen 443 ssl http2;. 위의 권장 설정에 이미 포함되어 있습니다. HTTP/2는 HTTPS를 필요로 합니다 — 평문 HTTP에서는 사용할 수 없습니다.