【初心者向け】さくらVPSで ubuntu - docker - apache2 - wsgi - flask 環境を作るまで、一通りやってみる。 

最近はやりのpythonを勉強し始めたので、まずは、環境構築からまとめました。

タイトルのままですが、さくらVPSを契約するところから、
Flask（Pythonフレームワーク）のテストページをWebで公開するまでです。

Pythonのチュートリアルというよりは、サーバー環境の構築よりかもしれません。

#（１）OSのインストール

さくらのVPS管理画面から、インストール

インストール形式：標準OS
OS：Ubuntu 16.04 amd64

スタートアップスクリプト：[public] Ubuntu_apt-get_update_upgrade

インストールが終わると「稼働中」になるとありますが、
アップグレードに時間がかかる場合があります。
管理画面、コンソールのVNCコンソールから、状況が確認できます。



#（２）vimのインストール

```
sudo apt install vim
```



#（３）SSHの設定

```
dpkg -l | grep openssh-server
```

で、openssh-serverがインストール済みか確認。

インストールされてなければ、

```
sudo apt install openssh-server
```

で、インストール

```
sudo vim /etc/ssh/sshd_config
```

・Portを任意の番号に変更
・PermitRootLogin は no に変更

```
sudo systemctl restart sshd
```

services の設定も変更する（やらなくても動きましたが・・・。）

```
sudo vim /etc/services
```

・SSHのポート番号を変更する

※この時点では、iptablesのせいで、新ポートで入れません。



#（４）iptables

**■iptablesの設定方法**
https://help.sakura.ad.jp/hc/ja/articles/206208121

**■ファイアウォールiptablesを簡単解説～初心者でもよくわかる！VPSによるWebサーバー運用講座(4)**
https://knowledge.sakura.ad.jp/4048/

```
sudo vim /etc/iptables/iptables.rules
```

参考サイトをもとに修正
SSHとHTTP（80）,HTTPS（443）を開けました。

iptablesの再起動
→やり方わからなかったので、サーバーごと再起動しました。



#（５）公開鍵暗号を用いてのSSH接続設定

**■公開鍵認証によるSSH接続 - Tera Termの使い方**
https://webkaru.net/linux/tera-term-ssh-login-public-key/

**■WinSCP の秘密鍵の設定方法**
https://synclogue-navi.com/winscp-privatekey#

Tera Termで、メニュー - SSH鍵生成
・デフォルト設定で生成
・パスフレーズは、空でもOK

秘密鍵と公開鍵をローカルに保存する。

Tera Termでサーバーに接続後、公開鍵をドラッグドロップ
「~/」と入力して「SCP」

```
mkdir .ssh
chmod 700 .ssh
mv sakura2.pub .ssh/authorized_keys
```

※別のPCからログインする場合は、別のPCでも公開鍵・秘密鍵を作成し、
公開鍵の内容を、すでにあるauthorized_keysに新しい行として追加すればOKです。

SShの再起動

```
sudo systemctl restart sshd
```

ここでいったんログアウトして、SSHログインできるかを確認。
確認できたらパスワードログインできないよう、以下ファイルを修正

```
sudo vim /etc/ssh/sshd_config
```

```
PasswordAuthentication no
```

SShの再起動

```
sudo systemctl restart sshd
```

パスワードでログインできなくなってることを確認する。



WinScpでもつなぐ
新しい接続で、パスワード欄は空にして、
設定 - SSH - 認証で、秘密鍵を設定する。

ppk形式に変換しますか？
と聞かれるので、yesを選択、
ppk形式で保存する。

変換したppk形式を選択すればOK



（６）Dockerのインストール
----------------------------------------------------------------------------------------------------

**■Get Docker CE for Ubuntu（公式）**
https://docs.docker.com/install/linux/docker-ce/ubuntu/

インストール準備

```
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
```

インストール実行

```
sudo apt-get update
sudo apt-get install docker-ce
```

インストール後の作業

Dockerグループを作成し、ubuntuのユーザーをDockerグループに追加する

```
sudo groupadd docker
sudo usermod -aG docker $USER
```

終了後、いったんログアウトして、再度ログインする。

これで、ubuntu ユーザーでもdockerを実行できるようになりました。

起動時にDockerが立ち上がるようにする

```
sudo systemctl enable docker
```

--- Memo ---

コンテナ状況の確認

```
docker images
docker ps -a
```


コンテナの作成・起動

```
docker pull ubuntu:16.04
docker run -it -d --name ubuntu1604 -p 80:80 -p 443:443 --restart=always -v /var/www:/var/www ubuntu:16.04
```

※restartをつけることで、ホスト再起動時に自動再起動されます。



