【備忘録】reactで作ったwebアプリを自宅サーバー(Ubuntu)にデプロイしたい

自分で勉強がてら作ったReactアプリについて、ブラウザにURLを打つことでアクセスできるようにした。
また、単にアプリをデプロイするだけであればクラウドサーバーを使うのが楽だと思われるが、勉強のために自宅サーバーを立てる方法で行った。
この際、行った手順や参考になった記事について、霧散してしまうのはもったいないので自分用にまとめておく。

# 前提
localhostで動くReactアプリは手元にあることを前提とする。
また、サーバー構築用に使用していないノートパソコンを用意すること。


# 作業の流れ
作業の流れは以下の通り
1. ドメインの取得とDNS設定
1. サーバー用PCへのUbuntuのインストール
1. Apacheのインストール
1. IPアドレスの固定化とポートの開放
1. Reactのbuild
1. アプリのデプロイ
1. URLをhttpsに変更

# ドメインの取得とDNS設定

## ドメインの取得
ドメインの取得は「お名前ドットコム」で行った。
[お名前ドットコム](https://www.onamae.com/campaign/lp/top/?utm_source=Google&utm_medium=paidsearch&banner_id=102_kwt_domain_domainbrand-onamae_rsa_012&waad=oHo0Fp0R)
お名前ドットコムを使った積極的な理由はないが、よく名前を聞くサービスだったため選択した。
ドメインは「.com」を選択。今後も利用する想定のため、スタンダードっぽいものの中で価格と相談して決めた。
ドメイン取得は流れに乗って進めていけば簡単に取得できたが、この際誤ってレンタルサーバーの登録をしてしまった。（うっかりを誘発しやすいデザインになっていた）
今回は自宅サーバーにデプロイする想定だったので、こちらはすぐに解約した。
→三ヶ月は解約できません、とのことでお金が請求されてしまいました。。マジか。。
<b>初心者はお名前ドットコムは絶対に使うな</b>

## DNS設定
ドメインは、使用されるときDNSによりIPアドレスに読み替えられて使われている。
[参照：ウィズワークスの記事](https://shanaiho-app.jp/column/836/)

このため、DNSにドメインとIPアドレスの紐づけを設定してやる必要がある。

お名前ドットコムの場合、以下のような手順で設定が可能。

### ①左メニューから「ドメインDNS設定」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/dbeb569a-a2b2-4b3e-ba5b-2eac82e2ff1d.png)

### ②「次へ」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/b3922ba8-d82c-44e9-9595-1d7a5cf76061.png)

### ③DNS設定の中の「DNSレコード設定を利用する」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/c1b1ca73-7aaf-4d80-a4a5-ed9595ced8d4.png)

### ④「A/AAAA/CNAME/MX/NS/TXT/SRV/DS/CAAレコード」について入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/fc2b7318-a2c0-42f9-908a-715bfd054258.png)
- ホスト名：特にこだわりがなかったため「www」と入力
- TYPE：グローバルIPアドレスはIPv4だったので、「Aレコード」を選択
- TTL：特にこだわりはないのでデフォルト値
- VALUE：以下でグローバルIPを確認して入力
  - [グローバルIPアドレス確認](https://www.cman.jp/network/support/go_access.cgi)
　※なお、グローバルIPアドレスが割り当てられていない場合もあるようです。この場合はポート開放ができないため、外からサーバーにアクセスさせるためのハードルが上がるようです。

### ⑤ネームサーバー情報変更のチェックボックスにチェックを入れ、「確認画面へ進む」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/1aa7db63-4ec6-4901-bb1c-f7e4055bacca.png)

あとは基本的には流れで行ける。
※ドメインプロテクションについてのモーダルが表示されることがあるため、間違えて契約しないよう注意。

なお、変更はすぐには反映されない。一晩程度待つ必要がある。

# サーバー用PCへのUbuntuのインストール
まず、USBメモリを用意し、インストールメディアを作成する。
※ここで使ったUSBメモリはデータが削除されるため、要注意。

- インストール元
[Ubuntuの入手](https://www.ubuntulinux.jp/download)
上記から「日本語Remixイメージのダウンロード」>ミラーサイトからダウンロードする。

- インストールメディア作成ツール
[Rufus](https://rufus.ie/ja/)
上記をインストールして使用。

インストールメディアの作成と使用は、以下のサイトに記載がある流れで実施した。
[WindowsでUbuntuのインストールUSBメディアを作成する](https://diagnose-fix.com/topic2-003/)

# Apacheのインストール
ApacheはWebサーバーソフトウェアの一つ。
昔から使われており、簡易にセットアップできるため、初学者向けの記事でよく選定されている。
対抗としてはNginxがあるようだが、今回はApacheを利用する。
Ubuntuを使ったApache2のインストール手順は、以下記事を参考に行った。

[Apache2のインストール手順](https://qiita.com/pyon_kiti_jp/items/7000b9a04aa2899bf9a8)

# IPアドレスの固定化とポートの開放
## IPアドレスの固定化
外部からサーバーにアクセスするためには、ポートの開放が必要になる。
ポート開放時にはそのポートに対するアクセスをどのデバイスに振り分けるか設定する必要があるが、
この際、サーバーのローカルIPアドレスが動的に設定されていると、うまく振り分けの設定ができない。
このため、まずサーバーのローカルIPアドレスを固定化する必要がある。

なお、今回はノートパソコンの制約から、wifiを固定化する。
wifiのIPアドレスの固定化は「設定」＞「Wi-fi」から設定できた。

### ①設定ウィンドウの表示
「設定」＞「Wi-fi」を選択し、ネットワーク一覧からIPアドレスを固定化したいネットワーク右の歯車マークを押下。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/6d9b0681-bc54-4ff1-bd62-4f90c7652e8f.png)

### ②IPv4の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/452f3042-8bbf-4645-97fe-488a07b22c69.png)

 - IPv4メソッド：手動に切り替え
 - アドレス：固定化するIPアドレスを指定。第１〜第３オクテットまではデフォルトゲートウェイと同一。第４オクテットは0-255の範囲で任意に入力
 - ネットマスク：サブネットマスクを指定。私のルーターでは「255.255.255.0」で固定
 - ゲートウェイ：デフォルトゲートウェイを指定
 - DNS：今回はGoogleのDNSを指定

## ポートの開放
IPアドレスが固定化できたら、ポートの開放を行う。
ポート開放はルーターにて設定する。

### ①ルーターの設定画面に接続する
大抵の場合、デフォルトゲートウェイのIPアドレスをブラウザのアドレスバーへ入力することで、ルーターの設定画面に接続できる。
Ubuntuの場合、以下のコマンドでデフォルトゲートウェイのIPアドレスが確認できる。
```
ip route
```
デフォルトゲートウェイのIPアドレスはdefaultの後ろにあるIPアドレスになる。

### ポートの開放設定
ルーターの設定画面からポートの開放を行う。
私の環境では以下のような画面からポート開放が行えた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/79921a35-0142-4af2-9591-82ef6f3afc4d.png)
各設定は以下のように設定している。
 - 設定名：任意のものを設定
 - 公開する機器のIPアドレス：サーバーの固定IPアドレスを設定
 - プロトコル：TCPを選択
 - LAN側ポート番号：http向けなら80、https向けなら443
 - インターネット側ポート番号：LAN側ポート番号と同じものを設定

なお、LAN側ポート番号とインターネット側ポート番号は同じにしないとうまく開放されなかった。
私の環境だけかもしれないが、ハマりポイントとして記載しておく。

ここまできたら、ブラウザにグローバルIPを入力してみるとよい。
すると、以下のような画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/b23a76ab-2980-4acf-ae25-a781c50de3d2.png)

なお、これはapache2のデフォルトのドキュメントルートである、"/var/www/html/index.html"が表示されている。

また、ネームサーバーの変更が反映されていれば、このタイミングでFQDN（www.exampleなど）を使ったアクセスも可能であるため、試してみると良い。(なおこのタイミングではhttpsでは接続できないため要注意)

# Reactのbuild
Reactのbuildは以下の記事を参考に行った。
[【React】Reactでアプリを作りデプロイするために必要な最小限のこと](https://note.alhinc.jp/n/n23f7d406b489)
作業の流れは以下の通り。
 - package.jsonの修正
 - reactアプリのビルド
 - htaccessの追加
の流れで行った。

## package.jsonの修正
上記資料の通り、以下のように修正を行った。
```
{
  "name": "react-quiz",
  "version": "0.1.0",
  "private": true,
  "homepage": ".",
  "dependencies": {
  ...略
```

## reactアプリのビルド
デプロイするための資材をビルドする。
ブラウザはjsxやtsxを解釈することはできないため、ビルドが必須。

ビルドはターミナルに以下のコマンドを入力して行う。※npmの場合

```
npm run build
```

この結果、プロジェクトフォルダ直下のbuildフォルダ内にビルドされたファイルが出力される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/6309fbc1-e844-4c22-b003-916dd231859e.png)


## htaccessの追加
buildフォルダの中に".htaccess"ファイルを追加する。
.htaccessファイルはApacheで使用可能な設定ファイルであり、すべてのリクエストをindex.htmlにリダイレクトさせるよう設定することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/734962c7-00c6-475e-887a-0296106ac607.png)
```
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [QSA,L]
```

※なお、作成後に改めて調べたところ.htaccessはあまり使わないほうが良いのだとか。
　参照：[Apacheの.htaccessは極力使用しないこと](https://takami-hiroki.hatenablog.com/entry/20101018/p3)
　ここの設定については後ほど修正しようと思います。

# アプリのデプロイ

buildフォルダ内のファイルをapacheのドキュメントルートに配置する。
なおデフォルトのドキュメントルートは"/var/www/html/index.html"なので、
"/var/www/html/"直下にbuildフォルダ内のファイルを配置すればOK。

なお、もともと配置されているindex.htmlは念の為以下のようにバックアップを取っておく。
```
sudo mv /var/www/html/index.html /var/www/html/indexBackup.html
```

配置が完了したら、ブラウザにグローバルIPを入力する。（ネームサーバーの変更が反映されていれば、ドメイン名でもよい）
うまくいっていれば、以下のようにreactアプリが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/db36042a-61df-4d2f-a0a9-3f1d975fcbb3.png)

# URLをhttpsに変更
※以降はネームサーバーの変更が反映された状態を前提とする

単にApacheのドキュメントルートに資材を配置しただけでは、httpでしか接続できない。
しかし、現在はwebのhttps化が進み、httpsを前提とした機能も増えている。
このため、配置したwebアプリについてもhttps化する。

なお、https化は以下の流れで実施した。
 - オレオレ証明書の発行
 - Let's Encrypt

## オレオレ証明書の発行
https化には証明書の発行が必要。
かつてはこの証明書発行には有料サービスを使用するしかなかったようだが、
現在はLet's Encryptという無料のサービスを利用することができる。

ただし、今回私はLet's Encryptを使用する前に、一度オレオレ証明書（自身で発行した証明書）を使ってhttps化したあと、オレオレ証明書をLet's Encryptから発行された証明書に置き換えることでスムーズにhttps化を行うことができた。

オレオレ証明書の発行は以下記事を参考に行った。
https://qiita.com/cffnpwr/items/09995c5b19b01d7f1092

この結果、警告が表示されるもののhttps化することができた。
(CAに認証されていない証明書だと、警告が表示される)

## Let's Encryptによる認証

オレオレ証明書からLet's Encryptへの置き換えを行う。

まずLet's Encryptを使った証明書の発行は以下を参考に行った。
https://qiita.com/Disk_MJM/items/f8992fd1805d5d6dc896

発行された証明書について、
"/etc/apache2/sites-available/default-ssl.conf"の設定を書き換えて、オレオレ証明書との置き換えを行った。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/6c06a310-cd07-46dd-8742-dc88e6746774.png)

証明書の置き換えを行ったあとは、以下コマンドによりapacheを再起動して変更を反映させた。

```
systemctl restart apache2
```

これによりhttpsを使って接続できるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457280/1b2e592b-4e42-4af3-9804-80d7cd0c94db.png)

## その他設定
httpで接続した場合にhttpsにリダイレクトする設定、
及びLet's Encryptの自動更新についても対応を入れた。
（ここについても[Let's Encrypt](https://qiita.com/Disk_MJM/items/f8992fd1805d5d6dc896)を参考におこなった）