웹사이트 운영에서 SSL 인증서는 필수 보안 요소입니다.
하지만 Let's Encrypt SSL 인증서는 90일마다 갱신해야 하는 번거로움이 있죠.
특히 현대적인 웹 애플리케이션은 프론트엔드 서버와 백엔드 서버를 분리한 마이크로서비스 아키텍처를 채택하는 경우가 많습니다.
이러한 환경에서 Nginx 리버스 프록시를 통해 다중 서버 구조를 하나의 도메인으로 통합하고, SSL 인증서를 효율적으로 관리할 수 있습니다.
이 글에서는 Amazon Linux 환경에서 Nginx 리버스 프록시 구조와 Certbot을 활용한 SSL 인증서 자동갱신 시스템 구축 방법을 단계별로 상세히 알아보겠습니다.
실제 운영 환경에서 검증된 설정 방법과 각 명령어 실행 결과까지 포함하여 완벽한 가이드를 제공합니다.
리버스 프록시 아키텍처와 SSL 인증서의 중요성
현대적인 웹 애플리케이션은 다음과 같은 다층 구조로 설계됩니다:
클라이언트 → Nginx (리버스 프록시) → 프론트엔드 서버 (포트 3000) / 백엔드 API 서버 (포트 8080)
이러한 아키텍처에서 Nginx는 단순한 웹서버가 아닌 중요한 역할을 담당합니다:
- SSL 터미네이션 포인트 역할
- 로드 밸런싱 및 트래픽 분산
- 정적 파일 서빙 최적화
- 보안 헤더 및 방화벽 기능
SSL 인증서는 이 구조의 최전단인 Nginx에서 처리되어, 모든 하위 서비스에 보안을 제공합니다.
SSL 인증서 자동갱신이 필요한 이유
Let's Encrypt는 무료 SSL 인증서를 제공하지만 유효기간이 90일로 제한됩니다.
수동으로 갱신하다 보면 깜빡하기 쉽고, 인증서 만료로 인한 서비스 중단 위험이 있습니다.
자동갱신 시스템을 구축하면 다음과 같은 장점을 얻을 수 있습니다:
- 인증서 만료로 인한 서비스 중단 방지
- 관리 부담 최소화
- 보안 수준 지속적 유지
- 운영 안정성 향상
Amazon Linux 환경에서 Certbot 설치하기
Amazon Linux에서는 DNF 패키지 매니저를 사용하여 Certbot을 설치합니다.
Nginx 플러그인과 함께 설치하여 웹서버 설정 자동화를 지원받을 수 있습니다.
sudo dnf install -y certbot python3-certbot-nginx
실행 결과:
Last metadata expiration check: 0:01:23 ago on Sun 01 Jun 2025 02:15:42 PM KST.
Dependencies resolved.
================================================================================
Package Architecture Version Repository Size
================================================================================
Installing:
certbot noarch 2.7.4-1.amzn2023 amazonlinux 35k
python3-certbot-nginx noarch 2.7.4-1.amzn2023 amazonlinux 25k
Installing dependencies:
python3-acme noarch 2.7.4-1.amzn2023 amazonlinux 89k
python3-certbot noarch 2.7.4-1.amzn2023 amazonlinux 425k
...
Complete!
설치가 완료되면 Certbot 버전을 확인해보겠습니다.
certbot --version
실행 결과:
certbot 2.7.4
리버스 프록시 기반 Nginx 웹서버 SSL 설정 구성하기
리버스 프록시 환경에서 SSL 인증서를 적용하기 위해 Nginx 설정 파일을 수정해야 합니다.
이 설정은 프론트엔드 서버(React, Vue 등)와 백엔드 API 서버를 하나의 도메인으로 통합하는 마이크로서비스 아키텍처에 최적화되어 있습니다.
HTTPS 서버 블록과 HTTP 리다이렉션, 그리고 각 서비스로의 프록시 설정을 포함한 완전한 설정을 구성하겠습니다.
Nginx 메인 설정 파일 편집
sudo vim /etc/nginx/nginx.conf
다음은 실제 운영 환경에서 사용 중인 리버스 프록시 최적화된 Nginx 설정입니다:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
# HTTPS 서버 블록 - 리버스 프록시 설정
server {
listen 443 ssl;
listen [::]:443 ssl ipv6only=on;
server_name example.com www.example.com;
# SSL 인증서 설정 (Certbot에 의해 자동 관리)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# 백엔드 API 서버 프록시 설정 (/api 경로)
# 모든 API 요청을 백엔드 서버로 전달
location /api {
proxy_pass http://backend-server:8080;
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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# API 서버 응답 시간 최적화
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 프론트엔드 서버 프록시 설정 (/ 경로)
# React, Vue 등 SPA 애플리케이션 서빙
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
# WebSocket 지원 (개발 서버 Hot Reload 등)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# 클라이언트 정보 헤더 전달
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;
}
# 에러 페이지 설정
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# HTTP 서버 블록 (HTTPS 강제 리다이렉션)
# 모든 HTTP 요청을 HTTPS로 리다이렉트
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
return 404;
}
}
이 설정의 핵심 특징은 다음과 같습니다:
리버스 프록시 구조:
/api
경로: 백엔드 API 서버로 프록시 (포트 8080)/
경로: 프론트엔드 서버로 프록시 (포트 3000)- SSL 터미네이션을 Nginx에서 처리하여 내부 서버는 HTTP로 통신
보안 헤더 설정:
- 클라이언트 실제 IP 정보 전달
- HTTPS 프로토콜 정보 전달
- 호스트 정보 보존
Nginx 설정 검증하기
설정 파일 수정 후 반드시 문법 검사를 수행해야 합니다.
잘못된 설정으로 인한 웹서버 중단을 방지할 수 있습니다.
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를 재시작합니다.
sudo systemctl restart nginx
실행 결과:
# 성공시 아무 메시지도 출력되지 않음
서비스 상태를 확인해보겠습니다.
sudo systemctl status nginx
실행 결과:
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: active (running) since Sun 2025-06-01 14:20:15 KST; 5s ago
Process: 12345 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 12346 (nginx)
Tasks: 2 (limit: 4915)
Memory: 3.2M
CPU: 15ms
CGroup: /system.slice/nginx.service
├─12346 "nginx: master process /usr/sbin/nginx"
└─12347 "nginx: worker process"
SSL 인증서 발급 및 자동 설정하기
Certbot을 사용하여 SSL 인증서를 발급하고 Nginx 설정에 자동으로 적용하겠습니다.
도메인과 서브도메인을 모두 포함하여 인증서를 발급받습니다.
sudo certbot --nginx -d example.com -d www.example.com
실행 결과:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2025-08-30.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for example.com to /etc/nginx/nginx.conf
Successfully deployed certificate for www.example.com to /etc/nginx/nginx.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
인증서 발급이 성공하면 브라우저에서 HTTPS 접속을 확인할 수 있습니다.
Cron 자동갱신 시스템 구축하기
SSL 인증서 자동갱신을 위해 Cron 데몬을 설치하고 설정하겠습니다.
매일 새벽 시간대에 인증서 갱신 작업을 수행하도록 스케줄링합니다.
Cron 데몬 설치 및 활성화
sudo dnf install -y cronie
실행 결과:
Last metadata expiration check: 0:15:30 ago on Sun 01 Jun 2025 02:15:42 PM KST.
Package cronie-1.6.1-2.amzn2023.0.1.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
Cron 서비스를 시작하고 부팅시 자동 시작되도록 설정합니다.
sudo systemctl start crond
sudo systemctl enable crond
실행 결과:
Created symlink /etc/systemd/system/multi-user.target.wants/crond.service → /usr/lib/systemd/system/crond.service.
Cron 서비스 상태를 확인해보겠습니다.
sudo systemctl status crond
실행 결과:
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-06-01 14:25:42 KST; 30s ago
Main PID: 12450 (crond)
Tasks: 1 (limit: 4915)
Memory: 1.2M
CPU: 5ms
CGroup: /system.slice/crond.service
└─12450 /usr/sbin/crond -n
SSL 인증서 자동갱신 크론잡 설정하기
루트 계정의 크론탭을 편집하여 자동갱신 스케줄을 등록합니다.
sudo crontab -e
다음 내용을 크론탭에 추가합니다:
# 매일 새벽 3시에 갱신 확인 (로그 포함)
0 3 * * * /usr/bin/certbot renew --nginx --post-hook "systemctl reload nginx" >> /var/log/letsencrypt/renew.log 2>&1
이 크론잡은 다음과 같은 기능을 수행합니다:
- 매일 새벽 3시에 실행
- 갱신이 필요한 인증서만 자동 갱신
- 갱신 후 Nginx 자동 재로드
- 모든 과정을 로그 파일에 기록
크론탭 등록을 확인해보겠습니다.
sudo crontab -l
실행 결과:
# 매일 새벽 3시에 갱신 확인 (로그 포함)
0 3 * * * /usr/bin/certbot renew --nginx --post-hook "systemctl reload nginx" >> /var/log/letsencrypt/renew.log 2>&1
SSL 인증서 상태 확인 및 갱신 테스트
설정이 완료되면 인증서 상태를 확인하고 갱신 테스트를 수행해야 합니다.
실제 갱신 없이 테스트만 진행하여 시스템이 올바르게 동작하는지 검증할 수 있습니다.
현재 인증서 상태 확인하기
sudo certbot certificates
실행 결과:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: example.com
Serial Number: 4f8a3c2b1e9d7a6e5c8b9f2a1d3e4c5b6a7e8f9c
Key Type: RSA
Domains: example.com www.example.com
Expiry Date: 2025-08-30 13:45:12+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
자동갱신 테스트 수행하기
실제 갱신 과정을 시뮬레이션하여 설정이 올바른지 확인합니다.
sudo certbot renew --dry-run
실행 결과:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for example.com and www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
테스트가 성공하면 자동갱신 시스템이 올바르게 구성된 것입니다.
갱신 로그 모니터링 및 관리
자동갱신 시스템 운영 중 로그를 통해 갱신 상태를 모니터링할 수 있습니다.
정기적인 로그 확인으로 시스템 안정성을 보장할 수 있습니다.
갱신 로그 확인하기
sudo tail -f /var/log/letsencrypt/renew.log
갱신이 성공적으로 수행되면 다음과 같은 로그를 확인할 수 있습니다:
2025-06-01 03:00:01,123:DEBUG:certbot._internal.main:certbot version: 2.7.4
2025-06-01 03:00:01,124:DEBUG:certbot._internal.main:Location of certbot: /usr/bin/certbot
2025-06-01 03:00:01,124:DEBUG:certbot._internal.main:Arguments: ['--nginx', '--post-hook', 'systemctl reload nginx']
2025-06-01 03:00:01,125:DEBUG:certbot._internal.main:Discovered plugins: PluginsRegistry(PluginEntryPoint(name='nginx'...))
2025-06-01 03:00:02,456:INFO:certbot.renewal:Cert not yet due for renewal
로그 파일 로테이션 설정
로그 파일이 무한정 커지는 것을 방지하기 위해 logrotate를 설정할 수 있습니다.
sudo vim /etc/logrotate.d/letsencrypt
다음 내용을 추가합니다:
/var/log/letsencrypt/*.log {
weekly
missingok
rotate 12
compress
notifempty
create 644 root root
}
보안 강화 및 최적화 팁
SSL 인증서 자동갱신 시스템의 보안성과 안정성을 높이기 위한 추가 설정을 알아보겠습니다.
방화벽 설정 확인
HTTPS 포트가 열려있는지 확인합니다.
sudo firewall-cmd --list-all
실행 결과:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: ssh dhcpv6-client http https
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
SSL 보안 등급 확인
온라인 SSL 테스트 도구를 활용하여 보안 등급을 확인할 수 있습니다.
SSL Labs 같은 서비스에서 A+ 등급을 받는 것이 이상적입니다.
백업 및 복구 계획
인증서와 설정 파일의 정기적인 백업을 수행해야 합니다.
중요한 디렉토리는 다음과 같습니다:
/etc/letsencrypt/
- 인증서 및 설정/etc/nginx/nginx.conf
- 웹서버 설정/var/spool/cron/
- 크론잡 설정
문제 해결 및 트러블슈팅
SSL 인증서 자동갱신 과정에서 발생할 수 있는 일반적인 문제와 해결 방법을 정리했습니다.
갱신 실패 시 대처 방법
갱신이 실패하는 경우 다음 단계를 따라 문제를 해결할 수 있습니다:
- 로그 파일 확인
- 도메인 DNS 설정 점검
- 방화벽 및 포트 상태 확인
- Nginx 설정 문법 검사
- 수동 갱신 테스트 수행
인증서 경로 문제 해결
인증서 파일 경로가 변경되거나 손상된 경우:
sudo certbot certificates
sudo nginx -t
문제가 발생하면 인증서를 재발급받아 해결할 수 있습니다.
마이크로서비스 아키텍처에서의 SSL 관리 장점
리버스 프록시 기반 SSL 관리 방식은 다음과 같은 운영상 이점을 제공합니다:
중앙집중식 인증서 관리:
- 하나의 SSL 인증서로 모든 서비스 보안 커버
- 인증서 갱신 작업의 단순화
- 백엔드 서버들은 HTTP로 통신하여 성능 최적화
확장성과 유지보수성:
- 새로운 마이크로서비스 추가시 location 블록만 추가
- 개별 서비스의 SSL 설정 불필요
- 로드 밸런싱과 헬스체크 통합 관리
보안 강화:
- 내부 네트워크는 HTTP로 통신하여 SSL 오버헤드 제거
- 외부 접근점 단일화로 보안 정책 일관성 유지
- 인증서 만료 위험 최소화
마무리
리버스 프록시 기반 SSL 인증서 자동갱신 시스템 구축을 통해 현대적인 마이크로서비스 아키텍처에서 웹사이트 운영의 안정성과 보안성을 크게 향상시킬 수 있습니다.
Nginx를 중심으로 한 프론트엔드-백엔드 분리 구조는 확장성과 유지보수성을 동시에 제공합니다.
정기적인 모니터링과 로그 확인을 통해 시스템이 올바르게 동작하는지 확인하는 것이 중요합니다.
특히 리버스 프록시 환경에서는 각 서비스의 헬스체크와 프록시 설정 검증이 필수적입니다.
이 가이드에서 제시한 설정은 실제 운영 환경에서 검증된 방법으로, Amazon Linux 환경의 Nginx 리버스 프록시 구조에서 안정적으로 동작합니다.
SSL 인증서 관리 자동화와 마이크로서비스 아키텍처를 통해 더 안전하고 효율적인 웹서비스 운영을 시작해보세요.
추가적인 보안 강화나 성능 최적화가 필요한 경우 전문가의 도움을 받아 시스템을 고도화할 수 있습니다.
지속적인 업데이트와 모니터링을 통해 최신 보안 표준을 유지하는 것을 권장합니다.
'linux' 카테고리의 다른 글
firewalld vs iptables: 리눅스 방화벽 관리 도구의 차이점과 실전 활용 가이드 (0) | 2025.07.22 |
---|---|
nftables로 리눅스 방화벽 구성하기 - iptables 대체 가이드 (0) | 2025.06.15 |
.bashrc와 .zshrc를 활용한 터미널 환경 최적화 완벽 가이드 (0) | 2025.05.26 |
awk, sed, xargs를 활용한 실무 예제 모음: 리눅스 텍스트 처리 마스터 가이드 (0) | 2025.05.25 |
리눅스 개발자가 알아야 할 필수 명령어 단축키 모음 - 생산성 향상을 위한 완벽 가이드 (0) | 2025.05.24 |