見出し画像

AWS EC2 でStreamlitを独自ドメインでホスティングして、HTTPS対応にする

<この記事の想定ターゲット>
・WEBアプリをPythonだけで作ってサクッとユーザーテストしたい。けど…
・AWSのアカウントを一応作っただけで、
・nginxをほとんど使ったことがなく、ネットワーク知識があまりない
・ただ、Linux基本操作は分かる

さくっとPythonだけでwebアプリを作れる便利なStreamlit。プロトタイプように使って一般ユーザーにテストしてもらったのですが、なかなか手間取ったので備忘録としてまとめています。また、HTTPではセキュリティの問題で何人かユーザーにブラウザで支障があり、HTTPS対応しておけばよかったと思い、後日に試したのでそれについてもまとめています。

今回はAWS初心者がEC2のAmazon Linux2 でHTTPSかつ独自ドメインで公開するまでの手順を以下のように説明していきます。

  1. AWS EC2インスタンスの準備とElastic IPの関連付け

  2. 独自ドメインの取得と登録

  3. Streamlitの接続確認

  4. HTTPS接続できるようにしてみる

1. EC2インスタンスの準備とElastic IPの関連付け

AWSでEC2インスタンスを新規作成して、静的IPアドレスのElastic IPを割り当て、それをインスタンスに関連付けます。

1-1. EC2インスタンスの準備

まずは、AWSのインスタンスページに行きインスタンスの起動を選択します。

EC2って Elastic Compute Cloud の略なんですね

今回は名前を test_streamlit にして、以下のデフォルト設定にしてインスタンスを起動させます。キーペアは新しく作成しても既存のものでもどちらでも。ここでは、test_streamlitというキーを作成しています。
名前                            :test_streamlit
OSイメージ               :Amazon Linux
インスタンスタイプ:t2.micro

Amazon Linux 2 は RHEL7 / CentOS7ベースらしいですね。

1-2. Elastic IPの関連付け

インスタンスのIPアドレスを固定するために、静的なアドレスであるElastic IPを関連づけます。そうしなければ、インスタンスを停止・休止するとIP アドレスが変わってしまいます。
ちなみに、Elastic IP を関連付けているとインスタンスを停止していても料金が発生してしまうので注意しましょう。

まずは、Elastic IP アドレスをデフォルト設定で割り当てます。

Elasticはflexibleの類語で、柔軟とかしなやかの意味
日本には2つのリージョンがあり、ap-northeast-1 が東京で、ap-northeast-3は大阪

新しく、54.150.100.31というIPアドレスが割り当てられました。

デフォルトでは、IPv4 アドレス設定プロトコルを使用

次に、このElastic IP アドレスの関連付けをします。

アドレスプールはAmazonが提供する貸し出し用のIPアドレス

先ほど作った、test_streamlitのインスタンスを選択します。

EC2のインスタンスページに戻ると、test_streamlitのインスタンスに先ほど割り当てた 54.150.100.31 が、パブリック IPv4アドレスとして関連付けられていることが分かります。

2. 独自ドメインの取得と登録

Route53 を使って、freenom で取得したドメインを登録します。以下の記事に freenom でのドメイン取得方法をまとめています。ここでは、この記事で取得した nankanonamae.tk を使って進めていきます。

まずは、Route 53 でホストゾーンを作成します。

53はDNSのポート番号からきてるんですね

ホストゾーンのドメイン名に、freenomで取得したドメイン名を設定します。

ホストゾーンはドメインのルーティングに関するレコードのコンテナ

nankanonamae.tk のホストゾーンが作成されたので、NS の4つのルーティング先を freenom に追加していきます。

NSはName Server。SOAはStart Of Authorityで、ゾーンの設定などを記述

Freenom の My Domains ページ から、
Manage Domain ⇒ Management Tools ⇒ Nameservers と進みます

Use custom nameserversを選択し、このフォームにRounte53 の4つのNSルーティング先を追加します。

このドメインにアクセスすると、AWSのNSでIPアドレスをきいてくれるようになる

再び、Route53のホストゾーンに戻り、レコードを作成します。レコード名はそのままで、この値には、先ほど取得したElastic IPである 54.150.100.31 を入力します。

TTLはTime To Liveで、ドメイン情報のキャッシュを保持する時間。
レコードタイプAは、IPv4 アドレスを使いウェブサーバーなどにトラフィックをルーティングする

