Last Updated: 2/6/2024, 5:44:57 AM

# Flask を HTTPS 化する。

以下3つの起動方法について解説します。

  1. Flask で対応
  2. ウェブサーバ(WSGI対応)で対応
  3. ウェブサーバで対応

なお、この次のページで Heroku で SSL に対応させる方法を紹介します。 Heroku を使う場合は、基本的には、この方法しか使えません。

また CDN, Cloudflare で対応する方法もあります。

# 0. 事前準備

# 1. flask をインストールする。

flask をインストールします。

$ pip install flask

# 2. hello.py を用意します。

なおこのコードは、公式サイトのトップに出てくる 最も簡単なサンプルコードを元にしています (Flask) (opens new window)

#
# hello.py
#
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == '__main__':
    app.run()

# 3. 秘密鍵と証明書を用意します。

SSL 秘密鍵 privkey.pem と証明書 fullchain.pem を発行しているものとします。 一昔前は有料でしたが、今は無料で発行できます。

# 4. カレントディレクトリを確認します。

カレントディレクトリは以下のような構成になっているとします。

$ ls -l
fullchain.pem
hello.py
privkey.pem
$

# 1. Flask で対応

Flask で対応させる方法も2種類あります。

# 1.1. app.run()

発行させた秘密鍵と証明書を Flask に対応させる。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"


if __name__ == '__main__':
    #
    # Step 1.
    #   これを追記します。
    # 
    import ssl
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    ssl_context.load_cert_chain(
        'fullchain.pem', 'privkey.pem'
    )
    app.run(ssl_context=ssl_context)
$ #
$ # Step 2. コマンドを実行します。
$ #
$ python hello.py

ここから知りました。ありがとうございます。 こういうのどうやってやり方を見つけるんだろう...

# 1.2. flask run

$ FLASK_APP=hello.py
$ flask run --cert fullchain.pem --key privkey.pem

# 1.3. WSGI ってなに?

WSGI は別に知らなくても大丈夫です。でももし興味がありましたら、以下の動画がとても勉強になります。 WSGI を使って Flask そっくりなウェブアプリケーションを0から作っています。

# 2. ウェブサーバ(WSGI対応)で対応

# 2.1. gunicorn

gunicorn とは WSGI 対応ウェブアプリケーションです。 書式は以下の通りです。

$ pip install gunicorn
$ gunicorn hello:app --certfile fullchain.pem --keyfile privkey.pem

Flask オブジェクトが代入された変数名を指定します。 最初、この意味がわからなくて沈没してました。

$ gunicorn ファイル名:変数名 --certfile fullchain.pem --keyfile privkey.pem

# 2.2. uWSGI

# macOS の場合

uWSGI の方が gunicorn よりも高性能らしいです。 あまり、わかっていません。 普通に pip install すると https が使えません。

$ # 環境変数を設定して...
$ CFLAGS="-I/usr/local/opt/openssl/include"
$ LDFLAGS="-L/usr/local/opt/openssl/lib"
$ UWSGI_PROFILE_OVERRIDE=ssl=true
$ 
$ # インストール
$ pip install uwsgi -Iv
$
$ # 起動する。
$ uwsgi --https 127.0.0.1:5000,fullchain.pem,privkey.pem --module 'hello:app'

# Ubuntu の場合

インストールコマンドは以下を参照してください。起動コマンドは同じのはずです。

# 補足

普通に pip install uwsgi してしまうと --https オプションが有効になりません。

$ uwsgi --https 127.0.0.1:5000,fullchain.pem,privkey.pem --module 'hello:app'
uwsgi: unrecognized option `--https'
getopt_long() error
$

ただ CFLAGS, LDFLAGS が何を指しているかはわかりません。 いつか調べます。

# 2.3. gunicorn と uWSGI の比較

読んではいない...

# 3. ウェブサーバで対応

世の中には Apache と Nginx の二種類の有名なウェブサーバがあります。 最近は Nginx の方が流行りらしいです。この二種類の設定の仕方へのリンクのみ提示いたします。 自分でもやったことがないので、この辺はわかりません。

# 3.1. Apache

Apache は WSGI に対応していません。そのため mod_wsgi というモジュールを追加してあげて WSGI に対応させます。

Web サーバ側(Apache)で、解決する方法もあるみたい...

# 3.2. Nginx

Nginx-uWSGI や Nginx-gunicorn がどうやって通信してるかは、 あまりよくわかっていません。

Nginx と uWSGI は uwsgi というプロトコルを使って通信しているらしいです。 uWSGI には --http, --https, --socket というオプションがあります。 この --socket--http, --https の違いがよくわらない...

Ngnix は、正直言ってなんでこんなに、ガシガシ階層を積み込む感じなのかわからない。 パフォーマンス落ちちゃうんじゃないかな...

でも Nginx の方が流行りらしい... Apache よりは Ngnix の方がシェアがでかくなったらしい。 ちゃんと読まんとな...

# どこで HTTPS 化する?

色々な構成があるので、どこで HTTPS 化するのか疑問だったのですが、 安全なところまでは HTTP 通信を使っていいのかなと感じたりしています。

何を持って安全とするかは、よくわからないのですが。

基本的に HTTPS 通信は重いらしいです。 そのため不要であれば、サーバ間で HTTPS 通信は避けたい様な気もします。

# Flask が持っているサーバ

Flask は開発用のサーバを自分の中に持っています。app.run()flask run で起動できます。 公式ドキュメントはこちらから。

Flask は werkzeug というライブラリをメインに使って開発されています。 その werkzeug の中に run_simple という試験用のウェブサーバの関数があります。 これを動かしている気配があります。

ちなみに werkzeug の run_simple は Python の標準ライブラリである http.client (opens new window) から作っているようです。

# app.run() と flask run の違い

app.run() した時と flask run した時で、そんなに大きな違いはなさそうです。 ただ、若干挙動に違いがあります。

どう動きが変わってくるかと言うとは、パスが変わりす。 app.run() した時は「スクリプト」として実行されます。 flask run した時は「ライブラリ」として import された上で実行されます。

いつハマるかというと、もともと1つだったファイルを、複数に分割して使おうとすると import で盛大にハマります。

もし後々ファイルを分割することを検討している場合は、 flask run で起動して app.run() では起動しないことを、オススメしたいです。

ただ、import を書き換えれば、問題は解決するので、大した話ではないのですが。 色々調べた挙句 2, 3 万文字の記事になりました...

説明が悪くて伝わりづらいのですが、なんとなくの雰囲気だけ伝わればと思いました。

# おわりに

ここまで以下のように見てきました。

以上になります。ありがとうございました。