ポートフォリオ作成の過程で学んだ技術を振り返る ~Webサーバ構築編~

# はじめに
　Javaのポートフォリオ作成の過程でWebサーバを構築する必要があり、リバースプロキシからSSL証明書の設定,取得までの手順をまとめました。自身の備忘録として、linuxコマンドやオプションの意味も一部まとめております。

# 前提
　AWSにて、以下の環境が構築されている前提で話を進めます。ドメインを取得し、Route53にDNSレコードを設定済みです。
　EC2にはnginxをインストールしているだけになります。この状態からtomcatをインストールし、リバースプロキシ、ssl証明書の取得,設定を行っていきます。
![sample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448205/2b0deb72-34d9-3824-6698-0117b0997e48.jpeg)
こちらのサイトを参考に、tomcatのインストールを行いました。

https://tech.pjin.jp/blog/2019/10/02/ec2_corretto11_02/

## nginx
オープンソースなWebサーバ。
特徴や他ソフトウェアとの比較は、こちらの記事が分かりやすいです。

https://qiita.com/kamihork/items/49e2a363da7d840a4149

## Tomcat
Javaのwebアプリを動かすソフトウェア。
当初私は「tomcatだけでアプリ動かせるなら、nginxインストールしなくてもいいんじゃ？」と思っていましたが、こちらの記事を読んで両方必要だと学びました。

https://qiita.com/tanayasu1228/items/11e22a18dbfa796745b5

# Tomcatをインストール~設定

## 何はともあれ、まずはインストール
```
$ cd ~
$ wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache/tomcat/tomcat-9/v9.0.60/bin/apache-tomcat-9.0.60.tar.gz
```
wgetは、HTTPアクセスをしてコンテンツをファイルに保存するコマンド。
「wget URL」と命令する。

## ファイルを解凍
```
$ tar -xzvf ~/apache-tomcat-9.0.60.tar.gz
```
tarは、複数のファイルを1つのアーカイブファイルにまとめたり、逆に展開したりするコマンド。
以下オプションコマンドの内容
　-x:アーカイブファイルを展開する
　-z:圧縮または展開を同時に行う
　-v:処理の進行しているファイル名を表示する
　-f:アーカイブファイル名をパラメータで指定する

## 解凍したファイルを移動
```
$ sudo mv ~/apache-tomcat-9.0.60 /opt
```
mvは、ファイルを移動させるコマンド。
「mv ファイル名 移動先ディレクトリ名」と命令する。

### /opt is どこ？
OSの一番上の階層(ルートディレクトリ)の一つ下にあるフォルダ。
参考にした記事によると、「パッケージ管理ツール以外でインストールしたディレクトリ構造になっているアプリケーションの格納先に適している」そう。

https://qiita.com/uhooi/items/c1388f8d803641bfb8f3

## シンボリックリンクを作成
```
$ sudo ln -s /opt/apache-tomcat-9.0.60 /opt/tomcat
```
lnは、ファイルのリンクを作成するためのコマンド。
「ln リンク元 登録名」と命令する。
-sオプションによって、シンボリックリンクが作成される。

### シンボリックリンク is 何？
ファイルに別名をつけ、異なった名前でファイルにアクセスする仕組み。いわゆるショートカット。
上記コマンドでは、「/opt/tomcat」という別名で「/opt/apache-tomcat-9.0.60」にアクセスすることが出来る。

## Tomcat用のユーザー作成
```
$ sudo useradd -s /sbin/nologin tomcat
```
useraddは、新規ユーザーを作成しユーザーごとの設定を決めるコマンド。
「useradd [オプション] ユーザー名」と命令する。
-sオプションによって、ログインシェルを指定できる。

### ログインシェル is 何？
ログインして最初に動き出すシェル(プログラム)のこと。
「/sbin/nologin」は、ユーザログインを拒否する(不正なログインを防ぐイメージ？)。

https://qiita.com/LostEnryu/items/9b0c363877581dc1171f#%E7%84%A1%E5%8A%B9%E3%81%AA%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A

## フォルダの所有者を設定
```
$ sudo chown -R tomcat:tomcat /opt/apache-tomcat-9.0.60
```
chownは、指定したファイルやディレクトリのユーザー所有権を変更するコマンド。
「chown 所有者名:[グループ] ファイル名またはディレクトリ名」と命令する。
-Rオプションによって、ディレクトリ内の所有者も変更する。

## サービス登録
```
$ sudo vi /etc/systemd/system/tomcat.service
```
viは、テキストエディタを起動するコマンド。
linixにおけるサービスとは「アプリケーション」のことで、サービス登録すると「systemctl 〇〇 サービス名」というコマンドが使えるようになる。

<details><summary>tomcat.serviceに記述する内容</summary><div>

```tomcat.service
[Unit]
 Description=Apache Tomcat 9
 After=network.target
[Service]
 User=tomcat
 Group=tomcat
 Type=oneshot
 PIDFile=/opt/apache-tomcat-9.0.60/tomcat.pid
 RemainAfterExit=yes
 ExecStart=/opt/apache-tomcat-9.0.60/bin/startup.sh
 ExecStop=/opt/apache-tomcat-9.0.60/bin/shutdown.sh
 ExecReStart=/opt/apache-tomcat-9.0.60/bin/shutdown.sh;/opt/apache-tomcat-9.0.60/bin/startup.sh
[Install]
 WantedBy=multi-user.target
```
</div></details>

## 実行権限を与える
```
$ sudo chmod 755 /etc/systemd/system/tomcat.service
```
chmodは、ファイルの権限や所有者を変更するコマンド。
「chmod 設定するパーミッション ファイルorディレクトリ」と命令する。

