今からお前んちこいよ

多摩川沿いにて細々とお勉強。

【SSLサーバ構築】docker-compose + Let’s Encrypt + Nginxでの設定

SSL証明書の発行更新はホストOSで行い、docker-composeで起動したNginxコンテナにその証明書をマウントする方針。 Nginxでは、443(https)ポートを解放し、80(http)ポートへのアクセスは443にリダイレクトするように設定する。

参考)SSL with Docker Swarm, Let's Encrypt and Nginx

ステップ1: Let’s Encrypt 証明書の発行

ホストOS上で 

$ docker run --rm -p 443:443 -p 80:80 --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly -n -m "メールアドレス" -d ドメイン・サブドメイン --standalone --agree-tos

見やすくすると。

docker run --rm -p 443:443 -p 80:80 
                   --name letsencrypt 
                   -v "/etc/letsencrypt:/etc/letsencrypt" 
                   -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly
                   -n -m "メールアドレス" 
                   -d sampledomain.com 
                   -d www.sampledomain.com 
                   -d sub1.sampledomain.com 
                   --standalone --agree-tos

実行すると、

[XXXX@XXXX ~]$ docker run --rm -p 443:443 -p 80:80 --name letsencrypt -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly -n -m "メールアドレス" -d ドメイン・サブドメイン --standalone --agree-tos
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for ドメイン・サブドメイン
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/ドメイン・サブドメイン/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/ドメイン・サブドメイン/privkey.pem
   Your cert will expire on 2017-12-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

キーが以下のようにホストOSに出来上がり、証明書が発行される。
・/etc/letsencrypt/live/ドメイン・サブドメイン/fullchain.pem
・/etc/letsencrypt/live/ドメイン・サブドメイン/privkey.pem

ステップ2: Dockerの設定

docker-compose.yaml

# nginx-image

〜〜〜 略 〜〜〜
        ports:
            - "80:80"
            - "443:443"    <-- 追記
        volumes:
            - "./log:/var/log"
            - "./html/app:/usr/share/nginx/html"
            - "/etc/letsencrypt:/etc/letsencrypt"    <-- 追記

default.conf

server {
    # redirect from http to https
    listen 80;
    server_name  _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name ドメイン・サブドメイン;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /usr/share/nginx/html/public/;

    ssl_certificate     /etc/letsencrypt/live/ドメイン・サブドメイン/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ドメイン・サブドメイン/privkey.pem;
    ssl_protocols       TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html/;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location ~ /\.ht {
        deny all;
    }
}
$ docker-compose up

ブラウザで確認。

・ https でアクセスできれば成功
・ http でのアクセスが https にリダイレクトしていれば成功

ステップ3:証明書更新スクリプトの設置

証明書は90日で期限が切れる。更新(正確には作り直し)するスクリプトをつくり、cronに設定しておく。 期限が迫ってきた場合は更新処理が走り、余裕がある場合はなにもなく処理が終わる。

certbot.sh

#! /bin/bash

docker run --rm --name letsencrypt \  
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
    certbot/certbot:latest \
    renew --quiet \
    -n -m "メールアドレス"        # 追記: 2017/12/09 - しばらく経つと再度認証が必要

crontabはこんな感じで、毎日 0:19 と 12:19 に更新チェックをする。

19 0,12 * * * /bin/sh ~/certbot.sh >> ~/certbot.log 2>&1