これで、独自ドメインである nankanonamae.tk がリクエストされると、AWSのネームサーバー経由で、IPアドレス 54.150.100.31 が関連づけられた test_streamlit インスタンスにつながるようになりました。

3. Streamlit の接続確認

ここでは、EC2インスタンスにSSH接続した後にStreamlit を実行して、ブラウザからつながるか確認します。

3-1. セキュリティグループの設定

streamlitを起動する前に、その接続を許可しないといけません。インスタンスにはデフォルトでSSH接続しか許可されていないので、他の接続も許可します。

セキュリティグループはAWS標準のファイアウォール機能で、
EC2インスタンスへのアクセスの許可や、トラフィックの制御ができる

セキュリティグループを選択し、インバウンドのルールを編集を選択。

インバウンドは受信で、アウトバウンドは発信

Streamlit はデフォルトでは 8501 ポートを使いますが、後ほどポート番号の変更や HTTP/HTTPS接続を試すので、それらも追加しておきます。ソースはテストなので0.0.0.0/0にします。

0.0.0.0/0(宛先0.0.0.0、ネットマスク0.0.0.0)の場合は全てのアドレスとマッチする。
ネットマスクは、IPアドレスのネットワーク部とホスト部を明確化する役割がある。

3-2. SSH接続で Streamlit のインストールと起動

3-2-1. EC2インスタンスにSSH接続

インスタンスページに戻り、インスタンスに接続してコマンドライン操作をします。

これで、ブラウザから接続できるがしょっちゅう途切れてしまう

また、設定したキーペアを使ってSSH接続もできます。

各自のパソコンの ~/.ssh/config に以下のように設定を追加します。HostNameはインスタンスに関連付けたIPアドレスを、IdentifyFileはダウンロードした証明書を指定します。今回はテスト用にデスクトップのAWSフォルダに置いています。

Hostはtest_streamlit にしてるが、どんな名前でよい

ssh接続する前に、証明書の権限を設定しないと File is too open とセキュリティエラーが出るので、以下のコマンドでroot権限者のみ変更できるようにします。

$ chmod 400 ~/Desktop/AWS/test_streamlit.cer #rootのみに権限
$ ssh test_streamlit #Host: test_streamlitに接続

3-2-2. Streamlit のインストールと起動

SSH接続し、Pythonの仮想環境を作って、そこにstreamlitをインストールします。streamlit hello すると、Streamlitが起動します。

$ python3 -m venv ~/env     # pythonの仮想環境をvenvで作成
$ source ~/env/bin/activate # 仮想環境に入る
$ pip install streamlit.    # streamlitをインストール
$ streamlit hello           # テスト実行
外部URLの http://54.150.100.31:8501 でもアクセスできる

ポート番号8501を指定して、http://nankanonamae.tk:8501 でhttp接続できることが確認できました。

httpなので、Not Secureになっている

これで一旦、セキュリティはさておき、誰でもStreamlitにアクセスできるようになっています。

4. HTTPS 接続できるようにしてみる

Streamlitは基本的にhttpしか対応していませんが、nginxを使ってhttps接続できるようにしてみます。httpでは、セキュリティの問題で接続できない場合がありますので、一般に公開する際にはhttps接続の方がいいでしょう。

4-1. Nginxでルーティングしてみる

まずはnginxで正常にルーティングできるかを確認します。http://nankanonamae.tk:8501 でつながることが確認できたので、次はポート指定なしの、 http://nankanonamae.tk でも接続できるように設定します。

$ sudo amazon-linux-extras install nginx1 -y # インストール
$ sudo service nginx start                   # 起動
$ sudo mkdir /etc/nginx/sites-available      #ドメイン設定ファイル用のフォルダ
$ sudo mkdir /etc/nginx/sites-enabled        #ドメイン設定ファイルのリンク用のフォルダ

$ sudo vim /etc/nginx/nginx.conf
# 以下のように include /etc/nginx/sites-enabled/*;を httpとserverの間に追記します

ルーティング設定のために、sites-available と sites-enabled の2つのフォルダを用意するのですが、違いは以下のようになります。作らなくても設定を変更できますが、あったら管理が便利になります。

/etc/nginx/sites-available : サービスごとのルーティング設定ファイル用のフォルダ
/etc/nginx/sites-enabled : 有効化したい設定ファイルのシンボリックリンク用のフォルダ

