注意
本記事のコマンドは Ubuntu 24.04 LTS で検証しています。VPS(Vultr・ConoHa等)での本番運用を想定しています。バージョンが異なると手順が変わる場合があります。
「Next.js をローカルで動かすのは簡単なのに、Ubuntu のサーバーに本番デプロイすると詰まる」——そんな経験はありませんか。
PM2(プロセスマネージャー)+Nginx(リバースプロキシ)+Let’s Encrypt(SSL)の組み合わせが、Next.js の本番運用で最もよく使われる構成です。
本記事では、Ubuntu 24.04 LTS 上で Next.js アプリを本番公開するまでの全手順を、実際にコンテナで動かした実測データとともに解説します。
Node.js v20.20.2、PM2 7.0.1、nginx 1.24.0(Ubuntu 24.04 時点)での検証結果を載せています。

この記事のポイント
- Ubuntu 24.04 に Node.js 20.x は
NodeSourceリポジトリ経由でインストールする(デフォルトリポジトリのバージョンは古い) - PM2 の
ecosystem.config.jsでアプリを管理し、pm2 startupでサーバー再起動時の自動復帰を設定する - Nginx はリバースプロキシとして
proxy_pass http://localhost:3000で Next.js へ転送する - certbot 2.9.0 + python3-certbot-nginx で Let’s Encrypt SSL を自動取得・自動更新できる
- SSH 接続は ed25519 鍵(OpenSSH 9.6p1)が推奨
目次
- 前提環境・必要なもの
- 手順1:VPS に SSH で接続する
- 手順2:Node.js 20.x をインストールする
- 手順3:Next.js アプリをサーバーに配置・ビルドする
- 手順4:PM2 でプロセス管理する
- 手順5:Nginx でリバースプロキシを設定する
- 手順6:certbot で SSL 証明書を取得する
- よくあるエラーと解決策
- まとめ
前提環境・必要なもの
この記事で使う構成は以下のとおりです。
| 項目 | 内容 |
|---|---|
| OS | Ubuntu 24.04 LTS(VPS 上) |
| Node.js | v20.20.2(NodeSource 経由) |
| PM2 | 7.0.1 |
| Nginx | 1.24.0 (Ubuntu) |
| certbot | 2.9.0-1 |
| 必要なもの | VPS(推奨: Vultr 東京リージョン)、独自ドメイン(SSL に必要) |
手順1:VPS に SSH で接続する
①SSH 鍵を生成する
VPS への接続にはパスワード認証ではなく SSH 公開鍵認証 を使います。Ubuntu 24.04 では OpenSSH 9.6p1 が動作します。ed25519 タイプの鍵を生成してください。

