Post

[Network] ๐Ÿ”’ Let's Encrypt + Certbot์œผ๋กœ Nginx HTTPS ๋ฌด๋ฃŒ SSL ์ ์šฉํ•˜๊ธฐ

[Network] ๐Ÿ”’ Let's Encrypt + Certbot์œผ๋กœ Nginx HTTPS ๋ฌด๋ฃŒ SSL ์ ์šฉํ•˜๊ธฐ

์›น ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•  ๋•Œ HTTPS๋Š” ์„ ํƒ์ด ์•„๋‹Œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. Letโ€™s Encrypt๋Š” ๋น„์˜๋ฆฌ ๊ธฐ๊ด€ ISRG(Internet Security Research Group)์—์„œ ์šด์˜ํ•˜๋Š” ๋ฌด๋ฃŒ SSL/TLS ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ ๊ธฐ๊ด€์ž…๋‹ˆ๋‹ค. Certbot ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ช…๋ น์–ด ๋ช‡ ์ค„๋กœ ์ธ์ฆ์„œ ๋ฐœ๊ธ‰๋ถ€ํ„ฐ Nginx ์„ค์ • ์ž๋™ํ™”, ์ž๋™ ๊ฐฑ์‹ ๊นŒ์ง€ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ”‘ SSL/TLS์™€ HTTPS ๊ธฐ๋ณธ ๊ฐœ๋…

SSL(Secure Sockets Layer) / TLS(Transport Layer Security)๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์„ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ณด์•ˆ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค. HTTPS๋Š” ์ด SSL/TLS ์•”ํ˜ธํ™”๋ฅผ ์ ์šฉํ•œ HTTP๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

1
2
HTTP  (ํ‰๋ฌธ ์ „์†ก) โ†’ ์ค‘๊ฐ„์ž ๊ณต๊ฒฉ, ๋„์ฒญ ๊ฐ€๋Šฅ
HTTPS (์•”ํ˜ธํ™” ์ „์†ก) โ†’ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ณด์žฅ, ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋ฒ„ ๊ฒ€์ฆ

TLS ํ•ธ๋“œ์…ฐ์ดํฌ ๋™์ž‘ ์›๋ฆฌ:

1
2
3
4
5
6
ํด๋ผ์ด์–ธํŠธ                        ์„œ๋ฒ„
    โ”‚โ”€โ”€ ClientHello โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ โ”‚  ์•”ํ˜ธํ™” ๋ฐฉ์‹ ์ œ์•ˆ
    โ”‚โ† ServerHello + ์ธ์ฆ์„œ โ”€โ”€โ”€โ”€โ”€  โ”‚  ์„œ๋ฒ„ ์ธ์ฆ์„œ ์ „๋‹ฌ
    โ”‚โ”€โ”€ ์ธ์ฆ์„œ ๊ฒ€์ฆ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’  โ”‚  CA ์„œ๋ช… ํ™•์ธ
    โ”‚โ”€โ”€ ์„ธ์…˜ ํ‚ค ์ƒ์„ฑ (๋Œ€์นญํ‚ค) โ”€โ”€โ”€โ†’  โ”‚  ์ดํ›„ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”
    โ”‚โ†โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ์•”ํ˜ธํ™” ํ†ต์‹  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚

์ธ์ฆ์„œ ์ข…๋ฅ˜

์ข…๋ฅ˜๋ณดํ˜ธ ๋ฒ”์œ„์˜ˆ์‹œ
๋‹จ์ผ ๋„๋ฉ”์ธ1๊ฐœ ๋„๋ฉ”์ธexample.com
์™€์ผ๋“œ์นด๋“œ1๊ฐœ ๋„๋ฉ”์ธ + ๋ชจ๋“  ์„œ๋ธŒ๋„๋ฉ”์ธ*.example.com
๋ฉ€ํ‹ฐ ๋„๋ฉ”์ธ(SAN)์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ ๋™์‹œa.com, b.com

Letโ€™s Encrypt ํŠน์ง•

ํ•ญ๋ชฉ๋‚ด์šฉ
๋น„์šฉ๋ฌด๋ฃŒ
์œ ํšจ๊ธฐ๊ฐ„90์ผ (์ž๋™ ๊ฐฑ์‹  ํ•„์ˆ˜)
๋ฐœ๊ธ‰ ๋ฐฉ์‹ACME ํ”„๋กœํ† ์ฝœ ์ž๋™ํ™”
์‹ ๋ขฐ๋„์ฃผ์š” ๋ธŒ๋ผ์šฐ์ €ยทOS์—์„œ ์‹ ๋ขฐ
์ œํ•œ๋™์ผ ๋„๋ฉ”์ธ ์ฃผ๋‹น 5ํšŒ ๋ฐœ๊ธ‰ ์ œํ•œ

Tip: ์œ ํšจ๊ธฐ๊ฐ„์ด 90์ผ๋กœ ์งง์€ ์ด์œ ๋Š” ๋ณด์•ˆ ์‚ฌ๊ณ  ๋ฐœ์ƒ ์‹œ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ์ค„์ด๊ณ , ์ž๋™ ๊ฐฑ์‹  ์ƒํƒœ๊ณ„๋ฅผ ์œ ๋„ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.