これで、設定ファイルを残しつつ、それを有効化するかどうかをsites-enabled内のシンボリックリンクの有無で変更できます。

さらに、以下のように nankanonamae.tk 用の設定ファイルを追加します。
server_name は各自取得したドメインに置き換えてください。

$ sudo chmod 777 /etc/nginx/sites-available # ファイルを追加できるように権限を変更
$ sudo chmod 777 /etc/nginx/sites-enabled # ファイルを追加できるように権限を変更

# nginxのルーティング設定を追加、80から8502にルーティング
$ echo '''server {
    listen       80;
    server_name  nankanonamae.tk;
    location / {
        proxy_pass http://0.0.0.0:8502/; # 今回はデフォルトの8501ではなく、8502ポートで試す
        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; # upgradeしないと、ずっとローディングして動かない
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}''' > /etc/nginx/sites-available/nankanonamae.tk

$ ln -s /etc/nginx/sites-available/nankanonamae.tk /etc/nginx/sites-enabled/nankanonamae.tk # シンボリックリンクを作成
$ sudo service nginx restart # nginxを再起動

また、Streamlitの設定ファイルも追加しておきます。デフォルトの設定ファイルは~/.streamlit/config.tomlなのですが、これも各自で用意する必要があります。

$ mkdir ~/.streamlit
$ echo '''[server]
port=8502
headless=true # 自動でブラウザを開かないようにする

[browser]
serverAddress = "nankanonamae.tk" # ドメイン名やIPアドレス
serverPort = 8502''' > ~/.streamlit/config.toml

$ streamlit hello # streamlitの起動

また、プロジェクトごとに設定ファイルを作ることもできますが、ここでは全体に適用されるデフォルトの設定ファイルにしています。ポートを変更できることを試すために、8502を設定しています。

起動すると、nankanonamae.tk:8502 でも nankanonamae.tkでも接続できることが分かります。

4-2. SSL証明書の取得

webサーバー用のSSL証明書を簡単に発行できる、Certbotを使ったやり方を紹介します。EC2インスタンスにSSH接続して、以下のコマンドを実行します。

# パッケージをダウンロード
# EPEL: Extra Packages for Enterprise Linux
sudo wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/

# パッケージをインストール
sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm

# epelを有効化する
sudo yum-config-manager --enable epel*

# certbotをインストール
sudo yum install -y certbot 
sudo yum install -y python-certbot-nginx

# certbotを使ってSSL証明書を発行
sudo systemctl stop nginx # 先にnginxを停止させておく。起動したままだとエラーになる
sudo certbot certonly --standalone --debug -d nankanonamae.tk # -d の引数は各自のドメインを指定する

完了すると以下の2つのファイルが生成される。
/etc/letsencrypt/live/nankanonamae.tk/fullchain.pem:公開鍵 ・/etc/letsencrypt/live/nankanonamae.tk/privkey.pem   :秘密鍵

4-3. nginxでhttpsの設定

/etc/nginx/nginx.conf のserver部分を以下のように書き換えます。デフォルトの設定とは違いかなりシンプルですが、テスト用なので十分です。後で、追加で設定したかったらやりましょう。

server {
        listen 80 default_server;
        server_name  nankanonamae.tk;
        return 301 https://$server_name$request_uri; # httpリクエストをhttpsにリダイレクト
}

次に、/etc/nginx/sites-available/nankanonamae.tk も以下のように書き換えます。httpsのポートである443に変更して、SSL証明書も指定します。ssl_protocolsとssl_ciphersは暗号化のバージョンに関するオプションです。
locationは 4-1. Nginxでルーティング の時と同じです。

server {
    listen              443 ssl;
    server_name         nankanonamae.tk;
    ssl_certificate     /etc/letsencrypt/live/nankanonamae.tk/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/nankanonamae.tk/privkey.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://0.0.0.0:8502/;
        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";
    }
}
sudo service nginx restart # 設定ファイルを更新するためにnginxの再起動

こで、https接続ができるようになります。https接続も証明書も確認できます。また、http接続でも自動的にhttps接続にルーティングされるようになっています。

証明書には有効期限があるので注意しましょう

あとは、streamlitのアプリを作って公開して試してもらいましょう。

最後に、こちらがざっくり構成図です。


この記事が気に入ったらサポートをしてみませんか?