Setup Let's Encrypt กับ nGINX
Reference: https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71
Setup certbot กับ nginx
เราจะต้องมี certbot
runคู่กับ nginx ก่อน certbot เป็น tool ของ Electronic Frontier Foundation สำหรับจัดการ Let's Encrypt certificates
version: '3'
services:
nginx:
image: nginx:1.15-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
certbot:
image: certbot/certbot
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
สังเกตุว่ามีการ mapping volumes ของทั้ง nginx
และ certbot
ให้ shared กันด้วย
Add "acme-challenge" path
เพิ่ม section ต่อไปนี้ลงใน server
section ของ service ที่เราต้องการให้มี certificate แต่เป็น port 80!
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
เช่น
server {
rewrite_log off;
listen 80;
charset utf-8;
server_name example.org;
client_max_body_size 1m;
location / {
return 301 https://$host$request_uri;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
จากนั้นเพิ่ม section นี้ลงใน server
ที่เป็น port 443! สังเกตุว่าตรง URL จะมีชื่อ domain ของเราอยู่ด้วย (ในที่นี้คือ example.org
) ต้องแก้ให้ตรงกับ domain ที่เราจะขอ
ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
และ (optional) best-practice HTTPS configuration ของ Let's Encrypt เอง
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
เช่น
server {
rewrite_log off;
listen 443 ssl http2;
charset utf-8;
server_name example.org;
location / {
root /app;
index home.html;
}
ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Create dummy certificate to start nginx
มี script สำหรับสร้าง dummy certificate (เป็น bash
) download ได้จาก
curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh
แต่ต้องแก้ file init-letsencrypt.sh
ก่อน มี 3 fields ที่ต้องแก้คือ
domains=(site.yourdomain.uri)
data_path="/data/certbot" # certbot shared path
email="admin@yourdomain.uri" # valid email address
Note: ถึงแม้ว่า domains
จะเป็น array แต่ควรทำทีละ site เพราะเคยเจอปัญหาทำหลายๆอันแล้ว script มัน run ไม่ถูก
run init-letsencrypt.sh
เพื่อ start nginx และ download certificate จาก Let's Encrypt!
Auto renewal
เพิ่ม script ดังต่อไปนี้ที่ certbot
เพื่อให้ check certificate renewal ทุกๆ 12 ชั่วโมง (ตามคำแนะนำของ Let's Encrypt)
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
และเพิ่ม script นี้ใน nginx
เพื่อให้ nginx reload config ทุกๆ 6 ชั่วโมง
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
docker-compose.yml
สุดท้าย หน้าตาประมาณนี้
version: '3'
services:
nginx:
image: nginx:1.15-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
image: certbot/certbot
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"