![](/media/images/lets_encrypt_with_docker.webp)
Let's Encrypt憑證申請
使用容器化的Nginx與Certbot
在處理EC2上面的HTTPS設定的時候,雖然AWS有提供憑證管理的服務ACM,但因為ACM並不允許使用者把它所頒發的憑證直接裝在架設於EC2的私有服務上面,所以更常聽到的替EC2設定HTTPS的做法,其實是透過將EC2部屬於一個跟ACM關聯起來的ALB後面。
我自己架設的一些服務是將Nginx, Application容器化後部署於一台EC2上,在沒辦法使用ACM憑證的前提下,就需要另覓其他的方法。
Let’s Encrypt是一個免費開放的自動化憑證頒發機構,他的目標是透過ACME協定在不需要人力的情況下,可以讓網頁伺服器自動取得瀏覽器可信任的憑證。
這篇筆記記錄了如何使用他的第三方憑證申請客戶端程式Certbot的Docker映像檔,透過提供驗證檔案的方式,申請憑證給容器化的Nginx使用。
他的主要流程為:
1. 伺服器上的憑證管理軟體(也就是Certbot)會對Let’s Encrypt發出要申請xxx.com
的請求。
2. Let’s Encrypt要求憑證管理軟體「做到某些事情」來證明自己對xxx.com
網域具有控制的能力。
- 設定DNS紀錄
- 在網站上新增一個提供檔案的路徑 (這篇筆記使用的方法)
3. 憑證裡軟體完成這些任務後,會請Let’s Encrtpy CA來檢驗
4. 檢驗成功後,憑證管理軟體就可以使用授權過的金鑰,對Let’s Encrypt CA來提出憑證的申請、更新、註銷。
Docker Compose設定
這邊使用Docker-Compose搭起一個Nginx與Certbot的容器。
(Certbot並不會像Nginx一樣被作為一個服務叫起來,而是會以指令的形式來使用它)
version: '3'
services:
server:
container_name: "server"
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- {想掛入Nginx容器的config檔案路徑}:/etc/nginx/
- ./certbot/www:/var/www/certbot/:ro
- ./certbot/conf/:/etc/nginx/ssl/:ro
- ./certbot/archive:/etc/nginx/archive/:ro
certbot:
image: certbot/certbot:latest
volumes:
- ./certbot/www/:/var/www/certbot/:rw
- ./certbot/conf/:/etc/letsencrypt/live:rw
- ./certbot/archive:/etc/letsencrypt/archive:rw
- volumes關係示意圖
Volumes的第一行設定是有關於NginX Config的位置,因為Nginx支援Config的hot reload,可以直接把想要使用的設定從外面掛進去容器讓它生效。稍後會把寫了Let’s Encrypt要驗證的Http檔案路徑的設定檔放在這裡。
第二行之後的設定,可以跟下面的Certbot的volumes一起配對著看,這邊使用一個與Docker Compose同路徑的./certbot
資料夾做範例,把該目錄與其下的子目錄分別掛給Nginx與Certbot的服務:
[Nginx Container] [Host Machine] [Certbot Container]
/var/www/certbot/ <--> ./certbot/www <--> /var/www/certbot/
/etc/nginx/ssl <--> ./certbot/conf/ <--> /etc/letsencrypt/live
/etc/nginx/archive <--> ./certbot/archive/ <--> /etc/letsencrypt/archive
./certbot/www
:Certbot會把產生給Let’s Encrypt驗證的檔案放在這個目錄下。這個目錄會被另外被掛進去Nginx的/var/www/certbot,然後Nginx的Config會把要給Let’s Encrypt驗證的網站路徑(/.well-known/acme-challenge/
)指向這個目錄。./certbot/conf
:Certbot會把產生的憑證放在/etc/letsencrpyt/live
這個目錄下,但需要注意的是這裡的憑證檔案其實都是軟連結,他們其實都是指向放置在/etc/letsencrpyt/archive
路徑下的檔案。./certbot/archive
:因此基於上述的理由,我們也需要把/etc/letsencrypt/archive
掛出去到Nginx的目錄下面,Nginx才能讀取對應的憑證檔案。
Nginx.conf的設定
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
server {
listen 80;
listen [::]:80;
server_name xxx.com;
charset utf-8;
client_max_body_size 75M;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Redirect all HTTP traffic to HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name xxx.com;
# SSL configuration
ssl_certificate /etc/nginx/ssl/xxx.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/xxx.com/privkey.pem;
charset utf-8;
client_max_body_size 75M;
location / {
...看原本的網站指向哪裡...
}
}
}
Nginx定義兩個Server Block,分別監聽80, 443port的請求,
Server Block 80 Port
我們需要在這個Block定義好,要讓Let’s Encrypt來驗證檔案的路徑,也就是/.well-known/acme-challenge
,這個路徑會指向剛剛我們在docker-compose所掛載的volumevar/www/certbot
。然後我們把其他的請求全部轉給監聽443 Port的block。
Server Block 443 Port
ssl_certificate
以及ssl_certificate_key
分別去剛剛掛載的路徑/etc/nginx/ssl
下面取得憑證與私鑰。
Certbot指令
憑證申請
docker-compose.yml與nginx.conf都處理好之後,就可以準備來使用申請憑證的指令。這邊我們指定使用--webroot
的方式,讓Let’s Encrypt CA透過檢查目錄下的檔案是否合法。-d
參數則是指定了我們要替xxx.com
網域申請憑證。
docker-compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ -d xxx.com
中間Certbot會問一些跟註冊信箱,ToS有關的訊息,按他指示的步驟完成後應該會出現類似下面的訊息:
....
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/xxx.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/xxx.com/privkey.pem
This certificate expires on ~~~~
...
可以檢查Host Machine的./certbot/conf
目錄,看一下憑證是否有出現。
重新啟動Nginx的服務之後,應該就可以看到伺服器能處理HTTPS
的請求。