๐Ÿ› ๏ธ ์‚ฌ์ „ ์ค€๋น„

  • ๋„๋ฉ”์ธ์ด ์„œ๋ฒ„ IP๋กœ DNS ๋ ˆ์ฝ”๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐฉํ™”๋ฒฝ์—์„œ ํฌํŠธ 80(HTTP) ๊ณผ 443(HTTPS) ์ด ์—ด๋ ค ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Certbot ์ธ์ฆ ์‹œ ํฌํŠธ 80์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ Nginx๊ฐ€ ์‹คํ–‰ ์ค‘์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
1
2
3
4
# ํฌํŠธ ๊ฐœ๋ฐฉ ํ™•์ธ (Ubuntu UFW ๊ธฐ์ค€)
sudo ufw allow 80
sudo ufw allow 443
sudo ufw reload

๐Ÿ“ฆ Certbot ์„ค์น˜

Ubuntu / Debian

1
2
3
sudo apt update
sudo apt install nginx -y
sudo apt install certbot python3-certbot-nginx -y

Rocky Linux / CentOS

1
2
3
sudo dnf install nginx -y
sudo dnf install epel-release -y
sudo dnf install certbot python3-certbot-nginx -y

Apache๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

python3-certbot-nginx ๋Œ€์‹  python3-certbot-apache๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

1
sudo apt install certbot python3-certbot-apache -y

โš™๏ธ Nginx ๊ธฐ๋ณธ ์„ค์ • (HTTP)

์ธ์ฆ์„œ ๋ฐœ๊ธ‰ ์ „์— Nginx๊ฐ€ ๋„๋ฉ”์ธ์„ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

1
sudo vi /etc/nginx/conf.d/example.com.conf
1
2
3
4
5
6
7
8
9
10
11
12
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

์„ค์ • ์ ์šฉ:

1
2
sudo nginx -t          # ๋ฌธ๋ฒ• ๊ฒ€์‚ฌ
sudo systemctl reload nginx

๐Ÿ” SSL ์ธ์ฆ์„œ ๋ฐœ๊ธ‰

Nginx ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฐฉ์‹ (๊ถŒ์žฅ)

Certbot์ด Nginx ์„ค์ •์„ ์ž๋™์œผ๋กœ ์ˆ˜์ •ํ•ด์ค๋‹ˆ๋‹ค.

1
sudo certbot --nginx -d example.com -d www.example.com

๋ฐœ๊ธ‰ ๊ณผ์ •์—์„œ ์ด๋ฉ”์ผ ์ฃผ์†Œ ์ž…๋ ฅ, ์ด์šฉ์•ฝ๊ด€ ๋™์˜, HTTPโ†’HTTPS ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์„ค์ • ์—ฌ๋ถ€๋ฅผ ๋ฌป์Šต๋‹ˆ๋‹ค.

๋ฐœ๊ธ‰ ์„ฑ๊ณต ์‹œ ์•„๋ž˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
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 2026-07-25.

Standalone ๋ฐฉ์‹ (Nginx ์ค‘์ง€ ํ›„ ๋ฐœ๊ธ‰)

1
2
3
sudo systemctl stop nginx
sudo certbot certonly --standalone -d example.com
sudo systemctl start nginx

ํฌํŠธ 80์„ Certbot์ด ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ Nginx๋ฅผ ๋จผ์ € ์ค‘์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Webroot ๋ฐฉ์‹

Nginx๋ฅผ ์ค‘์ง€ํ•˜์ง€ ์•Š๊ณ  ๋ฐœ๊ธ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
2
3
4
sudo certbot certonly --webroot \
  -w /var/www/html \
  -d example.com \
  -d www.example.com

๐Ÿ“„ ๋ฐœ๊ธ‰ ํ›„ Nginx ์„ค์ •

--nginx ์˜ต์…˜์œผ๋กœ ๋ฐœ๊ธ‰ํ•˜๋ฉด ์„ค์ •์ด ์ž๋™์œผ๋กœ ์ˆ˜์ •๋ฉ๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ์ ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

    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;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

์„ค์ • ์ ์šฉ:

1
2
sudo nginx -t
sudo systemctl reload nginx

๐Ÿ”„ ์ž๋™ ๊ฐฑ์‹  ์„ค์ •

Letโ€™s Encrypt ์ธ์ฆ์„œ๋Š” 90์ผ๋งˆ๋‹ค ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ์ž๋™ ๊ฐฑ์‹ ์„ ๋ฐ˜๋“œ์‹œ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐฑ์‹  ํ…Œ์ŠคํŠธ

1
sudo certbot renew --dry-run

--dry-run์€ ์‹ค์ œ ๊ฐฑ์‹  ์—†์ด ๊ฐฑ์‹  ๊ณผ์ •์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.

Crontab์œผ๋กœ ์ž๋™ ๊ฐฑ์‹ 

1
sudo crontab -e

