nyanpyou Note

主な目的は調べたり作ったりしたプログラミング備忘録(予定)

衝動的にLightsailとDjangoでWebサイトを作る その5

前回からの続き。

nyanpyou.hatenablog.com

構成(再掲)

デプロイしたはいいがデータベースにアクセスできない

データベースからレース情報を取ってくる機能が動作しない。ローカルでは問題なく動くため、恐らく設定がおかしいのだろうと予想し、確認する。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'database_name',
        'USER': 'username,
        'PASSWORD': 'password',
        'HOST': '',
        'PORT': '',
    }
}

settings.py内データベースに関する設定部分で、HOSTとPORTをいずれも空白(ローカルホスト)に設定すると動作するようになった。
今回は簡略化のため、データベースとDjangoアプリを同一サーバーに配置している。当然、開発環境では外部からデータベースへ、本番環境では自分自身に入っているデータベースへアクセスすることになるため、開発環境の設定のままでは動かない。
MySQLで用いる3306ポートを、ファイアウォールでIP制限していたことも原因と思われる。(IP制限を解除した上で開発環境設定を用いるテストはしていないので、正しいかは不明。)
単純な見落としだが注意する。

settings.pyを開発環境と本番環境で切り替える

開発環境と本番環境でいちいちsettings.pyを書き換えるのは手間なので、2種類の設定ファイルを用意し、使い分ける。
開発用の設定ファイルとしてsettings_develop.pyを用意した場合、開発用のローカルサーバーを立ち上げる際 、

manage.py runserver --settings projectname.settings_develop

とすることで読み込む設定ファイルを変更できる。

デプロイしたDjangoアプリにCSSを適用する

Djangoは開発環境そのままではCSS等の静的ファイルが配信できないので、本番環境でCSSが適用されるように準備。
settings.pyの最下部に

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

と追記した後、

python manage.py collectstatic

を実行すると、全ての静的ファイルをmanage.pyと同階層の/staticに本番環境用として集めてくれる。
しかし、これを実行後再度サーバーにデプロイしたものの、/static内のファイルにアクセスするとforbiddenが返されるようで、まだCSSが適用されない。
チュートリアルも含めてよくよくコードを見ると、staticのエイリアスの指定が間違っていたことが判明。

Alias /static/ /home/ubuntu/dir_name/project_name/static/  

にすると読み込めた。最後の/、忘れちゃダメ。

qiita.com

qiita.com

HTTPSに対応させる

Webアプリのデプロイが完了したので、最後にHTTPSでの接続を可能にしたい。
今回はLet's encryptを使って無料でHTTPS化を試みる。
Let's encryptは非営利団体のInternet Security Research Group(ISRG)により運営されている証明書認証局。主要なスポンサーは電子フロンティア財団(EFF)、Mozilla Foundation、アカマイ・テクノロジーズ、OVH、シスコシステムズFacebookGoogle ChromeInternet Society。(Wikipediaより)

ドメインの取得

まず、以下の記事を参考にAmazon Route 53でドメインを取得。

dev.classmethod.jp

取得ドメインはumamusume-database.netとした。
2021年5月時点で.netドメインの料金は年間1200~1500円くらい。
個人開発のため、ドメイン登録時にWhois Privacy Serviceを有効にしておいた。これを有効にしておくと、Whoisの情報がAWSのものに置き換わり、個人情報が載らなくなる。

f:id:nyanpyou106:20210611113143p:plain
個人情報を晒したくない場合は、連絡先の編集から忘れずに設定

次に、取得したドメインをサーバーのIPアドレスと紐づけるため、DNSレコードの作成を行う。Route 53は勿論この機能も提供しているのだが、高くはないもののお金がかかる。

料金 - Amazon Route 53 | AWS

実はLightsailでもDNSレコードを作成する機能は提供されており、しかも追加料金なし(但し作成できるDNSゾーンは最大3つ。各ゾーン毎のDNSレコード数は無制限。Amazon Lightsail に関するよくある質問を参照。)なので、Lightsailを使っている場合はこれを利用した方がお得。
よって今回はLightsail側で設定する。
以下の記事に沿ってLightsailでDNSゾーンとDNSレコードの作成を行い、その後Route 53でumamusume-database.net取得時に自動で作成されていたホストゾーンを削除。最後にumamusume-database.netのネームサーバーをLightsailで作成したDNSゾーンに更新する。

