概要
以前からVPSを契約していて活用していなかったので、今回は、VPSをAPIサーバとして、Flutterアプリを作りました。(アプリの内容は、chatgptで作成したナンバーズ3の当選番号予測プログラムであり、正確性が保証されていないためメインでは触れません。)
システム全体の構成から、触れたいところのみ詳細に書こうと思います。
システム全体の構成
DBについて
APIサーバについては契約していましたが、DBをどうしようと無料のものを探していたところ、Neonを見つけました。最初はHerokuにしようと思っていたのですが、2022年11月28日に無料枠が廃止されたようです。
Neonとは
サーバーレスなデータベース(Postgresql)を提供しているサービスです。
無料のプランは以下のようになってます。(公式サイトより抜粋)今回は、このサービスを使用して、APIサーバからアクセスしています。
このプランでいうところの0.25CUというのは、0.25 vCPU,1GB RAMだそうです。
なので、2CU = 2 vCPU,8GB RAMまでAutoScaleします。
ストレージが500MBで少し物足りないですが、今回作るアプリでは十分な容量です。
Neonのセットアップについては、ここでは割愛します。
APIサーバについて
以前からVPSサーバをWebARENA Indigoを契約していて使ってなかったので、今回APIサーバとして使用することにしました。VPSを契約した時に書いた記事がこちら(個人ブログの記事です)。
そして、同時期にドメインを取得したので、このVPSに割り当てています。
APIサーバでやること
今回APIサーバの役割は、以下の二つです。
- ナンバーズ3の過去の当選番号をスクレイピングして、予測した番号をNeonにinsertする(日次)
- FlutterアプリからのAPI呼び出しにより、Neonから予測した番号をselectしアプリ画面に表示する
どちらもPython3のプログラムですが、1.はcronによる日次バッチ、2.はFastAPIを用いたREST APIとなっています。ここで、FastAPIの環境構築とデーモンプロセス化までの手順を書いておきます。
FastAPI環境構築、およびデーモンプロセス化手順
まずは、以下のコマンドにより、fastapiとuvicornをインストールします。
pip install fastapi[all]
pip install uvicorn
次に、VPSサーバが万一再起動された場合を考慮して、デーモンプロセス化して自動起動するようにします。
(サービス名をfastapiとした場合)
cd /etc/systemd/system
touch fastapi.service
vi fastapi.service
記述内容は以下です。
[Unit]
Description=Your FastAPI Application
After=network.target
[Service]
User=username #実際のユーザー名を記述
Group=www-data
WorkingDirectory=/home/fastapi #fastapiのワーキングディレクトリを記述
ExecStart=/usr/local/bin/uvicorn main:app --host 127.0.0.1 --port 8000 #ポート番号は実際のものを記述
[Install]
WantedBy=multi-user.target
続いて、上記で指定したワーキングディレクトリにパーミッションを付与します。
chown -R username:www-data /home/fastapi
chmod -R 755 /home/fastapi
デーモンプロセスのリロードを行い、作成したサービスを起動し、自動起動を有効にします。
systemctl daemon-reload
systemctl start fastapi
systemctl enable fastapi
Nginxを介してFastAPIにアクセスする
FlutterからのAPI呼び出しをNginxで受けつつ、FastAPIにリバースプロキシ設定します。(NginxはFastAPIと同一サーバに環境構築します)
ここの手順は割愛します。
API呼び出しをHTTPS化する
HTTPSでのアクセスは必須です。
SSL証明書の発行となると費用が発生するため、どうにか無料でHTTPS化できないかと探していたら、Let's Encryptというフリーの認証局(CA)を見つけました。
有効期限が90日であるため、月初に自動更新するように設定をしましたが、有効期限が30日以上ある場合は、自動更新されないようです。
以下の手順で、Let's Encryptをインストールします。
# Let's Encryptのインストール
apt-get install letsencrypt
# 一旦nginxは停止
systemctl stop nginx
# SSL証明書取得
letsencrypt certonly --standalone -d [実際のドメイン名を記述]
# 途中でメールアドレスを入力します
# nginxを再開
systemctl start nginx
証明書が取得されているかを確認します。
以下コマンドを実行し、Found the following certs:以下にドメイン名に関する情報が出力されれば、取得できています。VALID:に残り何日有効か記載されています。
certbot certificates
Found the following certs:
Certificate Name: ドメイン名
Serial Number: XXXXXXXXXXXXXXXXX
Key Type: RSA
Domains: ドメイン名
Expiry Date: 2024-MM-DD 00:00:00+00:00 (VALID: XX days)
Certificate Path: /xxx/fullchain.pem
Private Key Path: /xxx/privkey.pem
【参考】実際のアプリ画面
参考までに実際のアプリの画面です。
特に画面での操作はなく、起動するとAPIでデータを取得し表示するのみです。
今はまだスクレイピングのプログラムが日次で動いていないので、8/26更新で止まってます。
あと、App Storeに一応審査を出していますがはたして通るのでしょうか?
まとめ
今までは、個人のブログで記事を書いていたのですが、今回初めてQiitaで記事を書いてみました。
情報の粒度感とかわからないですが、今後も個人開発で得た知見などを書いていく予定です。