自宅サーバ用ラズパイでPythonでLINE bot(HTTPS化)をつくる(heroku, ngrok使わない) Apache(+wsgi)+Flask(Djangoでも同じ？)

# はじめに
何もかも初心者なので設定に９割の時間を使いました...
設定は具体的には、

* PythonでWeb公開する
* それをSSL化

の２つです。
こちらはブラウザで`https://<domainname>/testFlask`で、pythonで書いた"Hello Flask!"が見れるようにすることです。
これさえできればLINE APIのWebhook URLにはっつければLINE botはできます。
後はherokuなりngrok使った他の記事を参考にしていただければと思います。

# スキーム

![schematic_view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418672/5a7a8b06-2120-6383-fe2b-6e2aba672b1d.png)

上図のように、PHPで書こうとするとApacheだけでいいんですが、Pythonで書きたかったのでwsgiというモジュールを使いました。
https://qiita.com/lamplus/items/9877849d3108e2c6d0df

###使ったモジュール、サービス

* Apache2
* LINE API
* wsgi
* Flask(Pythonのモジュール)
* Let's encrypt(SSL証明書発行の無料サービス)

### ディレクトリ構成

```
/etc/
 |---apache2/
 |       |---ports.conf
 |       |---sites-available/
 |                |---flask.conf(新規作成)
 |
 |---letsencrypt
 |       |-...
 |       ...
 |
 |
/home/
 |---t13m082h/
         |---ExampleFlask
                |---my_flask_app.py (my_flask_app.wsgiでこれをimportする)
                |---my_flask_app.wsgi (flask.confでこれを読み込ませる)

```



#　各モジュール、サービスのインストールは他記事参考に

Apache

```
# apt-get
$ sudo apt-get install apache2
```
wsgi + Flask

```
$ sudo apt-get install libapache2-mod-wsgi-py3 python-dev
$ pip install flask
$ pip install mod_wsgi
```

Let's encrypt
https://piguide.dev/2019/03/13/raspberry-pi-ssl-certificates-using-lets-encrypt.html

# Flaskで書いたページをWeb公開

エラーのlogは常に

```
$ sudo cat /var/log/apache2/access.log
$ sudo cat /var/log/apache2/error.log
```
で確認。(設定は後述)

### ポート設定
HTTPリクエストを受け付けるのはApacheだが、特定のListenしているポートにきたリクエストをwsgiで処理している。
まず、Listenしているポートを設定。
ポートの設定ファイルは `/etc/apache2/ports.conf`にまとめられている。

```:/etc/apache2/ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80
Listen 8000

<IfModule ssl_module>
	Listen 443
	Listen 4443
</IfModule>

<IfModule mod_gnutls.c>
	Listen 443
	Listen 4443
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

```
wsgi用に新しく4443番ポートを使用(ルータ設定のポートフォワーディングの設定も忘れずに)
これで4443番ポートに来たHTTPリクエストを受け付けることができるようになった。
ちなみに、ポート番号を変更したい時は

* /etc/apache2/ports.conf
* /etc/apache2/sites-available/flask.conf
* ルータのポートフォワーディング

の３箇所の変更が必要。

### wsgi設定
設定ファイルは`/etc/apache2/sites-available`ディレクトリのconfファイル。
全部の設定後のファイルの中身は以下。(SSL証明書の設定も入っているので一部読み飛ばしてください)
confファイル書き方
https://pawelzny.com/server/django/2018/02/26/the-most-complete-apache2-config-for-wsgi-django-and-drf/


```:/etc/apache2/sites-available/flask.conf
(t13m082h は username)
<IfModule mod_ssl.c>
<VirtualHost *:4443>
     # Add machine's IP address (use ifconfig command)
     #ServerName <domain name>
     # Give an alias to to start your website url with
     WSGIScriptAlias /testFlask /home/t13m082h/ExampleFlask/my_flask_app.wsgi
     <Directory /home/t13m082h/ExampleFlask>
     		# set permissions as per apache2.conf file
            Options FollowSymLinks
            AllowOverride None
            Require all granted
     </Directory>

     ErrorLog ${APACHE_LOG_DIR}/error.log
     LogLevel warn
     CustomLog ${APACHE_LOG_DIR}/access.log combined

     SSLEngine on
     Include /etc/letsencrypt/options-ssl-apache.conf
     SSLCertificateFile /etc/letsencrypt/live/<domain name>/fullchain.pem
     SSLCertificateKeyFile /etc/letsencrypt/live/<domain name>/privkey.pem
</VirtualHost>
</IfModule>
```

設定見る限り、ここの

```
WSGIScriptAlias /testFlask /home/t13m082h/ExampleFlask/my_flask_app.wsgi
```
でAapacheからwsgiへ受け流しています。
https://<domain name>/testFlaskでアクセスできます。

### .pyファイル

```python:my_flask_app.wsgi
# /home/bin/python

import logging
import sys

logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, '/home/t13m082h/ExampleFlask/')

from my_flask_app import app as application

```

```python:my_flask_app.py
# coding: utf-8
from flask import Flask

app = Flask(__name__)

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

if __name__=="__main__":
    app.run()
```
そして先程の、エラーログの設定はこちらです。

```
     ErrorLog ${APACHE_LOG_DIR}/error.log
     LogLevel warn
     CustomLog ${APACHE_LOG_DIR}/access.log combined
```

# HTTPS化
SSL署名書の発行は[こちら](https://pawelzny.com/server/django/2018/02/26/the-most-complete-apache2-config-for-wsgi-django-and-drf/)で終わっている前提とします。
つまり、`/etc/letsencrypt/live/<domain name>/`ディレクトリに証明書が置いてあること。
前述しましたが既にLet's encryptで443番ポートをSSL化していたので、4443番ポートで待機し、`https://<domain name>/testFlask`を`/home/t13m082h/ExampleFlask`へリダイレクトしている。
先程の`flask.conf`ファイルのこちらにて設定。

```
     SSLEngine on
     Include /etc/letsencrypt/options-ssl-apache.conf
     SSLCertificateFile /etc/letsencrypt/live/<domain name>/fullchain.pem
     SSLCertificateKeyFile /etc/letsencrypt/live/<domain name>/privkey.pem
```

## Document root 変える場所

* `/etc/apache2/sites-available`の`WSGIScriptAlias`と`<Directory>`
* `my_flask_app.wsgi`の`sys.path.insert()`

# 他のモジュール、サービスのメモ
### ngrok(エヌジーロック) ⇔ Let'script + 独自ドメイン + wsgi(ウィスギー)
ngrok使うと８時間で切れてしまう
８時間毎に起動し直すスクリプト書いてもいいが、毎回URLが変わってしまうのでLINE APIの設定のWebhook URLも毎回直さなければいけないのがだるい。
### heroku(ヘロク)  ⇔ 自宅サーバ(Raspberry Pi) + wsgi(ウィスギー)
無料では月に１０００時間しかサーバ稼働させられないので、稼働させたいWebアプリケーション増えた時に課金しなければいけない。

### nginx(エンジンエックス) ⇔ apache
Apacheを元々使っていたのと、自分用のサーバなのでたくさんアクセスもないのでApacheで十分。

### Django(ジャンゴ) ⇔ Flask
Flaskの方が軽いらしいので。

# 参考URL

https://qiita.com/okoppe8/items/0f67753706cdc11ff1cd
https://qiita.com/lamplus/items/9877849d3108e2c6d0df
https://www.codementor.io/abhishake/minimal-apache-configuration-for-deploying-a-flask-app-ubuntu-18-04-phu50a7ft
https://teratail.com/questions/78671 
https://blue-black.ink/?p=4601