Docker環(huán)境下自動更新Let’s Encrypt SSL證書

說明:以下腳本在Ubuntu 18.04運行通過,大部分腳本執(zhí)行需要管理員權(quán)限仑鸥。

1. 準(zhǔn)備docker環(huán)境

# 安裝必備工具包
apt-get -y install apt-transport-https ca-certificates curl software-properties-common

# 添加docker阿里云源僵芹,相對官方源速度更快
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

# 安裝最新版社區(qū)版docker
apt update -y 
apt install -y docker-ce

# 如果想要安裝指定版本的docker-ce,如下:
# 查看有哪些版本
apt-cache madison docker-ce
# 安裝指定版本
apt install -y docker-ce=[版本]

#  設(shè)置阿里云docker源
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://uon07it7.mirror.aliyuncs.com"]
}
EOF

systemctl daemon-reload
systemctl restart docker

# 下載安裝docker-compose
curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

2. Let's Encrypt免費證書簽發(fā)過程簡介

Let's Encrypt免費證書簽發(fā)過程包含以下三個階段:

  1. 在本地服務(wù)器上安裝Certbot膛壹,Certbot是簽發(fā)/更新證書的客戶端程序涡拘;
  2. 運行Certbot獲取SSL/TLS證書嚼锄,證書有效期為3個月诞外;
  3. 設(shè)置定時腳本每周運行一次Certbot更新證書。如果證書有效期小于30天灾票,Certbot會更新證書;

3. Certbot工作原理簡介

不論是第一次申請證書茫虽,還是更新證書刊苍,Certbot都會發(fā)起一次ACME請求既们,來驗證你是否擁有該域名。如果驗證通過正什,Certbot就會將新證書安裝到本地服務(wù)啥纸,其實就是將證書保存在一個目錄中。證書一般包含兩個文件(包含公鑰婴氮、私鑰以及證書等信息)斯棒,web服務(wù)器需要配置使用這兩個證書文件,來實現(xiàn)HTTPS訪問主经。

ACME驗證過程如下:

  1. 假設(shè)你有一個域名:example.com荣暮,和一個公網(wǎng)IP:xxx.xxx.xxx.xxx,并設(shè)置好了DNS解析罩驻;
  2. 配置好一臺web服務(wù)器穗酥,在80端口和443端口接受examle.com的請求;
  3. CertbotLet's Encrypt發(fā)起證書申請惠遏;
  4. Let's Encrypt返回Certbot一個唯一的token砾跃;
  5. Certbot配置web服務(wù)器,使token可以通過url:http://example.com/.well-known/acme-challenge/{token}訪問节吮;
  6. Let's Encrypt CA訪問上述url抽高,如果獲取到的token和它發(fā)送給Certbottoken一致,就可以證明你擁有該域名透绩;

注意:Certbot需要配置web服務(wù)器的相應(yīng)權(quán)限翘骂。以nginx為例,Certbot需要權(quán)限將token寫入.well-known/acme-challenge目錄渺贤。

4. 通過docker來運行Certbot

為了方便維護雏胃、升級,推薦使用docker來運行Certbot志鞍。整個過程可以分為兩部分:首次申請證書和更新證書瞭亮。

4.1 首次申請證書

  1. 創(chuàng)建web服務(wù)目錄: mkdir -p /letsencrypt/site。這里以靜態(tài)網(wǎng)頁為例固棚,也可以設(shè)為反向代理统翩。
  2. 創(chuàng)建docker-compose文件:nano /letsencrypt/docker-compose.yml
version: '3.1'

services:
  demo-site:
    container_name: 'demo-site'
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./site:/usr/share/nginx/html
    networks:
      - docker-network

networks:
  docker-network:
    driver: bridge
  1. 創(chuàng)建nginx配置文件:nano /letsencrypt/nginx.conf
server {
    listen 80;
    server_name example.com www.example.com;

    location ~ /.well-known/acme-challenge {
        allow all;
        root /usr/share/nginx/html;
    }

    root /usr/share/nginx/html;
    index index.html;
}
  1. 啟動web服務(wù)器:cd /letsencrypt && docker-compose up -d
  2. 運行Certbot申請證書
docker run --rm -it \
-v /letsencrypt/certbot/etc/letsencrypt:/etc/letsencrypt \             # 證書申請工作目錄
-v /letsencrypt/certbot/var/log/letsencrypt:/var/log/letsencrypt \     # 日志記錄
-v /letsencrypt/site:/data/letsencrypt \                               # ACME驗證token目錄,與nginx服務(wù)器共享
certbot/certbot \
certonly --webroot \                                                   # 指定ACME驗證方式:token文件驗證
--email youremail@domain.com --agree-tos --no-eff-email \              # 申請者郵件
--webroot-path=/data/letsencrypt \                                     # ACME驗證token文件放置目錄
-d example.com -d www.example.com                                      # 指定要申請證書的域名列表

如果腳本正常運行此洲,可以在/letsencrypt/certbot/etc/letsencrypt/live下找到example.com文件夾厂汗,其中包含申請成功的證書文件:fullchain.pemprivkey.pem

  1. 停止web服務(wù)器:cd /letsencrypt && docker-compose down
  2. 更新docker-compose配置
version: '3.1'

