Ubuntu ServerにNuxt.jsアプリケーションをSPAモードでデプロイ

### 到達目標

- Digital oceanでUbuntu ServerのDropret(サーバーインスタンス)を立ち上げたなど、Ubuntu Server環境にホスティングするための手順を検証する
- Nuxt.jsプロジェクトはtargetが'static'で、modeは'SPA'の状態を前提としています。いわゆるSSR,SSGのデプロイは行いません。



### サーバーにアクセスする

#### SSHクライアント

- ぼくは、PuTTY(windows)というSSHクライアントを利用しました。付属のPuTTYgenというツールでsshkeyを作成して、Dropretを作成する際に公開鍵を登録しました。ログイン方法はパスワードでも大丈夫です。

#### 初期設定

- ユーザ作成

```
// ユーザ作成、passwordがないと進めない感じだった
$ adduser webapp

// sudoグループに所属させる
$ usermod -aG sudo webapp

// passwordなしでsudoできるように以下の設定を書き換える。
$ visudo
%sudo ALL(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) NOPASSWD:ALL

// 作ったユーザでSSH鍵でログインできるようにする
$ rsync -a --chown=webapp:webapp ~/.ssh /home/webapp

// 一旦rootではなく作成したユーザでログインしなおす。

// rootユーザのログインを禁止する
$ sudo vi /etc/ssh/sshd_config
#PermitRootLogin yes
PermitRootLogin no

// sshを再起動する
$ sudo systemctl restart ssh
```

- ファイアウォールの有効化

```
$ sudo ufw app list
$ sudo ufw allow OpenSSH
$ sudo ufw enable
$ sudo ufw status
```

- node.jsをインストールする。[こちら](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-ja)のオプション2を参考にしました。

```
$ sudo apt update
$ sudo apt -y upgrade

$ cd ~
// 現在のLTS版をインストールするスクリプトをとってくる
$ curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh
// 一度curlしたファイルの中身を確認する。
$ vi nodesource_setup.sh 
// 実行
$ sudo bash nodesource_setup.sh
$ sudo apt install nodejs
$ node -v
>>> v16.14.0
```

- 警告が出たのでnpmをアップデートしました。

```
$ sudo npm install -g npm@8.5.3
```



### Nuxt.jsプロジェクトの静的デプロイ

- ソースコードをcloneする

```
$ mkdir ~/src
$ cd ~/src
// 公開鍵を生成させてGithubに登録する
$ ssh-keygen -t rsa -b 4096
// 表示された公開鍵をGithubのSettings>SSH and GPG keysに登録
$ less ~/.ssh/id_rsa.pub

$ git clone git@github.com:...
```

- axiosモジュールを使っている場合

```
// nuxt.config.js
  axios: {
    baseURL:  'http://localhost:8000/', ここを変更しておく
    timeout: 10000,
    headers: {
      "Content-Type": "application/json",
      "X-Requested-With": "XMLHttpRequest",
    },
  },
```



- package.jsonに従って依存パッケージをインストールする

```
$ npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
以上のようなエラーがでた場合
--forceか--legacy-peer-depsオプションをつけるとよいようです。https://chusotsu-program.com/npm-install-resolve-error/

$ npm install --legacy-peer-deps
```

- [こちら](https://nuxtjs.org/docs/get-started/commands/)を参考に静的デプロイ用の/distディレクトリを生成させる

```
$ cd project(cloneしてきた)
$ npm run generate
// yarnを使っているならyarn generate
$ ls
>>> /dist ....
// distが生成されていたら成功
```



### Nginxのインストールと設定

- /distディレクトリを配信用ディレクトリに移動させる

```
$ sudo cp -r ./dist /var/www/frontend
```

- Nginxのインストール

```
sudo apt install -y nginx
```

- Nginxの設定

```
$ sudo vi /etc/nginx/sites-available/frontend

server {
	listen 80;
	server_name xxx.xxx.xx.xx; # ホスト名またはIPアドレス
	
	location / {
		root /var/www/frontend;
	}
}
```

- 作成したファイルへのシンボリックリンクを作成

```
$ sudo ln -s /etc/nginx/sites-available/frontend /etc/nginx/sites-enabled/
// デフォルトの設定を削除
$ sudo unlink /etc/nginx/sites-enabled/default
```

-  設定ファイルのシンタックスを確認

```
$ sudo nginx -t
```

- Nginxをリロード

```
$ sudo systemctl reload nginx
```

- ポート80番を開ける

```
$ sudo ufw allow 'Nginx Full'
```

- 一度ここでブラウザから確認してみましょう。



### SSL化する

- Let's Encryptを使ってSSL化させる

- ドメインを取得しておく。お名前ドットコムであれば、1年間でも1円程度でドメインを取得できるのでおすすめです。
- ドメインとIPアドレスをDNSの設定で紐づける。[こちらの記事のDNSレコートの事前移行の章](https://qiita.com/ysKey2/items/0545e13ec05def42ad55#dns%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E4%BA%8B%E5%89%8D%E7%A7%BB%E8%A1%8C)にやり方が書いてあります。
- Nginxの設定を行う

```
$ sudo vi /etc/nginx/sites-availble/frontend

server {
	listen 80;
	server_name "hostname"; 取得したドメインに変更
	...
}

# sudo nginx -t
# sudo systemctl reload nginx
```

- webrootの設定を追加
- Let's Encryptに関してはhttps://free-ssl.jp/usage/ で丁寧に使い方が載っています。

```
$ sudo mkdir -p /var/www/letsencrypt
$ sudo chown webapp:www-data /var/www/letsencrypt
$ sudo vi /etc/nginx/sites-available/frontend

server {
	...
	location ^~ /.well-known/acme-challenge/ {
		allow all;
		root /var/www/letsencrypt/;
		default_type "text/plain";
		try_files $uri =404; 
	}
	...
}

$ sudo nginx -t
$ sudo systemctl restart nginx
```

- certbotのインストール

```
$ sudo apt -y install certbot
certbotからSSL/TLS証明書発行の申請を送る。--webrootプラグインから-wオプションでwebrootのパスを指定する。webrootにはワンタイムトークンがある

# sudo certbot certonly --webroot -w /var/www/letsencrypt -d "hostname"
emailアドレスと同意確認をチェックしてCongratulationsが表示されると成功

# sudo ls -al /etc/letsencrypt/live/"hostname"
を確認すると証明書が入っている
total 12
drwxr-xr-x 2 root root 4096 Mar  6 04:49 .
drwx------ 3 root root 4096 Mar  6 04:49 ..
-rw-r--r-- 1 root root  692 Mar  6 04:49 README
lrwxrwxrwx 1 root root   51 Mar  6 04:49 cert.pem -> ../../archive/hostname/cert1.pem
lrwxrwxrwx 1 root root   52 Mar  6 04:49 chain.pem -> ../../archive/hostname/chain1.pem
lrwxrwxrwx 1 root root   56 Mar  6 04:49 fullchain.pem -> ../../archive/hostname/fullchain1.pem
lrwxrwxrwx 1 root root   54 Mar  6 04:49 privkey.pem -> ../../archive/hostname/privkey1.pem
```

- Nginxの設定を変更

```
server {
	listen 443 ssl;
	server_name "hostname";
	ssl_certificate	/etc/letsencrypt/live/hostname/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/hostname/privkey.pem;
	
	...
	
}
// httpの場合リダイレクトさせる
server {
	listen 80 default_server;
	server_name _;
	return 301 https://hostname$request_uri;
}
```

- Nginxをリロードさせて動作確認ができれば完了です

```
$ sudo nginx -t
$ sudo systemctl relaod nginx
```