```
$ sudo systemctl enable tomcat
$ sudo systemctl start tomcat
```
起動時の登録、実行を確認する。

### パーミッションの数字について
3桁の8進数で「所有者・グループ・その他ユーザー」の順に指定でき、権限に対応した数値を足し合わせて表現する。
|数値|権限|
|--|--|
|4|読み取り|
|2|書き込み|
|1|実行|

今回のコマンドの場合は、
所有者：7 = 4 + 2 + 1 : 読み取り&書き込み&実行権限
グループ：5 = 4 + 1 : 読み取り&実行権限
その他ユーザ：5 = 4 + 1 :  読み取り&実行権限

# リバースプロキシ
設定完了後にtomcatを起動してURLを叩いても、Nginxのデフォルトページが表示されてしまいます。tomcatでJavaのwebアプリを起動する予定なので、リクエストをtomcatで処理できるようにするために、「リバースプロキシ」を行います。
[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B9%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7)でリバースプロキシの意味を調べると、
> リバースプロキシ（英: Reverse proxy）または逆プロキシは、特定のサーバへのリクエストが必ず通過するように設置されたプロキシサーバである。一般的なプロキシとは逆で、不特定多数のクライアントのアクセスに備えて特定のサーバー専用に設けられる。クライアントに取ってはサービスの窓口として機能し、普通はクライアントがリバースプロキシを意識することはない。

...なるほど分からん。。。

https://qiita.com/zawawahoge/items/a931de1464ccaa228551

なるほど分かった！
自分なりに解釈して図で表してみました。
![qiita-linux.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448205/b36ef98e-67c0-3c6f-e58e-87392f2fd429.png)
## Nginxでリバースプロキシの設定
```
$ sudo vim /etc/nginx/nginx.conf
```
confファイルの設定を変更します(修正箇所とその周辺だけ載せます)。
```nginx.comf
#
server {
        listen       80;
        listen       [::]:80;
        server_name  ~~実際のドメイン名~~;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location /{
            proxy_pass https://localhost:8080; #追加
        }
#
}
```
serverコンテキスト内のlocationに「proxy_pass https:\//localhost:8080」を追加しました。これでポート80でNginxにアクセスが来た場合、ポート8080(tomcat)のページを返すようになります。
URLを叩いて、tomcatのデフォルトページが表示されればOK!

# SSL接続
アドレスにアクセスするとURLの左側に「保護されていない通信」と表示されています。このままアプリをリリースしても、怪しまれて誰も利用してくれませんね。。

https://jp.globalsign.com/ssl/about/#:~:text=SSL%E3%82%B5%E3%83%BC%E3%83%90%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AF,%E3%81%8C%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

SSLサーバ証明書があると「ウチのサイトは個人情報などの通信データを暗号化しています。安全して利用できますよ」とユーザに証明できるわけです。
こちらの方々を参考に、SSL設定を行いました。
https://youtu.be/13NTn6WiQvU
https://ti-tomo-knowledge.hatenablog.com/entry/2018/08/03/203726

## EC2の443ポートの解放
EC2に紐づくセキュリティグループに、HTTPS通信を許可するように設定を追加します。
![Inkedqiita-linux3_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448205/a399d757-b272-3a98-b92b-6bd767e63d35.jpeg)


## SSL証明書の取得
リバースプロキシで設定した「proxy_pass https:\//localhost:8080;」は#でコメントアウトしておきます。
```
$ sudo yum install -y certbot python3-certbot-nginx
```
certbotという、SSL証明書を無料で発行してくれるツールをインストールします。

```
$ sudo certbot certonly --webroot -w /usr/share/nginx/html --debug -d ~~~実際のドメイン名~~~ --email ~~~実際のメースアドレス~~~
```
SSL証明書を取得します。オプションが多い。。。

## SSL設定
```
$ sudo vim /etc/nginx/nginx.conf
```
リバースプロキシの時は、serverのポート80のlocationを修正しました。ファイルの下のほうに、serverのポート443がコメントアウトされているので、今回はそこも修正します。
```nginx.conf
    server {
        listen       80;
        listen       [::]:80;
        server_name  ~~実際のドメイン名~~;
        #root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
         include /etc/nginx/default.d/*.conf;

         location /{
          # proxy_pass https://localhost:8080;
            return 301 https://~~実際のドメイン名~~; #追加
         }
    }
    server {
        listen       443 ssl http2 default_server; #修正
        listen       [::]:443 ssl http2 default_server; #修正
        server_name  ~~実際のドメイン名~~;
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/letsencrypt/live/~~実際のドメイン名~~/cert.pem"; # 追加
        ssl_certificate_key "/etc/letsencrypt/live/~~実際のドメイン名~~/privkey.pem"; # 追加

 #        ssl_certificate "/etc/pki/nginx/server.crt";
 #        ssl_certificate_key "/etc/pki/nginx/private/server.key";
 #        ssl_session_cache shared:SSL:1m;
 #        ssl_session_timeout  10m;
 #        ssl_ciphers PROFILE=SYSTEM;
 #        ssl_prefer_server_ciphers on;
 #
        # Load configuration files for the default server block.
        # include /etc/nginx/default.d/*.conf;

        location /{ 
            proxy_pass http://localhost:8080; #追加
            proxy_redirect http:// https://; #追加
        } 
```
ポート80でNginxにアクセスが来た場合はポート443(https)へリダイレクトし、ポート443へアクセスが来た場合はポート8080(tomcat)のページを返すようになります。


# 動作確認
SSL接続できていれば、アドレスの左側に鍵マークが付きます。
![Inkedqiita-linux2_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448205/a1cfd8d2-4eb2-cdeb-ae56-3c6750ad5ec9.jpeg)