LoginSignup
1
2

More than 3 years have passed since last update.

VPS + Flask で、おうちの状況をどこでも確認

Last updated at Posted at 2019-12-23
  • 今年は Advent Calendar に 2 つ参加することができました。

Prologue

  • IoT 家電が普及してきたことで、家の各種状態を
    外出先から見るということの需要が増えてきました。

  • でも、家庭内 LAN の機器に WAN から接続するためには
    NAT 越えなどのややこしい話をクリアする必要があり、
    一歩間違えば家庭内 LAN を脆弱にしてしまうリスクもあるため、
    安易にオススメできません。

  • そこで…

VPS を使って家庭内 LAN と公開サーバーを切り離そう

  • 今は VPS のプロバイダーや契約プランが増え、ワンコインから
    契約できるため、気軽に利用できるようになりました。

  • VPS を利用して、家庭内 LAN の機器を WAN に公開することなく、
    家庭内の状況を監視するようにします。

仕組み概念図

diagram_home_report.png

  • 家庭内 LAN 側からのアクションは upload だけなので、
    家庭内の機器がセキュリティリスクに曝されることはありません。

VPS を準備する

  • まだ VPS を契約していない方々

    • 契約してください!
    • ググったら各社の特徴比較の記事がいっぱいあります。
  • 準備の内容は、ここでは省略します。

    • ご契約の会社が公開している手順をご覧ください。
    • どの手順でも、終わった段階で作業 PC から VPS に
      ssh で接続できるようになっているはずです。

家庭の状況を収集し、upload する仕組みを作る。

  • ここでは簡単な事例として、RasPi で定期的に vmstat を実行し、
    その直近 10 回を表示することにします。
    • ここでは、こちらで準備した Pi4 を使います。

秘密鍵と公開鍵を作る

  • まず RasPi から password 認証無しに VPS に
    ssh で login できるように秘密鍵と公開鍵を準備します。
pi $ ssh-keygen -t ed25519
  • デフォルトのままポチポチしたらこうなっていると思います。
pi $ ls ~/.ssh/
id_ed25519  id_ed25519.pub
  • VPS をセットアップした作業 PC から rsync で
    id_ed25519.pub を引っ張ってきて、VPS に上げます。
PC $ rsync -av pi@192.168.xxx.yyy:~/.ssh/id_ed25519.pub ./
PC $ rsync -av id_ed25519.pub [VPS USER]@[VPS IP]:~/
PC $ ssh [VPS USER]@[VPS IP]
VPS $ cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
  • ~/.ssh/config を書きます。
    • ホスト名は、ここでは仮に flask-vps とします。
Host    flask-vps
    HostName    aaa.bbb.ccc.ddd
    Port        xxxxx
    User        username
    IdentityFile    ~/.ssh/id_ed25519
  • RasPi から VPS に login できることを確認します。
pi $ ssh flask-vps
VPS $ 

make_report.sh

  • 次に vmstat の結果と、実行した日時を txt に出力する script を作ります。
#!/bin/bash

date
echo
vmstat -S M 2 5
echo
  • ここの内容をもっと工夫することで、様々な情報を収集することができます。

submit.sh

  • 更に make_report.sh で log_report.txt を作成し、定期的に
    最後の方を切り出して VPS に upload する shellscript を作ります。

    • ファイル名のネーミングが今イチですがご容赦ください。
  • 無限 loop で service として動かすため、ファイルを別にしました。

    • make_report を function にして 1 ファイルにすることもできます。
  • upload する VPS のディレクトリは、ここでは
    ~/workspace/home_report/ とします。

#!/bin/bash

LOG='log_report.txt'
PERIODIC_MINUTES='10'
VPS_SVR="flask-vps:~/workspace/home_report/static"

while :
do
    ./make_report.sh >> $LOG
    cat $LOG | tail -n 100 > recent_${LOG}
    rsync -av recent_${LOG} $VPS_SVR/
#   exit 0
    sleep $(($PERIODIC_MINUTES * 60))
done
  • 実行した後、VPS 側できちんと upload できていることを確認します。

  • できていたら、RasPi で submit.sh を service 実行します。

$ nohup ./submit.sh &
$ exit
  • これで、RasPi が稼働中で、ネットワークに接続されている間は
    定期的に recent_log_report.txt が VPS に upload されます。
    • シャットダウンや再起動を行うと停止するので、
      その際はまた nohup ./submit.sh & してください。

upload された家庭の状況を Flask で公開する

  • ここまでの仕組みで ~/workspace/home_report/static/
    の中に定期的にデータが上がってくるので、あとはこのデータを
    Web ページのコンテンツとして表示するだけです。

home_report.py

  • あまり書くことないです。
"""
advent calendar 2019 flask.
"""

from __future__ import absolute_import, division, print_function, unicode_literals
import sys
from os import path
from flask import Flask, render_template

app = Flask( __name__)

@app.route( '/')
def entrance() :

    return  "{}".format( __name__)

@app.route( '/home-report')
def default_report() :

    with open( 'static/recent_log_report.txt', 'r') as file :
        report  = file.readlines()

    return  render_template( 'report.html', report = report)

def main( argv) :

    host_ip     = argv[1]
    host_port   = int( argv[2])

    app.run(    host    = host_ip,
                port    = host_port )

if __name__ == "__main__" :

    if len( sys.argv) < 3 :
        print( "USAGE: {:s} [ip] [port]".format( sys.argv[0]))
        sys.exit( 1)

    main( sys.argv)

templates/report.html

  • 最低限です。
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>Home Report</title>
        <style>
            div.report {
                background-color    : #EEE;
                font-family         : monospace;
                max-width           : 800px;
                padding             : 20px;
                margin              : 0 auto 0 40px;
            }
        </style>
    </head>
    <body>
        <h1>Home Report</h1>

        <div class="report">
            <!-- {{report}} -->
            {% for line in report %}
                {{line}}<br>
            {% endfor %}
        </div>
    </body>
</html>

VPS 側で Flask を実行する

  • ここまでで、VPS の作業ディレクトリの中はこんな感じです。
~/workspace/home_report/
|-- home_report.py
|-- static/
|  `-- recent_log_report.txt
`-- templates/
   `-- report.html
  • service として実行します。
VPS $ export IP=`networkctl status | grep -i address | awk '{print $2}'`
VPS $ export PORT='xxxxx'
VPS $ nohup python3 home_report.py $IP $PORT &
VPS $ exit

完成

  • ブラウザーで VPS の http://IP:PORT/home-report にアクセスすると、
    static/recent_log_report.txt の内容が表示されました。

    ss_home_report.png

    • 見た目はショボいですが、
      直近の家庭の状況が見られるサイトができました。

Epilogue

  • 今回は RasPi の情報だけでしたが、
    RasPi から収集可能な家庭内のテキストデータや画像なら
    何でも upload することができるため、汎用性は高いです。

  • VPS の入門ネタとしても、ぜひご活用ください :smiley:


EOF

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2