--- Memo ---
コンテナの停止

```
docker stop ubuntu1604
```

コンテナの起動

```
docker start ubuntu1604
```

起動していないコンテナをすべて削除

```
sudo docker rm $(sudo docker ps -a -q)
```


コンテナ内 bashの起動

```
docker exec -it ubuntu1604 /bin/bash
```

以降、コンテナ内で作業。
デフォルト、rootになっているので、そのまま実行する場合、コマンドのsudoは省いてください。

aptアップデートしておく

```
sudo apt update
sudo apt upgrade -y
```

ついでにvimも入れておこう

```
sudo apt install vim
```


#（７）apacheのインストール

```
sudo apt install apache2 apache2-dev
```

※apache2-devはこのあとのmod_wsgiインストールに必要らしい。

サービスの確認。

```
service --status-all
```

apache2がインストールされてますが、起動していない状態だった。

apache2の起動

```
sudo service apache2 start
```

ip直打ちで、Apacheデフォルトページが見えるようになりました。



ついでにドメインも設定してサブドメインで見れるようにします。
契約しているドメイン会社の管理画面で、Aレコードにipを登録すればOK。



#（８）Python3.6のインストール

まず、add-apt-repositoryをインストール

**■Ubuntu 14.04 で add-apt-repository が無いと言われた**
https://loumo.jp/wp/archive/20150626000042/

```
sudo apt-get install apt-file
sudo apt-file update
sudo apt-file search add-apt-repository
sudo apt-get install software-properties-common
```



次に、python3.6とpipをインストール

**■Ubuntu16.04でPythonのバージョンを2.7から3.6にバージョンアップする**
https://tetechi.com/python3-6/

```
sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6 python3.6-dev
curl -fsSL -o get-pip.py https://bootstrap.pypa.io/get-pip.py
sudo python3.6 get-pip.py
rm get-pip.py
```

python3.6 -V で3.6.5が入ったことを確認

デフォルトバージョンを3.6に変更

```
ln -s /usr/bin/python3.6 /usr/bin/python
```

python -V で、
Python 3.6.5 と表示された。



#（９）mod_wsgiのインストール＆設定、Flaskの設定

**■UbuntuのApacheでFlaskを用いてPython3でWebアプリケーションを作る**
http://blog.akashisn.info/entry/%3Fp%3D258

**■mod_wsgiでhello worldを描画する**
https://qiita.com/shigechioyo/items/2b25f60918be6b81581a

**■python3/mod_wsgiで日本語表示**
http://www.ohneta.net/wiki/index.php?python3/mod_wsgi%E3%81%A7%E6%97%A5%E6%9C%AC%E8%AA%9E%E8%A1%A8%E7%A4%BA

**■[Python] mod_wsgiを使ってPython3.6をApacheで動かす（CentOS6系）**
https://www.yoheim.net/blog.php?q=20170206

**■Python: mod_wsgi の組み込みモードとデーモンモードについて**
http://blog.amedama.jp/entry/2015/08/16/220628

**■UbuntuでPython3.4 + mod_wsgi + mysql5を使うときの注意点**
https://ur.edu-connect.net/archives/28888

**■AssertionError using Apache2 and libapache2-mod-wsgi-py3 on Ubuntu 14.04 (Python 3.4)**
https://askubuntu.com/questions/569550/assertionerror-using-apache2-and-libapache2-mod-wsgi-py3-on-ubuntu-14-04-python

いろいろ参考ページを試した結果、
以下のようなやり方で進めました。



mod_wsgiのインストール＆ローディング

```
sudo pip install mod_wsgi
```

aptを使ってインストールする方法など、いろいろやり方はあるみたいですが、
pipでのインストールが無難なようです。

インストールされた場所の検索

```
find . -name mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
```

を実行したところ、
/usr/local/lib/python3.6/dist-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
にインストールされたようです。

このファイルをapacheに認識させます。

```
sudo vim /etc/apache2/mods-available/wsgi.load
```

以下、記述。wsgi_module の後は、先ほど検索した場所を書きましょう。

```
LoadModule wsgi_module /usr/local/lib/python3.6/dist-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
```

wsgiを有効化

```
sudo a2enmod wsgi
```

apache2 再起動

```
sudo service apache2 restart
```


apache2を再起動したところ、
AH00558: apache2: Could not reliably determine the server's fully qualified domain name
とのエラーが出た。

**■ubuntuにおけるapache2のAH00558エラーを解決する。**
http://mk-55.hatenablog.com/entry/2014/07/07/004510

```
sudo echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf
sudo a2enconf fqdn
sudo service apache2 restart
```

