エックスサーバーでNode.jsをインストールしてNestJSのREST APIをデプロイする方法
はじめに
Xserverは日本国内で人気の高いレンタルサーバーですが、標準ではNode.jsをサポートしていません。しかし、適切な設定を行えば、Xserver上でもNode.jsアプリケーションを動作させることが可能です。
本記事では、XserverにNode.jsをインストールし、NestJSで構築したREST API(データベースとやり取りするToDoリストのバックエンド)をデプロイする手順を解説します。
今回はSSR(サーバーサイドレンダリング)は使用せず、REST APIのみのシンプルなNestJSアプリケーションを対象とします。
想定する環境
- Xserverのスタンダードプラン(旧サーバー)
- APIはサブドメイン(例: api.example.com)で公開
- Node.jsのバージョン<v16.20.2>:新サーバーへの移行が完了している場合、新しいNode.jsを利用できるそうですが、今回は旧サーバーで動作確認されているバージョン※Xserverのシステムライブラリの制約により、Node.js v18以降を使用するとエラーが発生するため(古い環境ではglibcのバージョン不足によりNode.js 18+が動作しません)。
XserverへのNode.jsインストール
まずはXserverサーバー上でNode.jsを利用できるよう、Node.js本体をインストールします。
XserverではデフォルトでNode.jsが使えないため、自身のアカウント環境にNode.jsを導入する必要があります。
ここでは nodebrew というNode.jsのバージョン管理ツールを使用して環境構築を行います。
以下の手順でセットアップしましょう。
-
SSHでXserverに接続します。
XserverのサーバーパネルでSSH接続を有効にし、発行されたホスト名・ユーザー名でターミナルからログインしてください。XserverのSSH設定。 -
Nodebrewをインストールします。
SSH接続した先のターミナル上で次のコマンドを実行し、nodebrew本体をセットアップします。$ curl -L git.io/nodebrew | perl - setup
-
Nodebrewのパスを通します。 Nodebrewをインストールするとホームディレクトリに.nodebrewフォルダが作成されます。これを利用するため、シェルの設定ファイルにパスを追記します。上記でファイルを開いたら、以下の行を末尾に追加して保存します。
$ vi ~/.bash_profile # エディタでプロファイルを開く
viエディタの操作方法変更を保存したら、次のコマンドで設定を反映させます。export PATH=$HOME/.nodebrew/current/bin:$PATH
$ source ~/.bash_profile
- Node.js本体をインストールします。 現在Xserverで動作が確認されているバージョンである v16.20.2 をインストールします。nodebrewを使うことで、必要なNode.jsバイナリを自動でダウンロードして展開してくれます。
$ nodebrew install-binary v16.20.2
- インストールしたバージョンを有効化します。 Node.js v16.20.2 のインストールが完了したら、以下のコマンドでそのバージョンを利用するよう切り替えます 。
$ nodebrew use v16.20.2
- インストール確認を行います。 念のため、nodeおよびnpmコマンドのバージョンを表示して正しくインストールできたか確認しましょう 。上記のように、それぞれバージョン番号が表示されればOKです。
$ node -v v16.20.2 $ npm -v 8.19.4 # npmのバージョン番号が表示される
※注意: Xserverの旧サーバー環境では、Node.js v16.20.2より新しいバージョンをインストールして実行しようとすると、GLIBC_2.27やGLIBC_2.28が見つからないといったエラーが発生する可能性があります。これはサーバー側のシステムライブラリ(glibc)が新しいNode.jsの要求バージョンに追いついていないためです。そのため旧サーバーのXserver上で動かすNode.jsはv16系(16.20.2が最新版)に留めておきましょう。開発マシンでもプロジェクト直下に**.node-version**ファイルを置くなどしてNode.jsのバージョンを合わせ(v16.20.2に固定)ておくと、デプロイ時に環境差異による不具合を防げるでしょう。新サーバーでは新しいバージョンを利用できるそうですが、こちらは未確認です。
※viの操作方法
viエディタで設定ファイルを編集する際の基本操作は以下の通りです。
-
ファイルを開く
vi ~/.bash_profile
-
編集モードに入る
キーボードでi
を押すと「挿入モード」になり、テキストを入力・編集できます。 -
追記する
末尾までカーソルを移動し、必要な行(例:export PATH=...
)を入力します。 -
編集を保存して終了する
Esc
キーを押して挿入モードを終了し、:wq
と入力して Enter を押すと保存してviを終了します。
NestJSプロジェクトの準備
次に、デプロイするNestJSのプロジェクトをローカル環境で用意しましょう。今回は例として、データベース連携のあるToDoリスト管理用のREST APIをNestJSで実装したプロジェクトが手元にあるものとします(Nest CLIのnest newコマンドなどであらかじめプロジェクトを作成しておいてください)。サーバーサイドレンダリングは使用しない純粋なREST APIですので、基本的にはクライアントからのHTTPリクエストを受け取り、データベース操作を行ってJSONでレスポンスを返すようなエンドポイント群が含まれているはずです。
ここで、デプロイ後のURL構成を分かりやすくするために、グローバルプレフィックスを設定しておくことをおすすめします。グローバルプレフィックスとは、アプリ内のすべてのルートURLに共通の接頭辞を付与する機能です。例えばプレフィックスに 'api' を設定すると、エンドポイントのパスが一律に/api/から始まるようになります。これにより、将来的に同じドメインでフロントエンドの静的コンテンツや別のサービスを運用する場合でも、URLの衝突を避けつつAPIへのリクエストだけを明確に切り分けることができます。
NestJSプロジェクトのエントリポイントである main.ts を開き、以下のようにグローバルプレフィックスを設定してください。
// main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// グローバルプレフィックスを設定
app.setGlobalPrefix('api');
await app.listen(3000);
}
上記のように設定することで、例えばローカル開発環境では http://localhost:3000/api/ 以下がすべてAPIエンドポイントとなります。今回はapiというプレフィックスを付けましたが、必要に応じて任意の文字列に変更可能です。また、コード中の app.listen(3000) により、NestJSサーバーがポート3000で待ち受けるようにしています。このポート番号は後ほど行うXserver側のプロキシ設定で使用するので覚えておきましょう(デフォルトのまま特に変更しなければ3000で問題ありません)。
NestJSアプリのビルド(ローカル環境)
プロジェクトの準備ができたら、本番環境にアップロードする前にNestJSアプリをビルドします。NestJSは内部でTypeScriptを使用しているため、デプロイ前にJavaScriptへコンパイルする必要があります。以下の手順をローカル開発環境で実施してください。
-
依存パッケージのインストール: プロジェクト直下で npm の依存関係をインストールします(まだ実行していない場合)。
$ npm install
-
プロジェクトのビルド: ビルド用スクリプトを実行し、TypeScriptのコードをコンパイルします 。デフォルトでは Nest CLI が用意するスクリプト npm run build により、TypeScriptコンパイラ(tsc)が走ります。
$ npm run build
上述のコマンドにより、dist/ ディレクトリ以下にコンパイル後のJavaScriptファイル群(NestJSアプリの本番実行用コード)が出力されます 。同時に、プロジェクトには node_modules/ ディレクトリも存在しているはずです(開発時点でインストール済みの依存ライブラリ類)。Xserver側にデプロイする際は、この dist/ ディレクトリと node_modules/ ディレクトリが必要になります。ビルドが正常に完了し、必要なファイルが揃っていることを確認しましょう。
Xserverへのファイルアップロードと配置
ビルド済みのNestJSアプリをXserverに配置していきます。XserverではFTPやファイルマネージャー、SCPなどを使ってファイルをアップロードできますが、ここではフォルダ構成と配置場所の考え方について説明します。
まず、バックエンド用のファイルを置くディレクトリをXserver上に用意します。今回は例としてドメインexample.comに対し、サブドメインapi.example.comを追加してAPIエンドポイントを公開するケースを想定します。
続いて、公開ディレクトリではない場所にバックエンド用のコードを配置します。具体的には、先ほどのexample.comディレクトリ直下(public_htmlと同じ階層)に、例えばtodo-apiといった任意の名前のディレクトリを新規作成してください。このディレクトリに、ローカルでビルドしたNestJSアプリの dist/フォルダ と node_modules/フォルダ をアップロードします。アップロード方法は問いません(FTPクライアントでファイルを転送する、Xserverの提供するファイルマネージャーでZIPファイルをアップロードして展開する、GitHub Actionsを利用する…等、ご自身のやりやすい方法で構いません)。ポイントは、サーバーサイドのコード一式をサブドメインの公開ディレクトリではなく、その外側に置くという点です。
重要なポイント
バックエンドのソースコードや機密情報を含むファイルは、絶対に公開ディレクトリ(public_html配下)に配置しないでください 。公開ディレクトリに置かれたファイルはWebブラウザから直接アクセス可能となり、データベース接続情報やサーバーサイドの処理ロジックが外部に露出してしまう危険があります 。本手順では、example.com/todo-api/ 以下にバックエンドコードを置くことで、直接URLでアクセスされない安全な場所に配置しています。同様に、もし環境変数を記載した設定ファイル(例えば .env 等)がある場合も、公開ディレクトリではなくこのバックエンド用ディレクトリにアップロードしておきましょう。
リバースプロキシの設定(Apacheの.htaccess)
ファイルを配置しただけでは、ブラウザからこのNestJSアプリにアクセスすることはできません。XserverのWebサーバーはApacheが担っているため、Apache経由でNestJS(Node.js)にリクエストを中継する設定を行う必要があります。これにはリバースプロキシという仕組みを利用します。リバースプロキシを設定することで、特定のURLへのアクセスを内部で別のサーバー(ここではNestJSアプリ)へ転送できます。
設定はサブドメイン側で行います。先ほど作成したサブドメインapi.example.comの公開ディレクトリ(例: /home/ユーザー名/example.com/public_html/api/)に移動し、ここに .htaccess ファイルを作成してください。その中に次の内容を記述します。
RewriteEngine On
APIリクエストをバックエンドサーバーにプロキシ
RewriteRule ^api/(.*)$ http://localhost:3000/api/$1 [P,L]
上記の設定により、https://api.example.com/api/... というパスで来たHTTPリクエストはすべて、Apacheから内部の http://localhost:3000/api/... に転送されるようになります 。つまり、クライアント(ブラウザ)から見るとapi.example.com上でAPIが提供されているように見えますが、実際の処理はXserver内で起動しているNestJS(Node.js)サーバー(ポート3000番)が担当する形になります。ここで指定した [P] フラグは Proxy(プロキシ経由で転送) を意味し、[L] フラグは以降のRewriteルールを適用しないことを示すものです。
※上記ではグローバルプレフィックスとしてapiを付与した前提でRewriteRuleを記述しています。もしプレフィックスを変更している場合や、特定のパスだけをプロキシしたい場合は、RewriteRule中のパス部分(^api/(.*)$ の部分)を適宜変更してください。また、localhost:3000 の部分はNode.jsアプリを起動するポート番号と合わせる必要があります。今回はNestJSをポート3000で起動するため3000と記載していますが、別のポートを使用する場合は同様に書き換えてください。
NestJSアプリの起動
いよいよXserver上でNestJSアプリケーションを起動します。前準備として、リバースプロキシの設定まで完了した状態で進めます。
まずSSHでXserverに接続し、先ほどバックエンド用ファイルをアップロードしたディレクトリ(例: /home/ユーザー名/example.com/todo-api/)に移動します 。そこで以下のコマンドを実行し、NestJSサーバーをバックグラウンドではなくフォアグラウンドで一旦起動します 。
$ node dist/main.js
こちらのコマンドは、コンパイル済みのNestJSアプリを直接起動しています。dist/直下にmain.jsファイルがある場合の例です(プロジェクト構成によってはパスが異なる可能性があります。例えばdist/src/main.jsのようになっている場合はその実際のパスに読み替えてください)。コマンドを実行すると、現在のターミナルセッション上でNestJSアプリが起動し、Xserver内の localhost:3000 ポートでリクエストの待受を開始します。
この状態で、新たにブラウザからAPIエンドポイントにアクセスして動作確認を行いましょう。今回設定したエンドポイントは https://api.example.com/api/ 以下です。例えば、デフォルトのNestJSプロジェクトではGETリクエストに対して "Hello World!" という文字列を返すシンプルなエンドポイントが用意されています。適切にセットアップできていれば、ブラウザで https://api.example.com/api/ にアクセスすることで、“Hello World!”と表示されます。
表示が確認できれば、NestJSによるAPIサーバーがXserver上で正常に動作していることになります。
しかし現状では、このNode.jsプロセスはSSHセッションに紐づいて動いているため、ターミナルを閉じたり接続が切れたりするとサーバーも停止してしまいます。次に、Node.jsアプリをサーバー上で常駐実行させ、SSHから切断した後も動かし続ける方法を説明します。
PM2によるプロセスの常駐化(オプション)
本番環境でサービスとしてNestJSアプリを稼働させるには、SSHから独立してプロセスを常駐化する必要があります。そこで便利なのが PM2 と呼ばれるプロセスマネージャーです。PM2を使用すると、Node.jsアプリケーションをデーモン(バックグラウンドプロセス)として起動でき、サーバーを24時間稼働させたり、予期せぬエラー発生時に自動再起動させたりすることが容易になります  。
それでは、PM2を使ってNestJSアプリを常駐化してみましょう。
-
PM2のインストール: npmを使ってPM2をインストールします(グローバルオプション-gを付けておくと任意の場所でコマンドを利用できて便利です)。
$ npm install -g pm2
-
アプリのバックグラウンド起動: PM2経由でNestJSアプリを起動します。先ほどと同じディレクトリにいることを確認し、以下のコマンドを実行してください。
$ pm2 start dist/main.js
これでプロセス管理下でアプリが起動しました。SSHセッションを閉じてもNestJSサーバーが継続して動作し続けるようになります 。
PM2を導入するメリット
- 常時稼働: SSH接続を切断してもアプリケーションがバックグラウンドで動き続けます。
- 自動再起動: クラッシュや予期せぬエラーが発生した場合でも、PM2がプロセスを自動的に再起動して復旧してくれます。
-
ログ管理: アプリの標準出力・エラー出力ログをPM2経由で閲覧・管理できます(
pm2 logs
コマンドでリアルタイムログ確認などが可能)。 -
パフォーマンス監視: CPU使用率やメモリ消費量など、稼働中のプロセスのリソース状況をモニタリングできます(
pm2 monit
コマンドで確認可能)。
PM2で起動したプロセスは、pm2 list
やpm2 status
で一覧表示でき、pm2 stop <ID>
やpm2 restart <ID>
で停止・再起動ができます。またサーバー自体の再起動時にもPM2がプロセスを自動復旧してくれるため、長期間稼働させるサービスに適しています。
おわりに
以上、Xserver上でNode.js環境を構築し、NestJS製のREST APIをデプロイして動かすまでの手順を解説しました。
共有レンタルサーバーであるXserverでも工夫次第でNode.jsアプリケーションを稼働させることが可能です。初めての方はSSH操作やサーバー設定に戸惑うかもしれませんが、一つひとつ手順を踏めば確実に動作させられるので、ぜひ挑戦してみてください。
ただし、公式でサポートされている方法ではないことを念頭に置き、自己責任で実行するようお願いします。
今回扱った方法は比較的軽量なAPIサービスを念頭に置いた構成です。より大規模なトラフィックが予想される場合や最新のNode.jsバージョンを使いたい場合は、Xserverの新しい基盤環境(Rocky Linux 8系)への移行や、専用サーバー・VPSの利用、もしくはAWSなどのクラウドサービスの利用も検討してみてください。
まずは身近なXserverで手軽にバックエンドサービスを構築し、レンタルサーバーでNode.jsアプリを動かす感触を掴んでみてください。お疲れさまでした!
Discussion