Django + Channels + dephneをデプロイする方法

# Apache2などはASGIに対応しておらず、ASGIサーバーを内部に立てないといけない。

インターネット　－　Apache2　－　ASGIサーバー　という並びでやり取りする。

ASGIサーバーとしてchannelsが推奨しているのがdaphne（ダフネ）
DjangoのChannelは複数のインスタンス間で通信を必要とするため、Regisをインストールしておこう。

```
sudo apt-get install redis-server
```

また、最新版に変更するなら、[Redisのアップグレード](https://qiita.com/koji-dev/items/a4e7c49e3f3a61884cc8)を参照。

dapfneの特徴

 - LANのIPにはバインドできない。つまり、外部からの直接アクセスはできない様。

```
> daphne -b 0.0.0.0 -p 8001 yourproject.asgi:application
```

http://127.0.0.1:8001 (http://localhost:8001) にアクセスすると見える。

また、https用のASGIサーバーは、

```
> daphne -e ssl:8443:privateKey=yourkey.pem:certKey=yourcert.pem yourproject.asgi:application
```
で起動できる。

通常は、Apache2とDaphneは同じサーバー内で稼働するかと思われるので、その場合にはhttpで通信すればよい。

もしhttpsで通信したいのであれば、yourkey.pemとyourcert.pem を作成してSSLに対応できるようにしてください。


次に本番環境での話ですが、このままでは再起動などをしてくれないため、daphneをsupervisor上で動かすことにする。supervisorはデーモン（スレッド）監視プログラムなので、便利。supervisorのインストールは別途参照。

supervisorの設定だが、httpだと変巣numprocsの値を変更することにより、複数のインスタンスを作成することは簡単だったが、httpsだとあれこれやったが、１つのインスタンスしか動かすことができなかった。以下にsupervisorのconfを記載します。（私の場合、mail serverが、supervisor上で動いているので、ごちゃごちゃしていたらすいません。）

```/etc/supervisor/supervisord.conf
; supervisor config file

[unix_http_server]
file=/var/run/supervisor.sock   ; (the path to the socket file)
chmod=0700                       ; sockef file mode (default 0700)

[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisor/conf.d/*.conf
```

http用のconfファイル　（unix socketを使い、複数のデーモンを立ち上げることができるそうだ。numprocs=1しか試してないが。）

```/etc/supervisor/conf.d/daphne.conf
[fcgi-program:daphne]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8080

# Directory where your site's project files are located
directory=/home/gotodk1023/shopapp
user=gotodk1023

# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=/home/gotodk1023/.virtualenvs/venv_shopapp/bin/daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access>

# Number of processes to startup, roughly the number of CPUs you have
numprocs=1

# Give each process a unique name so they can be told apart
process_name=daphne%(process_num)d

# Automatically start and recover processes
autostart=true
autorestart=true

environment=PLACE="PROD_A2_AS1"
```
このとき、がっつり気を付けないといけないのは、/run/daphne/ディレクトリを作成し、アクセス権を777などに変更。これをしないと動かなかった。また、run/に追加したディレクトリやファイルは再起動時に消えるので、cronにて、再起動時に追加・権限変更を加えてやる。

```
crontab -e
```

最後の行に以下を追加

```
@reboot mkdir /run/daphne && chmod 777 /run/daphne
```

次に、httpsでの通信用のconfファイル

```/etc/supervisor/conf.d/daphne_ssl.conf
[program:daphne_ssl]

# Directory where your site's project files are located
directory=/home/gotodk1023/shopapp
user=gotodk1023

# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=/home/gotodk1023/.virtualenvs/venv_shopapp/bin/daphne -e ssl:8443:privateKey=/home/gotodk1023/local.key.pem:cer>

# Number of processes to startup, roughly the number of CPUs you have
numprocs=1

# Give each process a unique name so they can be told apart
process_name=daphne_ssl%(process_num)d

# Automatically start and recover processes
autostart=true
autorestart=true

environment=PLACE="PROD_A2_AS1"

```
[fcgi-program:daphne_ssl]では、動かなかったので、通常の[program:xxxxx]をしようした。この場合、複数のデーモンを立ち上げようとしたが、２つ目以降は常に起動と停止を繰り返したので、あきらめました。。。。すいません。

あと、テストでdaphneをsupervisorを使わずに動かしていると、Portが競合するのか、supervisorは立ち上がらないので、すべてのdaphneをKillしてからsupervisorを立ち上げるようにしてください。

```
service supervisor restart
service supervisor status
```


開発中に気を付けること（自分用）
　- frontendなどをreactなどで作っているときは、まずwebpack-serverなどで開発。
　- dephneサーバーを使用するときは、djangoのcollectstaticを忘れずにすること。dephneはpython manage.py runseverとは違い、アプリケーション内のフォルダを見に行ったりはしない。

# apache側の設定

まず、以下のモッドをアクティブにする必要がある。

proxy.load
proxy_http.load
proxy_wstunnel.load
（いらないのもあるかも。）

/etc/apache2/mods-available内に移動し、A2enmod modefilename.loadを実行する。

```
a2enmod rewrite
a2enmod proxy.load
a2enmod proxy_http.load
a2enmod proxy_wstunnel.load
```

次に、apache2のコンフィグファイルを変更する。virtualhost内を以下に変更する。
Port番号はご自分でお好きなのを選んでください。

``` yourfile.conf
MDomain shopapp.take-my-order.com
MDCertificateAgreement accepted

<VirtualHost *:443>

  SSLEngine on

  ServerName shopapp.take-my-order.com
  RewriteEngine on
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteCond %{HTTP:Connection} Upgrade [NC]
#  RewriteRule /(.*) wss://localhost:8443/$1 [P,L]  <= SSLなこちら
  RewriteRule /(.*) ws://localhost:8080/$1 [P,L]

#  SSLProxyEngine on　 <= SSLなこちら
#  ProxyPass / https://localhost:8443/　 <= SSLなこちら
#  ProxyPassReverse / https://localhost:8443/　 <= SSLなこちら
  ProxyPass / http://localhost:8080/
  ProxyPassReverse / http://localhost:8080/

</VirtualHost>

<VirtualHost *:80>

  ServerName shopapp.take-my-order.com

  RewriteEngine on
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteCond %{HTTP:Connection} Upgrade [NC]
  RewriteRule /(.*) ws://localhost:8080/$1 [P,L]

  ProxyPass / http://localhost:8080/
  ProxyPassReverse / http://localhost:8080/

</VirtualHost>
```
 
これで、このサブドメインのアドレスは、リバースプロキシサーバーのようなに、内部のポート番号8080のサーバーにアクセスするようになる。

ちなみに、SSL化をしなくても、apacheまではSSL、内部は非SSLで通信できているようだ。