これで、エラーが出なくなりました。



次、apacheのコンフィグ設定を変更します。
（一応バックアップもとる。）

```
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.bk
sudo vim /etc/apache2/sites-available/000-default.conf
```

```
<VirtualHost *:80>

    WSGIDaemonProcess myapp-process user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/html/app.wsgi

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

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

    <Directory /var/www/html>
        WSGIProcessGroup myapp-process
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>

</VirtualHost>
```


**■Python: mod_wsgi の組み込みモードとデーモンモードについて**
http://blog.amedama.jp/entry/2015/08/16/220628

mod_wsgiはデーモンモードがおすすめらしいので、
myapp-processという名前でプロセスを立ち上げ。

WSGIScriptAliasで、呼び出すwsgiファイルを指定してます。



apache再起動

```
sudo service apache2 restart
```


呼び出されるwsgiファイルを作る
vim /var/www/html/app.wsgi

以下、記述

```
def application(environ, start_response):
    status = '200 OK'
    output = b'Hello World!'

    response_headers = [('Content-type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]
```

ブラウザでipアドレスまたは、設定したドメインを開くと、
Hello Worldを確認できました。



#（１０）Flaskのインストール＆設定

Flaskのインストール

```
sudo pip install Flask
```


wsgi＆pyファイルの設置

```
vim /var/www/html/app.wsgi
```

以下のように、記述を変更

```
import os,sys
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
from main import app as application
```

main.pyからappをapplicationとしてインポートするだけ。

```
vim /var/www/html/main.py
```

以下記述

```
from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "Flask-index OK!"
```

ブラウザで開いて、表示を確認できた。



#（１１）SSLの実装

ついでに、Let's Encryptを使ってSSL対応しましょう。

**■Apache 2.4 on Ubuntu 16.04でSSL**
https://qiita.com/tontan9616/items/bd8b2f1f360f26c7bb46

**■さくらの VPS 上の Ubuntu で Let's Encrypt の SSL 証明書を利用、Https へ移行する**
https://loumo.jp/wp/archive/20171021120015/

**■さくらのVPS(Cent OS6.8)でLet's Encryptを自動更新する方法**
https://qiita.com/childsview/items/e4bff3b32b8304553980

**■意外と簡単！FlaskをHTTPS対応する方法【Let’s encrypt】**
https://blog.capilano-fw.com/?p=374



certbot コマンドのインストール

```
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-apache
```


main.pyを変更

```
vim /var/www/html/main.py
```

```
from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
    return "Flask-index OK!"

@app.route('/.well-known/acme-challenge/<filename>')
def well_known(filename):
    return render_template('.well-known/acme-challenge/'+ filename)
```


テンプレートフォルダの作成

```
mkdir -p /var/www/html/templates
```

```
sudo certbot certonly --webroot -w /var/www/html/templates/ -d example.com -m info@example.com
```

example.comは、適宜置き換えてください。



では、認証キーの取得を取得しましょう。

認証キーの取得

```
sudo certbot certonly --webroot -w /var/www/html/templates/ -d example.com -m info@example.com
```

・・・しかしエラー。「認証しに見に行ったけど、notFoundだったよ」とのこと。

念のため、apache2 再起動

```
sudo service apache2 restart
```

で、再度認証キー取得を行ったところ、無事成功しました。

```
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
```

が、保存された。



最後にapache2の設定を変更します。
まず、sslとrewriteモジュールを有効にします。

```
sudo a2enmod ssl
sudo a2enmod rewrite
```

```
a2enmod rewrite
```

で、モジュールが読み込まれたことを確認します。



apacheのconfig設定

```
sudo vim /etc/apache2/sites-available/000-default.conf
```

```
<VirtualHost *:80>
  ServerName example.com
  RewriteEngine on
  RewriteCond %{HTTP_HOST} ^example\.com
  RewriteRule ^/(.*)$ https://example\.com/$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>

  # SSL
  SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

  ServerName example.com

  # WSGI
  WSGIDaemonProcess myapp-process user=www-data group=www-data threads=5
  WSGIScriptAlias / /var/www/html/app.wsgi

  <Directory /var/www/html>
    WSGIProcessGroup myapp-process
    WSGIApplicationGroup %{GLOBAL}
    Order deny,allow
    Allow from all
  </Directory>

</VirtualHost>
```


保存したら、apache2を再起動する。

```
sudo service apache2 restart
```


ブラウザでドメインを開くと、
自動的にhttpsにリダイレクトされて、表示されました。



以上、さくらVPS上でFlaskアプリを公開するまででした。
次回以降、この環境でPythonアプリを勉強していこうと思います。