OpenSSH_9.6p1 Ubuntu-3ubuntu13.16, OpenSSL 3.0.13 30 Jan 2024
$ ssh-keygen -t ed25519 -C “ubuntu@your-vps”
Generating public/private ed25519 key pair.
Your identification has been saved in ~/.ssh/id_ed25519
Your public key has been saved in ~/.ssh/id_ed25519.pub
$ ssh-keygen -lf ~/.ssh/id_ed25519.pub
256 SHA256:GDjyXpLRpRtJyvwYVYekloC85ntO2HoBaq25RGxWP4s ubuntu@your-vps (ED25519)
上の出力は ubuntu:24.04 コンテナで実際に ssh-keygen を動かした結果です。ssh -V で OpenSSH_9.6p1 が確認でき、ssh-keygen -lf で生成した鍵のフィンガープリント(SHA256:GDjy…WP4s)まで取得できました。256 は鍵長が 256bit であることを示します。
②VPS に公開鍵を登録して接続する
Number of key(s) added: 1
Now try logging into the machine, with: “ssh ubuntu@YOUR_VPS_IP”
$ ssh ubuntu@YOUR_VPS_IP
Welcome to Ubuntu 24.04.1 LTS
セキュリティ
SSH 接続できることを確認したら、/etc/ssh/sshd_config で PasswordAuthentication no を設定してパスワード認証を無効にしてください。総当たり攻撃の対策として重要です。
手順2:Node.js 20.x をインストールする
Ubuntu 24.04 のデフォルトリポジトリの Node.js はバージョンが古い場合があります。NodeSource 公式の setup スクリプトを使って最新の Node.js 20.x をインストールしてください。
Reading package lists… Done
$ sudo apt install -y curl ca-certificates
$ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash –
Get:1 https://deb.nodesource.com/node_20.x nodistro InRelease [12.1 kB]
Get:2 https://deb.nodesource.com/node_20.x nodistro/main Packages [14.6 kB]
$ sudo apt install -y nodejs
$ node –version
v20.20.2
$ npm –version
10.8.2
これは docker run --rm ubuntu:24.04 で NodeSource の setup_20.x を実際に流して取得した結果です(2026-06-14 時点)。Node.js は v20.20.2、npm は 10.8.2 が入りました。Ubuntu 標準リポジトリの nodejs ではなく NodeSource を使うのがポイントで、これで Node.js 20 系の最新パッチが入ります。
手順3:Next.js アプリをサーバーに配置・ビルドする
①アプリをサーバーへ転送する
ローカルで開発した Next.js プロジェクトを VPS にアップロードします。git を使う方法が最も一般的です。
$ cd /home/ubuntu
$ git clone https://github.com/yourname/my-next-app.git
Cloning into ‘my-next-app’…
done.
$ cd my-next-app
$ npm install
added 450 packages in 38s
②本番ビルドを実行する
▲ Next.js(プロジェクトのバージョン)
✓ Compiled successfully
Route (app) Size First Load JS
┌ ○ / … …
✓ Generating static pages
$ npm run start
– Local: http://localhost:3000
✓ Ready
上はビルド出力のイメージです(ビルド時間や Route のサイズはアプリの中身で変わるので伏せています)。http://localhost:3000 でアクセスできれば Next.js の起動は成功です。ただし、このままでは Ctrl+C でサーバーが止まります。次の手順で PM2 を使って常時起動させます。
手順4:PM2 でプロセス管理する
PM2 は Node.js プロセスを常時起動・自動再起動・ログ管理してくれるプロセスマネージャーです。本番サーバーでは必須のツールです。
①PM2 をインストールする
added 90 packages in 52s
$ pm2 –version
7.0.1
②ecosystem.config.js を作成する
アプリのルートディレクトリに ecosystem.config.js を作成します。コマンドで直接起動するより、設定ファイルで管理する方が後から変更が楽です。

module.exports = {
apps: [{
name: ‘nextjs-app’,
script: ‘node_modules/.bin/next’,
args: ‘start -p 3000’,
cwd: ‘/home/ubuntu/my-next-app’,
instances: 1,
autorestart: true,
max_memory_restart: ‘400M’,
env: {
NODE_ENV: ‘production’,
PORT: 3000,
},
}],
};
EOF
③PM2 でアプリを起動し、自動起動を設定する
[PM2] App [nextjs-app] launched (1 instances)
│ 0 │ nextjs-app │ cluster │ online │ 0% │ 42.0mb │
$ pm2 list # name=nextjs-app status=online mode=cluster
nextjs-app online restarts=0 mode=cluster_mode
$ curl -s http://localhost:3000
Hello from Next.js app on Ubuntu 24.04 (managed by PM2)
$ pm2 save
[PM2] Successfully saved in ~/.pm2/dump.pm2
これは ubuntu:24.04 コンテナで実際に PM2 でアプリを常駐させ、curl http://localhost:3000 で応答が返ることまで確認した実測ログです。ここでひとつ発見があります。ecosystem.config.js で instances を指定すると、PM2 はアプリを fork ではなく cluster モードで起動します(実測で mode=cluster_mode を確認)。常駐後のメモリは 42.0mb でした。
cluster モードの注意点
cluster モードは Node.js の cluster モジュールでプロセスを多重化する仕組みです。server.js のような素の Node サーバーなら問題なく動きますが、script: 'node_modules/.bin/next' のように 実行ファイル(バイナリ)を直接指定すると cluster 化に失敗することがあります。Next.js を next start で動かす場合は exec_mode: 'fork' を明示するか、instances を外して fork モードにするのが安全です。
④pm2 startup でサーバー再起動時の自動復帰を設定する
pm2 save で現在のプロセス一覧を保存したら、サーバー再起動後も自動で立ち上がるように pm2 startup を実行します。
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu –hp /home/ubuntu
$ # 表示されたコマンドをそのままコピーして実行する
手順5:Nginx でリバースプロキシを設定する
Nginx をリバースプロキシとして使い、外部からの HTTP/HTTPS リクエストを PM2 が動かす Next.js(ポート 3000)に転送します。
①Nginx をインストールする
Setting up nginx (1.24.0-2ubuntu7.11) …
$ nginx -v
nginx version: nginx/1.24.0 (Ubuntu)
$ sudo systemctl enable –now nginx
Synchronizing state of nginx.service with SysV service script
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service
②リバースプロキシ設定ファイルを作成する

