VPSを借りて、CentOS＋Nginx＋uWSGIでWagtailをデプロイしてみた

## ■はじめに
ちょっと前からWagtailでものをちょこっと作っており、そろそろ公開したいなーと思ったときにまず思いついたのはHerokuでした。

[ここに動画](https://learnwagtail.com/tutorials/how-to-deploy-wagtail-to-heroku/)もあるしこれで楽勝だ～と思い、デプロイして、画像を管理画面から登録してみると何かおかしい。なにも表示されないのである。

調べてみると、DjangoをHerokuにデプロイすると、画像や動画といったMediaファイルが使えないといった記事がちらほら。代案として、Amazon S3を使う方法もあるらしい([こちら](https://wagtail.io/blog/amazon-s3-for-media-files/))

しかし、趣味レベルで従量課金制のものを使うのもちょっと気が引けたので、VPSでがんばるか～と思った次第です。

といってもWagtailをVPSにデプロイした話は日本語ではあんまり見つけられず、英語記事を参考にしてがんばってみたら見事に詰まってしまったので、前段として日本語記事が多いDjangoのデプロイをしてみました。それが↓↓
https://qiita.com/OcchiNecchi/items/9a6c8447c1a03ea3c842

なんとかDjangoはできたので、次はWagtailもやってみました！

内容はDjangoデプロイ時にまとめたものと被りがとても多いですが、がんばってまとめていきます！

もし、当該VPSにDjango等を入れたことがあり、設定が進んでいるのであれば、「デプロイ先ディレクトリ、仮想環境の作成」から、当該VPSがまっさらな状態であれば、最初から実施してください。

## ■前提
- CentOS 7.6
- VPSは契約済(この記事ではConohaVPS)

## ■構成
イメージとしては下記のようになる
Web Browser <--> Nginx <--> socket <--> uWSGI <--> Djnago(Wagtail) <--> SQLite

# ☆VPS契約したばかりでまっさら状態の場合はここから☆

## ■リポジトリを作成

下記コマンドでリポジトリを作成する

```CentOS:CentOS
# yum install -y https://centos7.iuscommunity.org/ius-release.rpm
```

> 2020月10月3日追記
> iuscommunity.orgのリダイレクトが2020-06-01に廃止されるため、上記ではエラーが発生するとのこと
> 代わりに下記コマンドを実行する。
> yum install -y https://repo.ius.io/ius-release-el7.rpm

きちんと作成されているか確認

```CentOS:CentOS
# yum install -y https://centos7.iuscommunity.org/ius-release.rpm
```

## ■Pythonをインストールする

Pythonをインストールし、エイリアスを登録しておく

```CentOS:CentOS
# yum install -y python36u python36u-libs python36u-devel python36u-pip
# alias puthon3='python3.6'
```

## SSH、firewallの設定
SSHのポート番号が22というのは広く知れ渡っているため、悪意のあるロボットの「無作為IPアドレス+22番ポート」
攻撃から身を守る必要がある。そのため、ポートを変えたほうが良いとのこと。

まず、firewallの起動と自動起動設定を行う。

```CentOS:CentOS
# systemctl start firewalld.service
# systemctl enable firewalld
# systemctl status firewalld
```

次に、http、https、sshでの外部アクセスを許可する。また、80も空けておく。

```CentOS:CentOS
# firewall-cmd --permanent --add-service=http
# firewall-cmd --permanent --add-service=https
# firewall-cmd --permanent --add-port=xxxxx(任意のポート番号)/tcp
# firewall-cmd --permanent --zone=public --add-port=80/tcp

# systemctl restart firewalld
```
/etc/ssh/sshd_configファイルを編集する。

```CentOS:CentOS
# vi /etc/ssh/sshd_config

...略...
#Port 22 ← デフォルトはポート番号22
Port 54321 ←【例】任意の空きポート番号を指定する
...略...
```

設定反映を行う。

```CentOS:CentOS
# service sshd restart
```

設定したポートでSSHで接続できるか確認する。

## SQLiteの最新化
後でDjangoを入れて、サーバーを起動すると、SQLiteのバージョンが古いとエラーが発生する。

```CentOS:CentOS
django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or later is required (found 3.7.17).
```

そのため、新しいSQLiteを入れてあげる必要がある。

まず、最初はCのコンパイラが入ってないので入れてあげる。

```CentOS:CentOS
# yum -y install gcc
```

SQLiteのソースを取得、ビルドしてインストールまで行う。

```CentOS:CentOS
# wget https://www.sqlite.org/2019/sqlite-autoconf-3290000.tar.gz
# tar zxvf ./sqlite-autoconf-3290000.tar.gz
# cd ./sqlite-autoconf-3290000
# ./configure --prefix=/usr/local
# make
# make install
# find /usr/ -name sqlite3
```

不要なファイルを削除する。

```CentOS:CentOS
# cd ..
# rm -rf ./sqlite-autoconf-3290000 ./sqlite-autoconf-3290000.tar.gz
```

新しいSQLiteを適用する。

```CentOS:CentOS
# mv /usr/bin/sqlite3 /usr/bin/sqlite3_old
# ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3
# echo 'export LD_LIBRARY_PATH="/usr/local/lib"' >> ~/.bashrc
# source ~/.bashrc
```

下記でバージョンを確認すると、新しくなっていることが確認できる。

```CentOS:CentOS
# sqlite3 --version
```

## ■nginxを入れる

下記コマンドでインストールする。

```CentOS:CentOS
# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# yum install nginx -y
```

# ☆Djangoでデプロイしたことがあるならここから☆

## ■デプロイ先ディレクトリ、仮想環境の作成
今回は/var/www/配下にいろいろ作っていきます。

```CentOS:CentOS
// デプロイ先ディレクトリ作成
# mkdir -p /var/www/wagtail_mysite

// 仮想環境の作成
# cd /var/www/wagtail_mysite
# python3 -m venv myvenv

// 仮想環境を有効化
# source myvenv/bin/activate
```

## ■パッケージをインストール

pipで必要なパッケージをインストールする。

```CentOS:CentOS
// pipを更新
(myvenv)# pip install --upgrade pip

// 仮想環境にWagtailをインストール
(myvenv)# pip install wagtail

// 仮想環境にuWSGIをインストール
(myvenv)# pip install --upgrade uwsgi

// 一旦仮想環境を無効にする
(myvenv)# deactivate
```
Wagtailプロジェクトも作成しておく。

```CentOS:CentOS
(myvenv)# wagtail start mysite

// 一旦仮想環境を無効にする
(myvenv)# deactivate
```

## ■uWSGIの設定
socketファイルとpidファイルを格納するディレクトリを作成し、所有者や権限を変更する。

```CentOS:CentOS
// ディレクトリ作成
# mkdir -p /var/run/uwsgi

// 所有者変更
# chown root:nginx /var/run/uwsgi

// 権限変更
# chmod +w /var/run/uwsgi
```


先ほど作成した仮想環境myvenv配下にuWSGIのための変数を定義するファイルuwsgi_paramsを作成する。

```CentOS:CentOS
// 移動
# cd /var/www/wagtail_mysite/myvenv

// ファイル作成
# vi uwsgi_params
```

```bash:/var/www/wagtail_mysite/myvenv/uwsgi_params
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;
```

同じくmyvenv配下にuwsgi.iniファイルを作成する。

```CentOS:CentOS
// 移動
# cd /var/www/wagtail_mysite/myvenv

// ファイル作成
# vi uwsgi.ini
```

```bash:/var/www/wagtail_mysite/myvenv/uwsgi.ini
[uwsgi]
uid = nginx
gid = nginx

# 作成したWagtailプロジェクトのルートを指定する
chdir = /var/www/wagtail_mysite/mysite

# wsgi.pyの場所を指定する
# (Wagtailのプロジェクト名を「mysite」にするとmysite/配下にwsgi.pyがあるはず)
module = mysite.wsgi

# 仮想環境の場所を指定する
home = /var/www/wagtail_mysite/myvenv

master = true
processes = 2
threads = 1

# 先ほど作成したsocketとpidファイルの作成場所を指定する
socket = /var/run/uwsgi/master.sock
pidfile = /var/run/uwsgi/master.pid

chmod-socket = 666
vacuum = true
thunder-lock = true
max-requests = 6000
max-requests-delta = 300

# log
logto = /var/log/uwsgi/uwsgi.log
deamonize = /var/log/uwsgi/uwsgi-@(exec://date +%Y-%m-%d).log
log-reopen = true
```

サーバーを再起動したときにuWSGIが自動で起動するように[/etc/systemd/system/]配下にuwsgi.serviceを作成する。

```CentOS:CentOS
// 移動
# cd /etc/systemd/system

// ファイル作成
# vi uwsgi.service
```

```CentOS:/etc/systemd/system/uwsgi.service
# uwsgi.service
[Unit]
Description=uWSGI
After=syslog.target

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /var/run/uwsgi; chown root:nginx /var/run/uwsgi; chmod g+w /var/run/uwsgi;'
# 自分が作成した仮想環境配下のactivateとuwsgi.iniファイルを指定する。
ExecStart=/bin/bash -c 'source /var/www/wagtail_mysite/myvenv/bin/activate; uwsgi --ini /var/www/wagtail_mysite/myvenv/uwsgi.ini'
#Restart=always
Restart=on-failure
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target
```

サービスの自動起動をONにする。

```CentOS:CentOS
// サービスの停止
# systemctl stop uwsgi

// サービスの自動起動の有効化
# systemctl enable uwsgi

// サービスの開始
# systemctl start uwsgi
```

## ■nginxの設定

https://qiita.com/si-masuda/items/6df2b19dfae5bef107a8
を参考にさせていただきました。

同一サーバーで複数のアプリケーションを運用することも想定し、バーチャルホストの設定を行う。

まず、[/etc/nginx/sites-available]と[/etc/nginx/sites-enabled]を作成する。

```CentOS:CentOS
// 設定ファイルを格納するディレクトリを作成する。
# mkdir /etc/nginx/sites-available

// 有効にしたいバーチャルホストの設定ファイルへのシンボリックリンクを格納するディレクトリ
# mkdir /etc/nginx/sites-enabled
```

[/etc/nginx/sites-available]配下に設定ファイルを作成する。

```CentOS:CentOS
// 移動
# cd /etc/nginx/sites-available

// ファイル作成(名前は任意)
# vi wagtail_mysite
```

```bash:/etc/nginx/sites-available/wagtail_mysite

upstream django {
    # 上記で設定したソケットファイルの場所を指定する。
    server unix:///var/run/uwsgi/master.sock;
}

# サーバの設定
server {
    # ポート番号
    listen      80;
    # VPSのIPアドレスを入力する
    server_name [IPアドレス];
    charset     utf-8;

    # Wagtailの静的ファイルの設定
    location /static {
        # staticディレクトリが存在する場所を指定する。
        root /var/www/wagtail_mysite/mysite;
    }

    location / {
        uwsgi_pass  django;
        # 上記で設定したuwsgi_paramsの場所を指定する
        include     /var/www/wagtail_mysite/myvenv/uwsgi_params;
    }
}
```

nginxが起動したときに[/etc/nginx/sites-enabled]配下を読み込むようにして、[/etc/nginx/sites-enabled]配下では[/etc/nginx/sites-available]の設定ファイルへのシンポリックリンクを張ったり削除することで、バーチャルホストの設定を有効にしたり、無効にしたりし、管理を楽にする。

上記で作成した設定ファイルのシンボリックリンクを[/etc/nginx/sites-enabled]に貼る。
ちなみに設定済みのシンボリックリンクが存在した場合はunlinkコマンドで削除してあげる

```CentOS:CentOS
// 有効にしたいバーチャルホストの設定ファイルへリンクを張る。
# ln -s /etc/nginx/sites-available/wagtail_mysite /etc/nginx/sites-enabled/wagtail_mysite
```

[/etc/nginx/]配下にあるnginx.confを修正し、[/etc/nginx/sites-enabled]を見るようにする。

```CentOS:/etc/nginx/nginx.conf
http {
    ...
     #gzip  on;
+    include /etc/nginx/sites-enabled/*;
     include /etc/nginx/conf.d/*.conf;
     ...
}
```

OSを再起動してもnginxを自動で起動するようにする。[/etc/systemd/system/]配下にnginx.serviceを作成する。

```CentOS:/etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```

サービスの自動起動をONにする。

```CentOS:CentOS
// サービスの停止
# systemctl stop nginx

// サービスの自動起動の有効化
# systemctl enable nginx

// サービスの開始
# systemctl start nginx
```

## ■Wagtailの設定
Wagtailのマイグレーション等を行う

```CentOS:CentOS
# cd /var/www/wagtail_mysite

# source myvenv/bin/activate

(myvenv)# cd mysite

// マイグレーションを行う
# python manage.py migrate

// スーパーユーザーを作成する
python manage.py createsuperuser
```

静的ファイルを下記コマンドで集める

```CentOS:CentOS
(myvenv)# python3 manage.py collectstatic
```

## ☆これでアクセスできるようになるはず

VPSのIPアドレスで接続すれば、Wagtailのページが出てくるはず。
もし、エラーが出た場合は、nginxのログファイル(/var/log/nginx/error.log)やuWSGIのログファイル(/var/log/uwsgi/uwsgi.log)を確認してみる。

### unable to open database file と出てくるとき
SQLiteが開けないと怒られるエラー。SQLiteは、データベースファイルへの書き込み権限だけでは無く、ディレクトリにも書き込み権限が無いとダメらしい。
そのため、権限を見直すと解決する。

### SQLite 3.8.3 or later is requiredと出てくるとき

上でSQLiteを新しくして、python manage.py runserverでは普通に動くのに、ブラウザからアクセスすると上記のエラーで怒られた。
原因はさっぱりわからなかったので、怒られてる該当箇所を書き換えた。趣味レベルだったらこれでいいかなと。

怒られてるファイル(/var/www/wagtail_mysite/myvenv/lib64/python3.6/site-packages/django/db/backends/sqlite3/base.py)を編集する。

```CentOS:base.py
・・・略・・・
def check_sqlite_version():
    # if Database.sqlite_version_info < (3, 8, 3):
    if Database.sqlite_version_info < (3, x, x):
        raise ImproperlyConfigured('SQLite 3.8.3 or later is required (found %s).' % Database.sqlite_version)
・・・略・・・
```

## ☆まとめ
Djangoをデプロイしたときとやったことがかなり被っていますが、なんとかWagtailもデプロイできました。あとはローカルで作った資材をFTPツールで配置してあげればいいのかなと

## ☆参考文献
1、https://www.rosehosting.com/blog/install-wagtail-on-centos-7/#6-Create-a-python-virtual-environment-and-your-Wagtail-project
2、https://kodak-ism.com/how-to-release-django-app-on-centos7-and-nginx/