AWS CloudFrontをTomcatのリバースプロキシとして利用する

# 概要

以前、私が運用していた構成は、EC2インスタンスの上にnginxとTomcatを立てて、nginxをリバースプロキシにしてTomcatで処理を動かすというよくある構成でした。

多忙のためnginxを最近メンテナンス（バージョンアップとか）できていなかったので、これを気にTomcatだけをEC2で動かして、WebサーバはAWSのマネージドサービスを利用して、Webサーバの運用負担を減らそうというのが今回の狙いです。

（当然Tomcatの更に奥にDBサーバが居ますが今回はDBサーバについては扱いません）

# システムの構成

```mermaid
graph TD;
    ユーザー-->|443 HTTPS|CloudFront;
    自分だけ-->|443 HTTPS|CloudFront;
    CloudFront-->|8080 HTTP|EC2;
    自分だけ-->|22 SSH|EC2;
    EC2-->DB[(DataBase)];
```

SSHからEC2への接続は自分だけができるようセキュリティグループでマイIPを設定しています。

:::note warn
この記事では冗長化やサイトメンテナンス時用の対処を行っていません。
必要に応じて各自で対応してください。（ALBをCloudFrontとEC2の間に入れるとか）
:::

# EC2インスタンスの作成とTomcatの環境構築

## EC2の要件

「Elastic IP」で「パブリック IPv4 アドレス」と「パブリック IPv4 DNS」をEC2インスタンスに割り当ててください。
Tomcatの動作の為Javaをインストールしてください。


## EC2インスタンス側でTomcatのディレクトリを作成

```shell_session
# mkdir /app
```

## Tomcat実行用のユーザーを作成

```shell_session
# adduser tomcat
```

## 作成したディレクトリの所有者を作成したユーザーに変更

```shell_session
# chown tomcat:tomcat /app
```

## 作成したユーザーにログインしてTomcatを格納するディレクトリに移動

```shell_session
# su - tomcat
$ cd /app
```

## Tomcatのダウンロード

Tomcatの本体をTomcatの公式ホームページからダウンロードします
[Apache Tomcat®](https://tomcat.apache.org)

![Tomcatのダウンロード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/5bf43545-13c2-6e71-b38a-bbe0c2d4053a.png)

コピーしたURLをwgetでダウンロードします

```shell_session
$ wget https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.3/bin/apache-tomcat-11.0.3.tar.gz
```

ダウンロードされたTomcatの圧縮ファイルを解凍します

```shell_session
$ tar zxvf apache-tomcat-11.0.3.tar.gz
```

これ以降圧縮ファイルはもう使わないので削除してしまって大丈夫です。

```shell_session
$ rm -fv apache-tomcat-11.0.3.tar.gz
```

## 解凍したディレクトリ内に移動します

```shell_session
$ cd apache-tomcat-11.0.3
```

## Tomcatの設定

Tomcatの設定ファイルですが、基本的にデフォルトで大丈夫です。
今回私は以下の通り設定しています。（デフォルトと同じ設定ですがコメントを消したりしたものを使っています）

```shell_session
$ vi ./conf/server.xml
```

```xml:server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">

	<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
	<Listener className="org.apache.catalina.core.AprLifecycleListener" />
	<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
	<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
	<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

	<Service name="Catalina">

		<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

		<Engine name="Catalina" defaultHost="localhost">
			<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" />
		</Engine>

	</Service>

</Server>
```

## WARの配置

解凍したTomcatのディレクトリ内にある`webapps`ディレクトリにあなたのwarファイルを格納してください。

```shell_session
$ cp あなたのWARファイル.war ./webapps/
```

## Tomcatの起動

Tomcatを起動します

```
$ ./bin/startup.sh
```

起動したらログを確認して下記のようなミリ秒の時間が出ていれば起動成功です。

```shell_session
cat ./logs/catalina.out
```

```
11-Feb-2025 06:49:21.604 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
11-Feb-2025 06:49:21.615 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [3022] milliseconds
```

# EC2のセキュリティグループの設定

EC2にアタッチしているセキュリティグループのインバウンドルールにてポート番号に先ほどTomcatのserver.xmlで設定したポート番号を入力、ソースにCloudFrontのプレフィックスリストを指定します。

![EC2のセキュリティグループの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/3e192a71-f04a-8ffc-f458-c266ebb20f66.png)

プレフィックスリストについてはこちらを参照してください。
[AWS マネージドプレフィックスリスト](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html)

:::note warn
プレフィックスリストを使用せずに「0.0.0.0/0」や「::/0」で許可してしまうと8080に直接アクセスできてしまいます。
:::

# CloudFrontのディストリビューションを作成

AWS マネジメントコンソールからCloudFrontを開き、新しいディストリビューションを作成します。

![CloudFront1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/da807389-bfd3-25d4-29cb-97b4153b0942.png)

キャッシュポリシーを必ず「CachingDisabled」に設定します

![CloudFront2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/a32473d9-56f1-11bb-142f-4fbab2200914.png)

:::note warn
動的なWebサイトの場合アクセスする人によってページコンテンツが変わる仕組みになっている物と思います。
キャッシュを有効にした場合他の人の為のページがキャッシュされて全く別の人に表示されるというセキュリティ事故が発生してしまうので、ここではCSSやJSファイルなどの静的ファイルも含み全てキャッシュを無効に設定しています。
ディストリビューション作成後にビヘイビアを追加してください。
:::

:::note info
エラーページを使用する場合ここでカスタムエラーページを設定してください。
:::

![CloudFront3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/abe7838e-da5c-0fdd-5797-93cc35ea3a90.png)

# CloudFrontの接続テスト

この状態でディストリビューションの詳細の「ディストリビューションドメイン名」のURLにアクセスするとあなたのページが表示されると思います。
表示されていたらここまで成功です。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/6cecf5dd-c967-e92f-6379-58385d4c8f82.png)

# Route 53で名前解決をCloudFrontに向ける

:::note warn
この作業により実際のユーザーがあなたのサイトに流入してきます。
:::

AWS マネジメントコンソールからRoute 53を開き、ホストゾーンのレコードを作成、または既存の場合は編集します。

レコードタイプはAかAAAAを選択し、
エイリアスにチェックを入れ、
CloudFront ディストリビューションへのエイリアスを選択し、
先ほど作成したCloudFrontのディストリビューションを選択します。

![Route 53で名前解決をCloudFrontに向ける](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607960/fb062046-b3db-6bc1-2050-0ada472d6346.png)

# 接続テスト

ブラウザにあなたのドメインを入力して正しく接続できれば設定完了となります。

お疲れ様でした！

# 最後に
もし記事に不備がある場合はお知らせ頂けると幸いです。