以下の内容を貼り付けます。example.com は自分のドメインに変更してください。
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
③設定を有効化してテストする
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl restart nginx
$ sudo systemctl status nginx
Active: active (running)
nginx -t の「test is successful」は ubuntu:24.04 上でこの設定を書いて実際に確認した出力です(nginx は 1.24.0-2ubuntu7.11)。この時点で、http://example.com(ドメインを VPS の IP に向けた状態)にアクセスすると Next.js のページが表示されるはずです。
手順6:certbot で SSL 証明書を取得する
Let’s Encrypt の無料 SSL 証明書を certbot で取得します。certbot 2.9.0-1 と python3-certbot-nginx が Ubuntu 24.04 で利用可能です(apt-cache 実確認済み)。

下のコマンドのうち apt install certbot python3-certbot-nginx の部分は ubuntu:24.04 で候補バージョン(どちらも 2.9.0-1)を実測確認済みです。一方、certbot --nginx による証明書の発行は 実在のドメインと DNS 設定が必要なため、以下は取得が成功したときの出力例です。
Setting up certbot (2.9.0-1) …
Setting up python3-certbot-nginx (2.9.0-1) …
$ sudo certbot –nginx -d example.com -d www.example.com # 出力例
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
Congratulations! You have successfully enabled HTTPS on https://example.com
SSL 自動更新の確認
- certbot は systemd タイマーで証明書を自動更新します
sudo certbot renew --dry-runで更新のテストができます- Let’s Encrypt 証明書の有効期限は 90 日間です
④UFW(ファイアウォール)で HTTPS を許可する
Rule added
$ sudo ufw delete allow ‘Nginx HTTP’
$ sudo ufw status
Status: active
To Action From
Nginx Full ALLOW Anywhere
OpenSSH ALLOW Anywhere
よくあるエラーと解決策
①「502 Bad Gateway」が出る
Nginx が Next.js(ポート 3000)に繋がっていないことが原因です。
# nextjs-app が “online” か確認
$ curl http://localhost:3000
# 直接アクセスして応答があるか確認
$ pm2 logs nextjs-app
# エラーログを確認
②PM2 が再起動後に起動しない
pm2 save と pm2 startup のどちらかが抜けているケースがほとんどです。
[PM2] Successfully saved in /home/ubuntu/.pm2/dump.pm2
$ sudo systemctl enable pm2-ubuntu
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-ubuntu.service
③nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
# ポート80を使っているプロセスを確認
$ sudo systemctl stop apache2 2>/dev/null || true
$ sudo systemctl restart nginx
Apache2 が先に起動していることがよくある原因です。
④npm run build でメモリ不足エラー
1GB RAM の VPS では Next.js のビルドが失敗することがあります。
# または swap を追加する
$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile && sudo swapon /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
まとめ
Ubuntu 24.04 に Next.js を本番デプロイする手順を解説しました。
- Node.js 20.x は NodeSource リポジトリ経由でインストール(
v20.20.2/ npm10.8.2を実測確認) - PM2 7.0.1 で
ecosystem.config.jsを使ったプロセス管理 +pm2 startupで自動起動。instances指定時は cluster モードで起動する点に注意 - nginx 1.24.0 でリバースプロキシを設定し、
nginx -tで設定テストが成功することを実測確認 - certbot 2.9.0-1 / python3-certbot-nginx 2.9.0-1 が apt で導入可能なことを実測確認(証明書発行には独自ドメインが必要)
- SSH 接続は OpenSSH 9.6p1 + ed25519 鍵を使用(フィンガープリントまで実測)
本番運用には RAM 2GB 以上の VPS が安定します。VPS の選び方・速度比較もあわせて参考にしてください。



コメント