이 가이드는 mod_ssl을 사용하여 Apache HTTP Server에 SSL 인증서를 설치하는 전체 과정을 안내합니다. 파일 업로드부터 강화된 TLS 설정 및 일반적인 오류 해결까지 다룹니다. GetHTTPS, Certbot 또는 기타 CA에서 발급받은 인증서에 사용할 수 있습니다.
아직 인증서가 없다면 5분 만에 무료로 발급받으세요.
사전 준비
- Apache 2.4 이상 설치 및 HTTP(포트 80)로 사이트 서비스 중
- Root/sudo 접근 권한
- 인증서 파일 — Apache는 3개의 별도 파일이 필요합니다:
cert.pem— 인증서(엔드 엔티티만)privkey.pem— 개인키chain.pem— 중간 CA 인증서 체인
왜 3개의 파일이 필요한가요? Nginx(단일
fullchain.pem사용)와 달리 Apache는 전통적으로 인증서와 체인을 별도 파일로 요구합니다. Apache 2.4.8 이상에서는SSLCertificateFile에fullchain.pem을 사용하고SSLCertificateChainFile을 생략할 수 있습니다. 형식 세부 정보 →
1단계: 인증서 파일 업로드
# 보안 디렉터리 생성
sudo mkdir -p /etc/ssl/gethttps
# 서버에 파일 복사
sudo cp cert.pem chain.pem privkey.pem /etc/ssl/gethttps/
# 개인키 권한 제한
sudo chmod 600 /etc/ssl/gethttps/privkey.pem
sudo chmod 644 /etc/ssl/gethttps/cert.pem /etc/ssl/gethttps/chain.pem
sudo chown root:root /etc/ssl/gethttps/*
SCP로 전송하는 경우:
scp cert.pem chain.pem privkey.pem user@your-server:/tmp/
# 서버에서:
sudo mv /tmp/{cert,chain,privkey}.pem /etc/ssl/gethttps/
2단계: 필요한 Apache 모듈 활성화
# Debian/Ubuntu
sudo a2enmod ssl # 핵심 SSL 모듈
sudo a2enmod headers # HSTS 및 보안 헤더용
sudo a2enmod rewrite # HTTP→HTTPS 리다이렉트용 (.htaccess 사용 시)
sudo systemctl restart apache2
# CentOS/RHEL/Amazon Linux
sudo yum install mod_ssl # 보통 한 번에 설치 및 활성화
sudo systemctl restart httpd
mod_ssl이 로드되었는지 확인:
apachectl -M | grep ssl
# Expected: ssl_module (shared)
3단계: HTTPS VirtualHost 설정
사이트의 SSL 설정 파일을 생성하거나 편집합니다. Debian/Ubuntu에서는 보통 /etc/apache2/sites-available/yourdomain-ssl.conf입니다:
# ─── HTTPS server ────────────────────────────
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
# Certificate files
SSLEngine on
SSLCertificateFile /etc/ssl/gethttps/cert.pem
SSLCertificateKeyFile /etc/ssl/gethttps/privkey.pem
SSLCertificateChainFile /etc/ssl/gethttps/chain.pem
# TLS protocol — only 1.2 and 1.3
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLCompression off
# OCSP stapling (faster cert verification for clients)
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/apache2/ssl_stapling(128000)"
# Security headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
# Your site
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
</Directory>
</VirtualHost>
# ─── HTTP redirect ───────────────────────────
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
각 디렉티브의 역할:
| 디렉티브 | 용도 |
|---|---|
SSLEngine on | 이 VirtualHost에 SSL/TLS 활성화 |
SSLCertificateFile | 인증서 경로 |
SSLCertificateKeyFile | 개인키 경로 |
SSLCertificateChainFile | 중간 CA 인증서 경로 |
SSLProtocol | TLS 1.2/1.3만 허용 — 이전 버전은 폐기됨 |
SSLHonorCipherOrder off | 클라이언트가 최적의 암호화 방식을 선택하도록 허용 |
SSLCompression off | CRIME 공격 방지 |
SSLUseStapling | 서버가 OCSP 응답을 미리 가져옴 |
Strict-Transport-Security | HSTS — 브라우저가 항상 HTTPS를 사용하도록 기억 |
Redirect permanent | 301 리다이렉트 HTTP → HTTPS |
4단계: 사이트 활성화 및 테스트
# Debian/Ubuntu
sudo a2ensite yourdomain-ssl.conf
sudo apachectl configtest # "Syntax OK"가 표시되어야 합니다
sudo systemctl reload apache2
# CentOS/RHEL
sudo apachectl configtest
sudo systemctl reload httpd
configtest에서 오류가 보고되면 정확한 줄 번호를 알려줍니다 — 리로드하기 전에 수정하세요.
5단계: 확인
브라우저: https://yourdomain.com을 방문합니다. 자물쇠 아이콘을 클릭하여 “Let’s Encrypt”가 발급자로 표시되는지 확인합니다.
명령줄:
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
온라인: SSL Labs Server Test에서 종합 등급을 확인합니다. 목표: A 또는 A+.
Apache vs Nginx: 인증서 파일 차이점
| Apache | Nginx | |
|---|---|---|
| 인증서 | SSLCertificateFile cert.pem | ssl_certificate fullchain.pem |
| 개인키 | SSLCertificateKeyFile privkey.pem | ssl_certificate_key privkey.pem |
| 체인 | SSLCertificateChainFile chain.pem | fullchain.pem에 포함 |
| 필요한 파일 수 | 별도 파일 3개 | 파일 2개 (체인 결합) |
Apache 2.4.8 이상에서는 SSLCertificateFile에 결합된 fullchain.pem을 사용할 수 있으며, 이 경우 SSLCertificateChainFile을 생략할 수 있습니다.
갱신
인증서 만료가 다가오면 (여기서 확인):
# 파일 교체
sudo cp new-cert.pem /etc/ssl/gethttps/cert.pem
sudo cp new-chain.pem /etc/ssl/gethttps/chain.pem
sudo cp new-privkey.pem /etc/ssl/gethttps/privkey.pem
# 리로드(재시작 아님) — 다운타임 없음
sudo systemctl reload apache2 # Debian/Ubuntu
sudo systemctl reload httpd # CentOS/RHEL
문제 해결
”AH02572: Failed to configure certificate” / 키 불일치
인증서와 개인키가 일치하지 않습니다. 일치 여부를 확인하세요:
# 이 두 해시값이 동일해야 합니다
openssl x509 -noout -modulus -in /etc/ssl/gethttps/cert.pem | md5sum
openssl rsa -noout -modulus -in /etc/ssl/gethttps/privkey.pem | md5sum
해시값이 다르면 서로 다른 GetHTTPS 세션의 파일을 사용 중인 것입니다. 동일한 세션에서 두 파일을 다시 다운로드하세요.
”AH01909: server certificate does NOT include an ID”
ServerName이 인증서의 SAN 필드에 있는 도메인과 일치하지 않습니다:
openssl x509 -noout -text -in /etc/ssl/gethttps/cert.pem | grep -A1 "Subject Alternative Name"
Apache의 ServerName이 나열된 DNS 이름 중 하나와 정확히 일치하는지 확인하세요.
브라우저에 “인증서를 신뢰할 수 없음” 표시
중간 체인이 누락되었습니다. SSLCertificateChainFile이 cert.pem이 아닌 chain.pem(중간 인증서)을 가리키는지 확인하세요. 체인을 테스트합니다:
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | grep "Verify return code"
# "Verify return code: 0 (ok)" = 정상
# "Verify return code: 21 (unable to verify)" = 체인 불완전
“AH00526: Syntax error on line X”
Apache 설정 구문 오류입니다. 일반적인 원인:
</VirtualHost>닫는 태그 누락SSLCertificateChainFile철자 오류- 헤더 값에 따옴표 누락
- 파일 경로가 존재하지 않음
HTTPS는 작동하지만 “안전하지 않음” 표시
혼합 콘텐츠 문제입니다 — 페이지가 HTTP를 통해 리소스를 로드하고 있습니다. DevTools → Console을 열어 http:// URL을 수정하세요.
자주 묻는 질문
cert + chain을 분리하지 않고 fullchain.pem을 사용할 수 있나요?
네, Apache 2.4.8 이상에서 가능합니다. SSLCertificateFile /path/to/fullchain.pem을 사용하고 SSLCertificateChainFile 디렉티브를 완전히 제거하면 됩니다. 이전 버전의 Apache에서는 별도 파일이 필요합니다.
Apache 버전을 어떻게 확인하나요?
apachectl -v
# or
httpd -v
Apache를 재시작해야 하나요, 리로드만 하면 되나요?
리로드 (systemctl reload)만으로 충분하며 다운타임이 없습니다. 재시작(systemctl restart)은 모든 활성 연결을 끊습니다. 인증서 변경 시에는 항상 리로드를 사용하세요.
Apache에서 도메인별로 다른 인증서를 서비스할 수 있나요?
네. 서로 다른 ServerName과 SSLCertificate* 디렉티브를 가진 별도의 <VirtualHost *:443> 블록을 생성하면 됩니다. Apache는 SNI(Server Name Indication)를 사용하여 올바른 인증서를 선택합니다.
Apache는 ECDSA 인증서를 지원하나요?
네. Apache 2.4 이상은 RSA와 동일한 방식으로 ECDSA를 처리합니다 — 동일한 디렉티브, 동일한 파일 형식입니다. GetHTTPS는 기본적으로 ECDSA P-256을 생성합니다.
Apache의 SSL 오류 로그는 어디에 있나요?
# Debian/Ubuntu
tail -f /var/log/apache2/error.log
# CentOS/RHEL
tail -f /var/log/httpd/ssl_error_log