f:id:nyanpyou106:20210611141305p:plain
インスタンス一覧画面のネットワーキングタブからDNSレコードを設定

f:id:nyanpyou106:20210611143847p:plain
ネームサーバーをLightsail記載のものに更新する

qiita.com

qiita.com

LightsailでのDNSについて詳しい話は以下の公式ページ参照。

lightsail.aws.amazon.com

Certbotの導入と実行

Let's Encryptの公式ページでは、Certbotを使ってHTTPS対応を実現する方法が紹介されている。
Certbotとは証明書を自動的に発行・設定してくれるツールで、これ1つ動かすだけで自動的にWebページをHTTPSに対応させることができるらしい。 各環境毎の導入手順も用意されているので、そちらに従って作業を行う。

certbot.eff.org

手順に登場するsnapコマンドはsnappyを実行するコマンドで、snappyはソフトウェアパッケージの管理システム。snappyで管理されるソフトウェアパッケージの形式をsnapと呼び、このパッケージはLinuxディストリビューションを問わず動作するらしい。今回使用しているUbuntu20.04.2にはsnappyは元から入っていた。
指示に従って

sudo certbot --apache

を実行したが、

Unable to find a virtual host listening on port 80 which is currently needed for Certbot to prove to the CA that you control your domain. Please add a virtual host for port 80

とエラーが出て止まった。どうもApacheの設定ファイルにVirtualHostの設定が無いと駄目みたいなので、Apacheの.confファイルにVirtualHostの設定を追加しようと試みた…が上手く動かない。 試行錯誤の過程をメモし忘れたため、何を参考にしたかの情報が一切残っていないが、とにかく同じエラーが出続けた。

しばらく悩むことになったが、

www.kantenna.com

を参考に、とりあえず元々の.confファイルに<VirtualHost *:80></VirtualHost>とServerNameだけ追記した状態で実行してみたところ、エラーの内容が変化した。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Error while running apache2ctl configtest.
Action 'configtest' failed.
The Apache error log may have more information.

AH00526: Syntax error on line 9 of /etc/apache2/sites-enabled/django.conf:
WSGIPythonPath cannot occur within <VirtualHost> section

The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError("Error while running apache2ctl configtest.
Action 'configtest' failed.
The Apache error log may have more information.

AH00526: Syntax error on line 9 of /etc/apache2/sites-enabled/django.conf:
WSGIPythonPath cannot occur within <VirtualHost> section")

このようにどこが悪いかCertbotが明確に教えてくれるようになったので、その通り書き方を変えたら動くようになった。
どうやらWSGIPythonPathとWSGIPythonhomeは<VirtualHost *:80></VirtualHost>の中に入れてはいけなかったらしい。
正常に実行できると、以下の通りに処理が進んだ。

#一部変更またはマスクしています
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: umamusume-database.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Requesting a certificate for umamusume-database.net
Performing the following challenges:
http-01 challenge for umamusume-database.net
Enabled Apache rewrite module
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/django-le-ssl.conf
Enabled Apache socache_shmcb module
Enabled Apache ssl module
Deploying Certificate to VirtualHost /etc/apache2/sites-available/django-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/django-le-ssl.conf
Enabled Apache rewrite module
Redirecting vhost in /etc/apache2/sites-enabled/django.conf to ssl vhost in /etc/apache2/sites-available/django-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://umamusume-database.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/...
   Your key file has been saved at:
   /etc/letsencrypt/...
   Your certificate will expire on 2021-XX-XX. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the "certonly" option. 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

これで晴れてHTTPS対応が完了。試してみたところ、HTTPで接続を試みた場合も、HTTPSで接続されるように自動で設定してくれているようだった。

f:id:nyanpyou106:20210611154633p:plain
しっかり証明書が表示されている

終わりに

全5回に分けて衝動的にLightsailとDjangoでWebサイトを作った過程とその際に遭遇した問題について投稿しました。
同じ状況で困った方の参考になる部分があれば幸いです。

今回も1~5まで全部合わせると結構な分量になった(もっと細かい内容で書いてないこともあるにもかかわらず)ので、今までの一気に書き上げて投稿するスタイルよりも、適度な所で切って小分けに投稿するスタイルの方が、書く自分としても読んでくれる人の側からしても良さそうな気がする。検索もしやすいし。

次何を書くか、何を作るか相変わらず何も決まっていませんが、人の役に立つものが思いつくことを祈ります。
転職については不安しかない。仕事下さい。