Ubuntu 서버 초기 설정 ④ — Nginx 설치와 Let's Encrypt HTTPS
서버가 안전하고 기본기가 갖춰졌다. 이제 세상과 연결하자. Nginx로 트래픽을 받고, Let's Encrypt로 자물쇠를 달아준다.
1~3편에서 SSH 보안, 방화벽, 시스템 기본 설정을 마쳤다. 이번 편에서는 Nginx 웹 서버를 설치하고, 도메인을 연결한 뒤, Certbot으로 무료 SSL 인증서를 발급받아 HTTPS를 활성화한다.
Ubuntu에 Nginx 설치하기
sudo apt install nginx -y
설치 확인
# Nginx 버전 확인
nginx -v
# 서비스 상태 확인
sudo systemctl status nginx
active (running)이 보이면 Nginx가 정상 동작 중이다.
기본 페이지 접속
브라우저에서 http://서버_IP를 열면 Nginx 기본 환영 페이지가 나타난다.
Welcome to nginx!
If you see this page, the nginx web server is successfully installed...
이 페이지가 보이면 Nginx 설치가 완료된 것이다. 🎉
💡 접속이 안 되는 경우: 2편에서 설정한 UFW에서 80번 포트가 허용되어 있는지 확인한다.
bash sudo ufw status | grep 80
도메인 DNS 설정
도메인이 서버 IP를 가리키도록 DNS A 레코드를 설정해야 한다. 도메인 등록 업체 또는 DNS 관리 서비스에서 설정한다.
A 레코드 설정 예시
| 호스트 | 타입 | 값 | TTL |
|---|---|---|---|
@ | A | 123.45.67.89 (서버 IP) | 300 |
www | A | 123.45.67.89 (서버 IP) | 300 |
@은 루트 도메인 (example.com)www는 서브도메인 (www.example.com)
💡 Cloudflare를 사용하는 경우: DNS 설정 시 프록시 상태를 DNS only (회색 구름)으로 두면 서버 IP가 직접 노출된다. Cloudflare CDN/보안 기능을 쓰려면 Proxied (주황 구름)으로 변경하되, SSL 모드를 Full (Strict)로 설정해야 한다.
DNS 반영에는 수 분~수 시간이 걸릴 수 있다. 확인 방법:
# 도메인이 서버 IP를 가리키는지 확인
dig +short example.com
# 출력: 123.45.67.89
Nginx Server Block(가상 호스트) 설정
Nginx의 Server Block은 Apache의 Virtual Host에 해당한다. 하나의 서버에서 여러 도메인을 서비스할 수 있게 해준다.
1단계 — 웹 루트 디렉토리 생성
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com/html
간단한 테스트 페이지를 만든다.
echo '<h1>example.com 작동 중!</h1>' > /var/www/example.com/html/index.html
2단계 — Server Block 설정 파일 작성
sudo nano /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# 로그 파일 경로
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}
3단계 — 사이트 활성화
# sites-enabled에 심볼릭 링크 생성
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# 기본 사이트 비활성화 (선택)
sudo rm /etc/nginx/sites-enabled/default
# 설정 문법 검사
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
test is successful이 나오면 문제없다.
# Nginx 재로드
sudo systemctl reload nginx
브라우저에서 http://example.com을 열면 "example.com 작동 중!" 페이지가 보여야 한다.
Certbot으로 Let's Encrypt SSL 인증서 발급
Let's Encrypt는 무료 SSL 인증서를 제공하는 비영리 인증 기관이다. Certbot은 인증서 발급과 Nginx 설정 변경을 자동으로 처리해주는 도구다.
Certbot 설치
sudo apt install certbot python3-certbot-nginx -y
인증서 발급
sudo certbot --nginx -d example.com -d www.example.com
인증서 발급 과정에서 다음을 묻는다.
- 이메일 주소 — 인증서 만료 알림 수신용
- 이용 약관 동의 —
Y - 이메일 수신 동의 — 선택사항 (EFF 뉴스레터)
- HTTP → HTTPS 리다이렉트 —
2(리다이렉트 설정 권장)
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
이 메시지가 나오면 인증서 발급 완료다. 🔒
Certbot이 자동으로 Nginx 설정을 수정해서 HTTPS를 활성화하고 HTTP→HTTPS 리다이렉트까지 설정해준다.
확인
브라우저에서 https://example.com을 열어 자물쇠 아이콘 🔒이 표시되는지 확인한다.
HTTP에서 HTTPS로 리다이렉트 설정
Certbot이 자동으로 설정해주지만, 수동으로 확인하거나 직접 설정할 경우를 위해 기록해둔다.
sudo nano /etc/nginx/sites-available/example.com
Certbot이 수정한 설정은 대략 아래와 같은 구조다.
# HTTP → HTTPS 리다이렉트
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 서버
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
# Let's Encrypt 인증서
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;
location / {
try_files $uri $uri/ =404;
}
}
listen 443 ssl http2;에서 HTTP/2가 활성화된 것도 확인할 수 있다.
Nginx 보안 헤더 추가
HTTPS만으로는 부족하다. 보안 헤더를 추가하면 XSS, 클릭재킹 등 흔한 웹 공격을 방어할 수 있다.
HTTPS server 블록 안에 다음을 추가한다.
# 보안 헤더
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
| 헤더 | 효과 |
|---|---|
X-Content-Type-Options | MIME 타입 스니핑 방지 |
X-Frame-Options | 다른 사이트에서 iframe으로 로드 차단 (클릭재킹 방지) |
X-XSS-Protection | 브라우저 XSS 필터 활성화 |
Referrer-Policy | 외부 링크 클릭 시 리퍼러 정보 제한 |
Strict-Transport-Security | 1년간 HTTPS 강제 (HSTS) |
# 설정 검증 및 재로드
sudo nginx -t && sudo systemctl reload nginx
💡 SSL Labs 테스트: SSL Labs에서 도메인을 입력하면 SSL 설정 등급을 확인할 수 있다. 위 설정을 적용하면 A+ 등급을 받을 수 있다.
SSL 인증서 자동 갱신 확인
Let's Encrypt 인증서는 90일마다 만료된다. Certbot은 자동 갱신 타이머를 함께 설치한다.
자동 갱신 타이머 확인
sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
Loaded: loaded (/lib/systemd/system/certbot.timer; enabled)
Active: active (waiting)
Trigger: Mon 2026-05-27 03:24:00 KST
active (waiting)이면 자동 갱신이 정상적으로 예약되어 있다. 하루에 2번 갱신 시도를 하며, 만료 30일 전부터 실제 갱신이 이루어진다.
수동 갱신 테스트
sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
simulated renewals succeeded가 나오면 자동 갱신이 정상 동작할 것이다.
(참고) 리버스 프록시 기본 설정
Node.js, Python(Flask/Django), Go 등의 애플리케이션을 Nginx 뒤에서 실행할 때는 리버스 프록시 설정을 사용한다.
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000; # 앱이 실행 중인 포트
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;
}
}
이 설정으로 외부에서 https://app.example.com으로 접속하면, Nginx가 SSL을 처리한 뒤 내부의 localhost:3000으로 전달한다.
📝 정리
- [x] Nginx 설치 —
apt install nginx로 설치, 기본 페이지 확인 - [x] DNS A 레코드 — 도메인이 서버 IP를 가리키도록 설정
- [x] Server Block — 사이트별 설정 파일을
sites-available에 작성,sites-enabled에 링크 - [x] Certbot + Let's Encrypt —
certbot --nginx로 무료 SSL 인증서 발급 및 자동 적용 - [x] HTTPS 리다이렉트 + HTTP/2 — Certbot이 자동 설정, 수동 확인 방법 기록
- [x] 보안 헤더 — HSTS, X-Frame-Options 등 추가로 SSL Labs A+ 달성
- [x] 자동 갱신 —
certbot.timer로 90일 만료 전 자동 갱신
다음 편 예고
5편: 서버 모니터링과 rsync 자동 백업
서버는 언젠가 문제가 생긴다. 디스크/메모리 모니터링 스크립트, logrotate 로그 관리, rsync 자동 백업, 그리고 "테스트하지 않은 백업은 백업이 아니다"는 원칙까지 다룬다.