LINUX

【AWS】Streamlitで作成したRAGアプリケーションをEC2にデプロイし、HTTPS化して安全に公開する方法を丁寧に解説

参照

https://qiita.com/y-mae/items/8dfacebf56347e9c1469?utm_campaign=daily_trend&utm_medium=web_push_notification&utm_source=qiita

概要

業務の中で、Streamlitで作成し、EC2にデプロイしたRAGアプリケーションを以下の要件で実装する必要があり、その際得た知見を整理してブログの形にまとめました。

  • お名前.comで作成したドメインと紐付け、ネームサーバーの管理はAmazon Route 53 上でできるようにする
  • HTTPS経由でセキュアにアクセスしたい

Streamlit Cloudでもデプロイできるのでは?という意見もあるかと思われますが、今回は「敢えて」EC2でデプロイする方法を実施しています。(詳細は後述)

前提) EC2上に構築したStreamlitアプリの特徴

  • EC2上でStreamlitアプリを起動すると、デフォルトではhttp://で起動してしまうので、安全性の観点で少し不安が残る
    →顧客要件で、http://でのアクセスは許可されておらず、https://でのアクセス設定が必要な場合も考えられる。

事前準備

お名前.comでドメインを払い出す、Route 53にドメイン管理を移管

今回は検証用に、お名前.comでmaeno-dev.comというドメインを取得しました。

ホストゾーンの作成

スクリーンショット 2024-12-31 7.04.16.png

Aレコードの作成

スクリーンショット 2024-12-31 7.27.45.png

NSレコードの確認

スクリーンショット 2024-12-31 7.28.03.png

ネームサーバーの管理を、お名前.comからRoute 53に移管するために設定変更

お名前.comの、ドメインメニューから、ネームサーバー設定を選択し、ドメインを選択し、その他のネームサーバーを使うという部分で、先ほどの画面で表示されていた4つの名前を記載します。

スクリーンショット 2024-12-31 7.33.28.png
スクリーンショット 2024-12-31 7.34.29.png

デプロイ用のEC2の作成、ローカルで作成したソースコードの移植

VPC作成

VPCなどを選択し、サブネットも同時に作成します。

EC2作成

スクリーンショット 2024-12-31 7.15.19.png
スクリーンショット 2024-12-31 7.15.38.png

作成したVPC、サブネットを選択。
インスタンスタイプはデフォルトの選択のままで進めます。

セキュリティグループは、HTTP化対応を行うまでは、自身のIPアドレスに加えて、HTTPS/HTTPで、全てのIPを許可しています。(おそらく、SSL証明書を発行する際、外部の認証機関からアクセスが入るため、自身のIPのみの許可では上手くいかなかった)証明書の設定が完了後、以下のルールを削除しました。
基本的には許可したいIPのみを指定し、安全にアクセスができるようにしましょう。

ローカルで作成したRAGアプリケーションをclone

ローカルで作成したソースコードをpullするために、gitをインストールします。

$ sudo yum install git-all

その後、

$ ssh-keygen -t rsa

で認証鍵を生成、公開鍵をGitHubに登録することで、EC2とリポジトリ間でSSHを可能にします。

その後以下コマンドでソースコードをcloneします。

$ git clone git@github.com:y-mae-dev/streamlit-rag-app.git

手順

0.RAGアプリケーションをローカルで準備

今回は Streamlit×Bedrock×Kendraで作る! 多機能チャットボットで紹介したアプリを使用します。(※一部アップデートを加えております。記事の本旨から逸れるためここでは解説しませんが、「参考)ソースコード」の項でソースコードは記載いたしますので参考にしていただければと思います。)

1.ローカル→作成したEC2インスタンスにSSH

.ssh/config 配下に 以下を記載しておきます。

Host streamlit-rag-app
  HostName (EC2のパブリックIPアドレス)
  User ec2-user
  Port 22
  IdentityFile ~/.ssh/(秘密鍵の名前)
$ ssh streamlit-rag-app

そうすることでEC2へアクセスできるようになります。

2. サーバー側でのリバースプロキシの設定

EC2でStreamlitを起動し、独自ドメインでHTTPS接続するまで(備忘録)
を参考にさせていただきました。

ここが今回の肝になります。

2.1 nginxのインストール

sudu yum install nginx 実行結果

2.2 nginxの起動

[ec2-user@ip-10-0-0-10 ~]$ sudo service nginx start
Redirecting to /bin/systemctl start nginx.service

2.3 設定ファイルの修正

2つのディレクトリを作成し、設定ファイル(nginx.conf)を一部変更します。

