DjangoをVPSにデプロイする7〜SSL・IP拒否・http/2編〜

DjangoをVPSにデプロイする6〜Gunicorn編〜の続きです。

この記事ではサイトをSSL化、IPアドレスでのアクセスを拒否、http/2化する設定を行います。

前提

まだ以下の用意・設定ができてない場合は済ませてから進みましょう!

  • 独自ドメイン取得済み
  • DNSにAレコード追加
  • ALLOWED_HOSTSにexample.com追加済み

Certbot

SSL化するために「Let’s Encrypt」を導入しますが、certbotを使えば簡単にSSL化することができ、自動で更新してくれます。

ここから先は、certbot公式の手順に従って進めますので、気になる方は公式ドキュメントも覗いてみてください。OSやWebサーバーを指定するとそれに対応した手順が表示されます。

1. SSH接続

SSH接続します。

$ ssh COMAND_NAME

2. snapdの確認

最新のubuntuにはデフォルトで入っているのでチェックします。

$ sudo snap install core; sudo snap refresh core

3. Certbotのアンインストール

もし、snapd以外(apt等)でCertbotをインストールしている場合は一度アンインストールします。まだCertbotをインストールしていない方は、この手順は必要ないので次に進んで下さい。

$ sudo apt remove certbot

4. Certbotのインストール

snapdを使ってcertbotをインストールします。

$ sudo snap install --classic certbot

5. コマンドの確認

certbotコマンドを実行できるか確認します。シンボリックリンクを作成しています。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

6. 証明書の発行

証明書取得の際、Nginxを自動で設定するか、手動で設定するかでコマンドが変わります。

自動で設定する場合

Nginxの設定が自動で書き込まれるので、自動でやりたい方はバックアップ等の対応をしておいた方が良いかもしれません。書き込みの際、差分が表示されると思うのでちゃんと見ておきましょう!

# 自動で設定する場合
$ sudo certbot --nginx

手動で設定する場合

手動で設定する場合「/etc/nginx/nginx.conf」が変更されると思います。

この記事では手動で設定する方法をベースに書いています。

$ sudo certbot certonly --nginx

実行すると、メールアドレスや証明書を発行するドメインを聞かれます。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): メールアドレスを入力

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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

Account registered.
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): example.com, www.example.com

三番目は「No」と答えていますが、これは支援等のメルマガを送って良いか聞かれているのでNoにしました。

必要な方は「Yes」にしても問題ありません。

最後に証明書を発行するドメインを聞かれるので、「example.com」「www.example.com」を入力します。wwwが必要無い方はexample.comだけでOKです。

成功すると以下のようなメッセージがでます。

Successfully received certificate.
Certificate is saved at:
    /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:
    /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2023-02-06.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

証明書は「/etc/letsencrypt/live/example.com/fullchain.pem」に保存されています。

Keyは「/etc/letsencrypt/live/example.com/privkey.pem」に保存されています。

最後の行には自動更新しますよ〜と書いてあります。

7. 自動更新ができるかテスト

$ sudo certbot renew --dry-run

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for example.com and www.example.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: 
  /etc/letsencrypt/live/example.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

successとなっていたら証明書が自動的に更新されるようになっています。


nginx.confの修正

手動で設定する選択をしたのでNginxのファイルも手動で対応していきます。

先程certbotが変更してしまった部分を修正します。

$ vi /etc/nginx/nginx.conf
- user nginx;
+ user root;

あとは、自身に必要なconfファイルがincludeされているか確認してください。これは「conf.d」と「sites-enabled」どちらでconfファイルを作成したかで変わります。

  • include /etc/nginx/conf.d/*.conf;
  • include /etc/nginx/sites-enabled/*;

プロジェクト名.confの修正

「SSL化」「IPアドレスでのアクセス拒否」「http/2」の設定を追加します。

自身のプロジェクト名.confのファイルを編集します。以下のどちらかのコマンドになると思います。

$ sudo vi /etc/nginx/conf.d/プロジェクト名.conf

$ sudo vi /etc/nginx/sites-available/プロジェクト名.conf

中身を次のように追加・変更します。

# IPアドレスでのアクセスを拒否
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    listen 443 default_server;
    listen [::]:443 default_server;
    ssl_reject_handshake on;

    server_name _;
    return 444;
}

# SSLでない場合は、SSLにリダイレクト
server {
    listen 80;
    listen [::]:80;
    server_name .example.com;
    return 301 https://$host$request_uri;
}

# ssl、http2、証明書、keyの追加
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name .example.com;

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

    location /static {
        alias /usr/share/nginx/html/プロジェクト名/static;
    }

    location /media {
        alias /usr/share/nginx/html/プロジェクト名/media;
    }

    location /favicon {
        empty_gif;
        access_log    off;
        log_not_found off;
    }

    location / {
        proxy_pass http://unix:/home/shiraishi/プロジェクト名/プロジェクト名/プロジェクト名.sock;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

これでhttpsで接続できるようになったはずです。

「https://ドメイン」にアクセスしてみてください。

もしエラーがでたらエラーログを確認して修正しましょう。

$ sudo less /var/log/nginx/error.log

これでSSL・IP拒否・http/2編は終了です!

次は「DjangoをVPSにデプロイする8〜Email編〜」です。