XserverでNuxt(Node.js)をホストする

## はじめに
Xserverで、Nuxtのプロジェクトをホストする方法をお伝えします。
Nuxt3でしか検証していませんが、おそらく他のNode.jsフレームワーク(Reactなど)でも動くはずです。

### Xserverとは
日本国内で提供されている人気のレンタルサーバーサービスのことです。
同様のレンタルサーバーサービス(さくらのレンタルサーバーやConoHa WINGなど)でも、似たような手順で動くと思われます。

https://www.xserver.ne.jp/

### 自分の環境
サーバー情報(ホスト名) : sv16xxx.xserver.jp, sv12xxx.xserver.jp

## node環境の構築
### 方法1 nvmを使う
複数のバージョンのNode.jsを簡単にインストールし、切り替えられるnvmというツールを使います。
一番簡単でおすすめの方法です。
#### nvmのインストール
XserverにSSHで接続し、以下のコマンドを実行します。
基本的にはユーザーのホームディレクトリ(`/home/ユーザー名`)に必要なフォルダが作成されるため、どのディレクトリで実行してもよいです。
```shell
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
```

:::note warn
[nvmのREADME.md(GitHub)](https://github.com/nvm-sh/nvm/tree/master?tab=readme-ov-file#install--update-script)でコマンドを確認して、最新のnvmをインストールしてください。
:::

下記のコマンドを実行して、バージョンが表示されたらインストール成功です。
```shell
bash # インストール後にシェルの再起動をしないと使えない(初回のみ)
nvm --version
```


#### nodeのインストール
下記のコマンドを参考に、必要なバージョンのnode.jsをインストールします。
```shell:例
nvm ls-remote #　インストール可能なバージョンを表示
nvm install node # 最新のバージョンをインストール
nvm install --lts # 最新LTSのバージョンをインストール
nvm install 14.7.0 # 特定のバージョンをインストール
```

下記のコマンドを参考に、インストールしたバージョンのnode.jsを有効化します。
```shell:例
nvm use node # 最新のバージョンを有効化
nvm use --lts # 最新のLTSバージョンを有効化
nvm use 14.7.0 # 14.7.0を有効化
```

下記のコマンドを実行して、バージョンが表示されたらインストール成功です。
```shell
node -v
```

### 方法2 直接インスール
使いたいバージョンのnodejsのバイナリファイルを直接ダウンロードします。
自分でファイルを見つけなければなりませんが、バージョン管理が不要な場合、余計なファイルは生成されません。

#### nodeのインストール
下記サイトより、インストールしたいバージョンのnode.jsを探します。
ファイル名に`linux-x64`を含むものが使えます。

https://nodejs.org/download/release/

見つけたら、ダウンロードして解凍します。
HOMEディレクトリで下記コマンドを実行してください。
※URLとファイル名は適宜書き換えてください。

```shell
wget https://nodejs.org/download/release/latest-v22.x/node-v22.15.1-linux-x64.tar.xz
tar xvf node-v22.15.1-linux-x64.tar.xz
```

続いてパスを通します。
次の内容を`.bashrc`へ追記します。
```:.bashrc
export PATH=~/node-v22.15.1-linux-x64/bin:$PATH
```

シェルを再起動し、インストールできているかを確認します。
```shell
bash
node -v
```

### 方法3 古い環境の場合
古いサーバーを利用している場合、上記2つの方法では次のようなエラーが発生して、`v16.20.2`以降のバージョンを動かすことができません。
```shell:発生するエラー
$ node -v
./node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./node)
./node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./node)
./node: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./node)
./node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by ./node)
./node: /lib64/libc.so.6: version `GLIBC_2.27' not found (required by ./node)
./node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by ./node)
./node: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by ./node)
```

理由は、サーバーに標準で入っているC言語関連のライブラリのバージョンが低いためです。
通常は[新サーバーに移行](https://www.xserver.ne.jp/manual/man_order_servertransfer_intro.php)することで、ライブラリのバージョンが上がり解決します。
しかし、一部の環境(学生プランなど)ではサーバーの移行ができません。
古いサーバーで`v16.20.2`以降を利用する場合は、次のような方法が有効です。

:::note info
[Homebrew](https://brew.sh/)を入れてgccを入れ直してみたり、nodebrewを使ってみたりもしたのですが、少なくとも私の技術ではうまく行きませんでした。
:::

#### node(unofficial)のインストール
Node.js unofficial-builds projectとは、公式には提供されていない、サポートが限定的なNode.jsのバイナリを提供する実験的なプロジェクトです。
古い環境でも使えるようなバージョンを提供しており、今回はこれを利用します。

:::note warn
利用するパッケージによっては、エラーが発生して利用できません。
例えば、`libSQL`は利用できませんでした。
:::

下記サイトより、インストールしたいバージョンのnode.jsを探します。
ファイル名に`linux-x64-glibc`を含むもののみが使えます。

https://unofficial-builds.nodejs.org/download/release/

見つけたら、ダウンロードして解凍します。
HOMEディレクトリで下記コマンドを実行してください。
※URLとファイル名は適宜書き換えてください。

```shell
wget https://unofficial-builds.nodejs.org/download/release/v20.17.0/node-v20.17.0-linux-x64-glibc-217.tar.xz
tar xvf node-v20.17.0-linux-x64-glibc-217.tar.xz 
```

続いてパスを通します。
次の内容を`.bashrc`へ追記します。
```:.bashrc
export PATH=~/node-v20.17.0-linux-x64-glibc-217/bin:$PATH
```

シェルを再起動し、インストールできているかを確認します。
```shell
bash
node -v
```

## ファイルの用意
Nuxtプロジェクトのフォルダをアップロードします。

:::note alert
場所は問わないのですが、`public_html`配下などの、直接公開される場所には置かないでください。
:::

### 方法1 Git
Gitコマンドを使い、GitHubなどから対象のリポジトリをクローンすることでコードをアップロードします。
クローンの方法は次のサイトなどを参考にしてください。

https://docs.github.com/ja/repositories/creating-and-managing-repositories/cloning-a-repository?platform=linux

### 方法2 FTP
FTPでXserverに接続して、必要なファイルをアップロードします。

:::note info
後述するビルドをローカル環境で行い、生成された`.output`フォルダだけをアップロードして使う方法もあります。
毎回手動でアップロードする手間はかかりますが、サーバーに余計なファイルを置きたくない場合はこちらがおすすめです。
:::

## ビルド
必要なパッケージをインストールしてビルドします。
```shell
cd Nuxtのrootディレクトリ
npm install
npm run build
```
`forever`という、nodeサーバーを継続的に動かすためのツールも、このタイミングでグローバルにインストールしましょう。
```shell
npm install -g forever@latest
```

## サーバー開始&停止
以下のコマンドでサーバーを開始します。
```shell
forever start .output/server/index.mjs
```
`.env`ファイルから環境変数を読み込む場合は、代わりに次のようにします。
```shell
forever start -c "node --env-file=.env" .output/server/index.mjs
```

停止などには下記のコマンドを参考にしてください。
```shell:例
forever list # 稼働中のnodeサーバー一覧を確認
forever stop id # 特定のnodeサーバーを停止(idに上のコマンドで確認したidを入れる)
forever stopall # 全てのnodeサーバーを停止
```

:::note info
メンテナンス等でサーバーが再起動された場合、nodeサーバーは自動で開始しません。
その場合は上記のコマンド(`forever start ...`)を再び実行してください。
:::

:::note info
プログラムを更新した場合は、`git pull`などでファイルを更新の上、サーバー停止→ビルド→サーバー開始の順でやり直してください。
同じポートを使って複数のnodeサーバーを立てることはできません。
:::


## ReverseProxyの設定
80、443ポートへきたアクセスをNuxtサーバーの3000番ポートへ転送するため、設定をします。
Apacheの設定フォルダをいじれる環境であれば`VirtualHost`を書き換えるのですが、Xserverではその方法が使えないため`.htaccess`で設定します。

次のような`.htaccess`ファイルを、対象ドメインの`public_html`配下に設置してください。
※環境に応じて適宜書き換えてください。
```:/home/username/example.com/public_html/.htaccess
# DirectoryIndex(index.htmlへ飛ばす機能)を無効化
DirectoryIndex disabled
# RewriteEngineを有効化
RewriteEngine On
# /配下へのアクセスをlocalhost:3000/へリバースプロキシ
RewriteRule ^(.*)$ http://localhost:3000/$1 [P,L,QSA]
RewriteRule ^$ http://localhost:3000/ [P,L,QSA]
# バックエンドサーバーが必要とする場合にHostヘッダーを設定
RequestHeader set Host localhost:3000
# Locationヘッダーの修正（ProxyPassReverseの代替）
Header edit Location ^http://localhost:3000/(.*) https://example.com/$1
```

:::note info
Nuxtはデフォルトで3000番ポートにて稼働しますが、環境変数にPORTを指定するとポートを変更できます。
その場合は、`.htaccess`も書き換えてください。
:::

:::note info
baseURLを変更する場合(`http://localhost/sub/`などがルートになる)、`nuxt.config.ts`を設定した上で、`.htaccess`を次のようにします。
対象ドメインの`public_html`の対象ディレクトリ配下に設置してください。
※環境に応じて適宜書き換えてください。
```:/home/username/example.com/public_html/sub/.htaccess
# DirectoryIndex(index.htmlへ飛ばす機能)を無効化
DirectoryIndex disabled
# RewriteEngineを有効化
RewriteEngine On
# /sub/配下へのアクセスをlocalhost:3000/sub/へリバースプロキシ
RewriteRule ^(.*)$ http://localhost:3000/sub/$1 [P,L,QSA]
RewriteRule ^$ http://localhost:3000/sub/ [P,L,QSA]
# バックエンドサーバーが必要とする場合にHostヘッダーを設定
RequestHeader set Host localhost:3000
# Locationヘッダーの修正（ProxyPassReverseの代替）
Header edit Location ^http://localhost:3000/sub/(.*) https://example.com/sub/$1
```
:::

## 終わりに
これで、`.htaccess`を設置したURLにアクセスすれば、Nuxtで作成したサイトにアクセスできるはずです。

## 参考

https://laboradian.com/install-nodejs-on-xserver/

https://github.com/nvm-sh/nvm

https://qiita.com/unused/items/f741e4bebfb6b6d470dc

https://www.taneyats.com/entry/nodejs-forever

https://www-creators.com/archives/248

https://stackoverflow.com/questions/12808506/can-proxypass-and-proxypassreverse-work-in-htaccess

https://qiita.com/niwasawa/items/ed605542685a8c00e0ad

https://github.com/nodejs/unofficial-builds/

https://nodejs.org/