$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
$ sudo vi /etc/nginx/nginx.conf
include /etc/nginx/conf.d/*.conf;

の下に、

include /etc/nginx/sites-enabled/*; 

を追加

$ sudo chmod 777 /etc/nginx/sites-available 
$ sudo chmod 777 /etc/nginx/sites-enabled

を実行し、フォルダ内の権限を変更

[ec2-user@ip-10-0-0-10 ~]$ echo '''server {
    listen       80;
    server_name  maeno-dev.com;
    location / {
        proxy_pass http://0.0.0.0:8501/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}''' > /etc/nginx/sites-available/maeno-dev.com

を実行し、nginxのルーティング設定を追加します。
これによって、httpのアクセスが8501にルーティングされます。

(streamlit-rag-app) [ec2-user@ip-10-0-0-10 streamlit-rag-app]$ streamlit hello

Collecting usage statistics. To deactivate, set browser.gatherUsageStats to false.


  Welcome to Streamlit. Check out our demo in your browser.

  URL: http://maeno-dev.com:8501

  Ready to create your own Python apps super quickly?
  Head over to https://docs.streamlit.io

  May you create awesome apps!

表示されているURLにアクセスしてみると、以下のような画面になり、通信が転送できていることがわかります。

スクリーンショット 2024-12-31 17.35.49.png
streamlit hello

を実行すると、streamlitが提供するWelcomeページに遷移します。

ここまではhttp接続を行い、アプリを起動できる状態にしました。
しかしながら、本記事の目的はhttps接続できるようにすることでした。続いてのステップとして、無料かつ自動でSSL証明書を発行できるツールであるcertbotを使って、SSL証明書を発行し登録します。
まずは、certbotをインストールします。(実行結果は以下)sudo yum install certbot-nginx実行結果

続いて、以下コマンドを実行します。

$ sudo certbot --nginx 

このコマンドは、Let’s Encrypt を使って SSL/TLS 証明書を取得し、自動的に Nginx に設定を追加するものです。以下が実行結果(一部)です。

[ec2-user@ip-10-0-0-10 ~]$ sudo certbot --nginx
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): maeno-dev.com
Requesting a certificate for maeno-dev.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/maeno-dev.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/maeno-dev.com/privkey.pem
This certificate expires on 2025-03-31.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Could not install certificate

NEXT STEPS:
- The certificate was saved, but could not be installed (installer: nginx). After fixing the error shown below, try installing it again by running:
  certbot install --cert-name maeno-dev.com

Could not automatically find a matching server block for maeno-dev.com. Set the `server_name` directive to use the Nginx installer.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

どうやらSSL証明書は登録できましたが、nginxにインストールできなかったようです。
もう一度手順を見直してみたところ、下記二つの対応が漏れていたようでした。

  • 仮想ホストmaeno-dev.com の設定を有効化
  • nginxの再起動を行い、設定の反映
ln -s /etc/nginx/sites-available/maeno-dev.com /etc/nginx/sites-enabled/maeno-dev.com

[ec2-user@ip-10-0-0-10 ~]$ sudo service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Successfully deployed certificate for maeno-dev.com to /etc/nginx/sites-enabled/maeno-dev.com
Congratulations! You have successfully enabled HTTPS on https://maeno-dev.com

上記のように、最終的に You have successfully enabled HTTPS on https://(ドメイン名)というような表示が出ればHTTPS化の作業は完了です。

4.Streamlitアプリを起動、https://ドメイン名でアクセスできるか確認

スクリーンショット 2024-12-31 18.08.04.png

画面のように、ドメイン名を当てた状態で、サンプルアプリケーションを起動できたことが確認できました。

ここでTips

nohup streamlit run app.py &

とすれば、アプリをバックグラウンドで常時起動することができます。
バックグラウンドで起動しない場合、以下のような問題が発生します。

  • ローカル→EC2との接続が切れてしまった際にアプリとの接続も切れてしまう
  • ターミナルが操作できない(アプリ起動時に、別ターミナルを開かないと、他のコマンドが打てない)

そのためアプリケーションを実際に誰かに公開する場合は、バックグラウンドで常時起動させておくのが運用上よいと思います。

EC2 vs Streamlit Community Cloud

EC2にStreamlitアプリをデプロイする場合と、Streamlit Community Cloudを比較するべく、セキュリティ、労力、コストの観点から比較してみました。
安全性を重視したいならEC2へのデプロイ、お手軽さを重視したいならStreamlit Community Cloudへのデプロイが良さそうですね。

比較項目EC2へのデプロイStreamlit Community Cloudへのデプロイ
セキュリティ・SGにおいて、特定IPによるアクセス許可を実施することでアクセス
制限が可能
・HTTPS対応や証明書の管理が
手動
– 基本的なセキュリティはStreamlit側で管理なので、サーバーや証明書の更新作業は不要。
・アプリはインターネット上に公開されるためアクセス制限は基本的に難しい
労力・サーバーのセットアップや環境構築が必要。非常に簡単にデプロイ可能
コスト・EC2の利用料が発生・無料。ただし、サービスの制限(作成できるリソースなど)がある

参考)ソースコード

完全版はGithubに公開しています。app.py

kendra_bedrock_query.py

app_config.py

.env

まとめ

いかがでしたでしょうか。
手順は少し煩雑ですが、要点を理解すればそこまで難しくないと思います。作成したアプリケーションをよりセキュアに公開したいという場合は、本記事でご紹介した方法を試してみるのはいかがでしょうか。
本記事が皆さんのお役に立つことができれば幸いです。

参考資料

EC2でStreamlitを起動し、独自ドメインでHTTPS接続するまで(備忘録)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です