services:
  demo-site:
    container_name: 'demo-site'
    image: nginx:alpine
    ports:
      - "80:80"     # 保留80端口呜师,用于證書更新
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./site:/usr/share/nginx/html
      - ./certbot/etc/letsencrypt/live:/letsencrypt/live        # 當(dāng)前證書目錄
      - ./certbot/etc/letsencrypt/archive:/letsencrypt/archive  # 歷史證書目錄
      - ./dhparam-2048.pem:/letsencrypt/dhparam-2048.pem        # 使用2048位DH(Diffie-Hellman)參數(shù)
    networks:
      - docker-network

networks:
  docker-network:
    driver: bridge

生成2048位的DH參數(shù)文件命令如下:

openssl dhparam -out /letsencrypt/dhparam-2048.pem 2048

live目錄的證書會soft link到archive目錄娶桦,而docker對soft link支持不好,因此需要同時映射live和archive目錄。

  1. 更新nginx配置衷畦,啟用HTTPS

處理http:

server {
    listen      80;
    server_name example.com www.example.com;

    # 重定向到https
    location / {
        rewrite ^ https://$host$request_uri? permanent;
    }

    # 高優(yōu)先級栗涂,僅用于更新證書
    location ~ /.well-known/acme-challenge {
        allow all;
        root /data/letsencrypt;
    }
}

處理https:

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    server_tokens off;

    ssl on;

    ssl_certificate /letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /letsencrypt/live/example.com/privkey.pem;

    ssl_buffer_size 8k;

    ssl_dhparam /letsencrypt/dhparam-2048.pem; # 使用2048位DH參數(shù),加強安全

    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

    ssl_ecdh_curve secp384r1;
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    root /usr/share/nginx/html;
    index index.html;
}

DH以及OCSP內(nèi)容請參考:Strong SSL Security On nginx

  1. 重新啟動web服務(wù)器:cd /letsencrypt && docker-compose up -d

4.2 更新證書

  1. 設(shè)置更新腳本
    touch /letsencrypt/renew.sh && chmod +x /letsencrypt/renew.sh
    nano /letsencrypt/renew.sh

renew.sh腳本內(nèi)容如下:

#!/bin/bash

docker run -it --rm \
-v /letsencrypt/certbot/etc/letsencrypt:/etc/letsencrypt \
-v /letsencrypt/certbot/var/lib/letsencrypt:/var/lib/letsencrypt \
-v /letsencrypt/certbot/var/log/letsencrypt:/var/log/letsencrypt \
-v /letsencrypt/site:/data/letsencrypt \
certbot/certbot \
renew --webroot -w /data/letsencrypt --quiet && docker kill --signal=HUP demo-site

最后一行腳本說明:在更新完證書后祈争,通知nginx重新加載配置斤程。

  1. 設(shè)置定時任務(wù)
    通過crontab設(shè)置定時任務(wù):
    crontab -e
    添加一行,每周執(zhí)行一次更新腳本:
    0 1 * * 0 /letsencrypt/renew.sh

5. 安全加強

可以通過ssllabs.com驗證證書菩混,如果按照上述配置忿墅,應(yīng)該可以獲得A+評價。
當(dāng)然沮峡,還可以進一步通過securityheaders.io校驗網(wǎng)站安全性疚脐,對于nginx可以添加以下配置:

server {
    # ....

    location / {
        #security headers
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "DENY" always;
        #CSP
        add_header Content-Security-Policy "frame-src 'self'; default-src 'self'; script-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; font-src 'self' data: https://maxcdn.bootstrapcdn.com; form-action 'self'; upgrade-insecure-requests;" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    }

    # ....
}

6. 小結(jié)

本文參考How to Set Up Free SSL Certificates from Let's Encrypt using Docker and Nginx,對Docker環(huán)境下如何使用Let's Encrypt自動獲取/更新SSL證書做了一個簡明攻略帖烘。
如果你正在使用K8S亮曹,ingress nginxtraefik都對let‘s encrypt提供了很好的支持,配合helm來安裝部署秘症,也更為簡單方便照卦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市乡摹,隨后出現(xiàn)的幾起案子役耕,更是在濱河造成了極大的恐慌,老刑警劉巖聪廉,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞬痘,死亡現(xiàn)場離奇詭異,居然都是意外死亡板熊,警方通過查閱死者的電腦和手機框全,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來干签,“玉大人津辩,你說我怎么就攤上這事∪堇停” “怎么了喘沿?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竭贩。 經(jīng)常有香客問我蚜印,道長,這世上最難降的妖魔是什么留量? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任窄赋,我火速辦了婚禮哟冬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寝凌。我一直安慰自己柒傻,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布较木。 她就那樣靜靜地躺著,像睡著了一般青柄。 火紅的嫁衣襯著肌膚如雪伐债。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天致开,我揣著相機與錄音峰锁,去河邊找鬼。 笑死双戳,一個胖子當(dāng)著我的面吹牛虹蒋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播飒货,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼魄衅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塘辅?” 一聲冷哼從身側(cè)響起晃虫,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扣墩,沒想到半個月后哲银,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡呻惕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年荆责,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亚脆。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡做院,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出型酥,到底是詐尸還是另有隱情山憨,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布弥喉,位于F島的核電站郁竟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏由境。R本人自食惡果不足惜棚亩,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一蓖议、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧讥蟆,春花似錦勒虾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至质况,卻和暖如春愕宋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背结榄。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工中贝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人臼朗。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓邻寿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親视哑。 傳聞我的和親對象是個殘疾皇子绣否,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容