Let’s Encrypt で nginx に HTTPS を設定 (TLS 証明書を発行)

スポンサーリンク

Let's Encrypt とは

Let's Encrypt とは、TLS 証明書を無料で発行する証明書認証局です。

Let's Encrypt の認証局を利用して TLS 証明書を発行し、 nginx の HTTPS を有効化するためには、certbot と呼ばれるツールを利用します。

nginx って何?という方は以下の記事をご覧ください。

ネットワークの基礎①

ネットワークの基礎②

スポンサーリンク

Let's Encrypt (certbot) の使い方

Let's Encrypt (certbot) を利用する前提条件は以下のとおりです。

  • nginx が稼働している
  • 証明書を発行するドメイン名が nginx のホストに名前解決できる

名前解決って何?という方については、以下の記事をご覧ください。

事前準備

利用する OS は Amazon Linux 2 です。

sudo amazon-linux-extras install nginx1 -y
sudo vim /etc/nginx/nginx.conf

server_name ディレクティブで TLS 証明書を発行するドメイン名を指定します。(ドメイン名 (example.com) は、あなたのドメイン名に置き換えてください

    server {
        listen       80;
        listen       [::]:80;
        #server_name  _; #変更前
        server_name  example.com;#変更後
sudo systemctl start nginx

certbot のインストール

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
sudo yum install -y certbot python-certbot-nginx

certbot で Let's Encrypt から TLS 証明書を発行・設定

以下の certbot のコマンドで TLS 証明書の発行から、nginx の設定までが自動で行われます。

nginx の設定ファイルを手動で変更したい場合は、代わりに「sudo certbot certonly --nginx」コマンドを利用します。

sudo certbot --nginx --agree-tos
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): hoge@foo.bar(#メールアドレス)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N (#あなたにメール送りたいけどいい?)

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1(#HTTPS 化する server_name の番号を選択)

動作確認

アクセスするドメイン名は発行した証明書のドメイン名に置き換えてください。

curl https://example.com -I
HTTP/1.1 200 OK

Let's Encrypt の TLS 証明書を自動更新

cron を利用して、TLS 証明書の更新コマンド「certbot renew --no-self-upgrade」を自動で実行します。

sudo vim /etc/crontab
0      12    *       *       *       root    certbot renew --no-self-upgrade
sudo systemctl restart crond
スポンサーリンク

Docker + Let's Encrypt + nginx

Docker を利用した Certbot では、nginx に手動で証明書をインストールする必要があります。

Because Certonly cannot install the certificate from within Docker, you must install the certificate manually according to the procedure recommended by the provider of your webserver.

https://eff-certbot.readthedocs.io/en/stable/install.html#running-with-docker

そのため、/etc/nginx/nginx.conf に HTTPS の設定を手動でする必要があり、面倒です。

そこで、Certbot と https-portal の2つの方法を紹介します。

Certbot 証明書を取得

export DOMAIN=example.com

赤線箇所は自身のドメイン名に置き換えてください。

version: "3"
services:
  nginx:
    image: nginx:alpine
    restart: always
    container_name: nginx
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - html:/usr/share/nginx/html/
    ports:
      - "80:80"

  certbot:
    image: certbot/certbot:v1.7.0
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - html:/usr/share/nginx/html/
    depends_on:
      - nginx
    entrypoint: ["certbot", "certonly", "-d $DOMAIN", "-m hoge@foo.bar", "--agree-tos","--webroot", "-w","/usr/share/nginx/html/"]

volumes:
  html:
test_certbot_1 exited with code 0

exit status が 0 なら証明書作成が成功です。Ctrl + C でコンテナを終了します。
(既に /etc/letsencrypt に証明書がある場合は、docker-compose.yml で別のパスを指定してください。)

sudo ls /etc/letsencrypt/live/

https-portal で証明書の取得と HTTPS の設定

https-portal は、クライアントと HTTPS を行うプロキシです。

https-portal コンテナ側の nginx で HTTPS が終端します。
(nginx コンテナ側の /etc/nginx/nginx.conf を変更するわけではありません。)

export DOMAIN=example.com

赤線箇所は自身のドメイン名に置き換えてください。

version: "3"
services:
  nginx:
    image: nginx:alpine
    restart: always
    container_name: nginx
    ports:
      - "80"

  https-portal:
    image: steveltn/https-portal:1
    ports:
      - "80:80"
      - "443:443"
    links:
    - nginx
    restart: always
    environment:
      DOMAINS: "$DOMAIN -> http://nginx"
      STAGE: 'production'
      HSTS_MAX_AGE: 60 # 秒。次のアクセスから HTTPS を強制する
      CLIENT_MAX_BODY_SIZE: 10M # アップロード制限
    volumes:
      - /tmp/cert/:/var/lib/https-portal
https-portal_1  | [services.d] done.

「https-portal_1  | [services.d] done.」が表示されるまでしばらく待ちます。

curl "https://$DOMAIN"

別の端末で curl をする場合は、"$DOMAIN" 環境変数に、あなたのドメインが設定されていることを確認してください。

なお、証明書は「ホスト側:/tmp/cert/」、「コンテナ側:/var/lib/https-portal/」にあります。

参考資料

参考書籍

ネットワークの基礎①

ネットワークの基礎②

参考ページ

ドキュメント - Let's Encrypt - フリーな SSL/TLS 証明書
Let's Encryptは、非営利団体の Internet Security Research Group (ISRG) が提供する自動化されたフリーでオープンな認証局です。