์•„๋ž˜ ๋ผ์ธ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ๋ฃŒ 30์ผ ์ „๋ถ€ํ„ฐ ๊ฐฑ์‹ ์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
# ๋งค์ผ ์ •์˜ค์— ๊ฐฑ์‹  ํ™•์ธ
0 12 * * * /usr/bin/certbot renew --quiet

# ๋˜๋Š” ๋งค์ฃผ ์›”์š”์ผ ์ƒˆ๋ฒฝ 3์‹œ + ๊ฐฑ์‹  ํ›„ Nginx ์žฌ์‹œ์ž‘
0 3 * * 1 /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"

Systemd Timer๋กœ ์ž๋™ ๊ฐฑ์‹  (Ubuntu ๊ถŒ์žฅ)

Ubuntu 22.04 ์ด์ƒ์—์„œ๋Š” Certbot ํŒจํ‚ค์ง€ ์„ค์น˜ ์‹œ systemd timer๊ฐ€ ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
# ํƒ€์ด๋จธ ์ƒํƒœ ํ™•์ธ
sudo systemctl status certbot.timer

# ์ˆ˜๋™์œผ๋กœ ๊ฐฑ์‹  ์‹คํ–‰
sudo certbot renew

๐Ÿ” ์ธ์ฆ์„œ ๊ด€๋ฆฌ ๋ช…๋ น์–ด

1
2
3
4
5
6
7
8
9
10
11
# ๋ฐœ๊ธ‰๋œ ์ธ์ฆ์„œ ๋ชฉ๋ก ํ™•์ธ
sudo certbot certificates

# ํŠน์ • ๋„๋ฉ”์ธ ์ธ์ฆ์„œ ๊ฐฑ์‹ 
sudo certbot renew --cert-name example.com

# ์ธ์ฆ์„œ ํ๊ธฐ
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/fullchain.pem

# ์ธ์ฆ์„œ ์‚ญ์ œ (๋กœ์ปฌ ํŒŒ์ผ๋งŒ ์‚ญ์ œ)
sudo certbot delete --cert-name example.com

โ“ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

๋ฐœ๊ธ‰ ์‹คํŒจ: ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜

1
Timeout during connect (likely firewall problem)

โ†’ ๋ฐฉํ™”๋ฒฝ์—์„œ ํฌํŠธ 80/443 ๊ฐœ๋ฐฉ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์ด๋ผ๋ฉด ๋ณด์•ˆ ๊ทธ๋ฃน(Security Group)๋„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๋ฐœ๊ธ‰ ์‹คํŒจ: ๋„๋ฉ”์ธ ํ™•์ธ ์˜ค๋ฅ˜

1
DNS problem: NXDOMAIN looking up A for example.com

โ†’ DNS A ๋ ˆ์ฝ”๋“œ๊ฐ€ ์„œ๋ฒ„ IP๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

1
2
dig A example.com
nslookup example.com

Nginx ์„ค์ • ์˜ค๋ฅ˜

1
nginx: [emerg] invalid parameter

โ†’ sudo nginx -t๋กœ ์„ค์ • ๋ฌธ๋ฒ•์„ ๊ฒ€์‚ฌํ•˜๊ณ , ์„ธ๋ฏธ์ฝœ๋ก ยท๊ด„ํ˜ธ ๋ˆ„๋ฝ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ฃผ๋‹น ๋ฐœ๊ธ‰ ํ•œ๋„ ์ดˆ๊ณผ

1
Error: too many certificates already issued for exact set of domains

โ†’ Letโ€™s Encrypt๋Š” ๋™์ผ ๋„๋ฉ”์ธ์— ๋Œ€ํ•ด ์ฃผ๋‹น 5ํšŒ ๋ฐœ๊ธ‰ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค. --staging ์˜ต์…˜์œผ๋กœ ํ…Œ์ŠคํŠธ ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•˜์—ฌ ์„ค์ •์„ ๊ฒ€์ฆํ•œ ํ›„ ์‹ค์ œ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

1
2
# ํ…Œ์ŠคํŠธ ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ (ํ•œ๋„ ๋ฏธ์†Œ๋ชจ)
sudo certbot --nginx --staging -d example.com

โœ… ์š”์•ฝ

  1. sudo apt install certbot python3-certbot-nginx๋กœ Certbot์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
  2. Nginx์— server_name์„ ์„ค์ •ํ•œ ๋’ค sudo certbot --nginx -d ๋„๋ฉ”์ธ์œผ๋กœ ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ฐœ๊ธ‰ ํ›„ /etc/letsencrypt/live/๋„๋ฉ”์ธ/ ๊ฒฝ๋กœ์— ์ธ์ฆ์„œ๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
  4. sudo certbot renew --dry-run์œผ๋กœ ์ž๋™ ๊ฐฑ์‹ ์„ ํ…Œ์ŠคํŠธํ•œ ๋’ค crontab ๋˜๋Š” systemd timer๋กœ ์ž๋™ ๊ฐฑ์‹ ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
This post is licensed under CC BY 4.0 by the author.